Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

CompressPsf.C

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include "CompressPsf.h"
00003 #include "strlib.h"
00004 #include "Molecule.h"
00005 #include "Parameters.h"
00006 #include "SimParameters.h"
00007 #include "InfoStream.h"
00008 #include "UniqueSet.h"
00009 #include "UniqueSetIter.h"
00010 
00011 
00030 //global variables recording compressed psf file information
00031 Molecule *g_mol = NULL;
00032 Parameters *g_param = NULL;
00033 SimParameters *g_simParam = NULL;
00034 ConfigList *g_cfgList = NULL;
00035 
00036 struct BasicAtomInfo
00037 {
00038     Index segNameIdx;
00039     Index resNameIdx;
00040     Index atomNameIdx;
00041     Index atomTypeIdx;
00042     Index chargeIdx;
00043     Index massIdx;    
00044     Index atomSigIdx;
00045     Index exclSigIdx;
00046     int resID;
00047 };
00048 
00049 typedef unsigned short SigIndex;
00050 struct AtomSigInfo
00051 {
00052     vector<SigIndex> bondSigIndices;
00053     vector<SigIndex> angleSigIndices;
00054     vector<SigIndex> dihedralSigIndices;
00055     vector<SigIndex> improperSigIndices;
00056     vector<SigIndex> crosstermSigIndices;
00057 
00058     AtomSigInfo()
00059     {}
00060     AtomSigInfo(const AtomSigInfo& sig)
00061     {
00062         bondSigIndices.clear();
00063         for(int i=0; i<sig.bondSigIndices.size(); i++)
00064             bondSigIndices.push_back(sig.bondSigIndices[i]);
00065 
00066         angleSigIndices.clear();
00067         for(int i=0; i<sig.angleSigIndices.size(); i++)
00068             angleSigIndices.push_back(sig.angleSigIndices[i]);
00069 
00070         dihedralSigIndices.clear();
00071         for(int i=0; i<sig.dihedralSigIndices.size(); i++)
00072             dihedralSigIndices.push_back(sig.dihedralSigIndices[i]);
00073 
00074         improperSigIndices.clear();
00075         for(int i=0; i<sig.improperSigIndices.size(); i++)
00076             improperSigIndices.push_back(sig.improperSigIndices[i]);
00077 
00078         crosstermSigIndices.clear();
00079         for(int i=0; i<sig.crosstermSigIndices.size(); i++)
00080             crosstermSigIndices.push_back(sig.crosstermSigIndices[i]);
00081     }
00082 
00083     ~AtomSigInfo()
00084     {
00085         bondSigIndices.clear();
00086         angleSigIndices.clear();
00087         dihedralSigIndices.clear();
00088         improperSigIndices.clear();
00089         crosstermSigIndices.clear();
00090     }
00091 
00092     void sortTupleSigIndices()
00093     {
00094         sort(bondSigIndices.begin(), bondSigIndices.end());
00095         sort(angleSigIndices.begin(), angleSigIndices.end());
00096         sort(dihedralSigIndices.begin(), dihedralSigIndices.end());
00097         sort(improperSigIndices.begin(), improperSigIndices.end());
00098         sort(crosstermSigIndices.begin(), crosstermSigIndices.end());
00099     }
00100   
00101     inline CkHashCode hash() const {
00102       // What's a good hash function for this? Lets make something up
00103       // Concatenate all the index lists into a list of chars, then hash that
00104       // string using Charm's string hash function
00105 
00106       // To keep memory allocation cheap, we'll just use a 32-byte buffer
00107       // and wrap around if we have more sigs
00108       const int maxlen = 32;
00109       unsigned char keydata[maxlen+1];
00110       const int maxchar = 256;
00111       int i,j;
00112       for(j=0;j<=maxlen;j++) keydata[j] = 0;
00113       j=0;
00114       for(i=0; i<bondSigIndices.size(); i++,j++) {
00115         keydata[j % maxlen] ^= (bondSigIndices[i] % maxchar);
00116       }
00117       for(i=0; i<angleSigIndices.size(); i++,j++) {
00118         keydata[j % maxlen] ^= (angleSigIndices[i] % maxchar);
00119       }
00120       for(i=0; i<dihedralSigIndices.size(); i++,j++) {
00121         keydata[j % maxlen] ^= (dihedralSigIndices[i] % maxchar);
00122       }
00123       for(i=0; i<improperSigIndices.size(); i++,j++) {
00124         keydata[j % maxlen] ^= (improperSigIndices[i] % maxchar);
00125       }
00126       for(i=0; i<crosstermSigIndices.size(); i++,j++) {
00127         keydata[j % maxlen] ^= (crosstermSigIndices[i] % maxchar);
00128       }
00129 //      CmiPrintf("Computed hash string len %d,%d\n",j,maxlen);
00130       if (j > maxlen) j = maxlen;
00131 //      for(i=0; i < j; i++) {
00132 //        if (keydata[i] == 0)
00133 //          keydata[i] = 255;
00134 //        CmiPrintf("key[%d]=%d %p\n",i,keydata[i],keydata);
00135 //      }
00136       return CkHashFunction_default((const void*)keydata,(size_t)j);
00137     }
00138 };
00139 
00140 int operator==(const AtomSigInfo &s1, const AtomSigInfo& s2)
00141 {
00142     if(s1.bondSigIndices.size() != s2.bondSigIndices.size())
00143         return 0;
00144     if(s1.angleSigIndices.size() != s2.angleSigIndices.size())
00145         return 0;
00146     if(s1.dihedralSigIndices.size() != s2.dihedralSigIndices.size())
00147         return 0;
00148     if(s1.improperSigIndices.size() != s2.improperSigIndices.size())
00149         return 0;
00150     if(s1.crosstermSigIndices.size() != s2.crosstermSigIndices.size())
00151         return 0;
00152 
00153     int equalCnt;
00154     equalCnt=0;
00155     int bondSigCnt = s1.bondSigIndices.size();
00156     for(int i=0; i<bondSigCnt; i++)
00157         equalCnt += (s1.bondSigIndices[i]==s2.bondSigIndices[i]);
00158     if(equalCnt!=bondSigCnt)
00159         return 0;
00160 
00161     equalCnt=0;
00162     int angleSigCnt = s1.angleSigIndices.size();
00163     for(int i=0; i<angleSigCnt; i++)
00164         equalCnt += (s1.angleSigIndices[i]==s2.angleSigIndices[i]);
00165     if(equalCnt!=angleSigCnt)
00166         return 0;
00167 
00168     equalCnt=0;
00169     int dihedralSigCnt = s1.dihedralSigIndices.size();
00170     for(int i=0; i<dihedralSigCnt; i++)
00171         equalCnt += (s1.dihedralSigIndices[i]==s2.dihedralSigIndices[i]);
00172     if(equalCnt!=dihedralSigCnt)
00173         return 0;
00174 
00175     equalCnt=0;
00176     int improperSigCnt = s1.improperSigIndices.size();
00177     for(int i=0; i<improperSigCnt; i++)
00178         equalCnt += (s1.improperSigIndices[i]==s2.improperSigIndices[i]);
00179     if(equalCnt!=improperSigCnt)
00180         return 0;
00181 
00182     equalCnt=0;
00183     int crosstermSigCnt = s1.crosstermSigIndices.size();
00184     for(int i=0; i<crosstermSigCnt; i++)
00185         equalCnt += (s1.crosstermSigIndices[i]==s2.crosstermSigIndices[i]);
00186     if(equalCnt!=crosstermSigCnt)
00187         return 0;
00188 
00189     return 1;
00190 }
00191 
00192 struct ExclSigInfo
00193 {
00194     vector<int> fullExclOffset;
00195     vector<int> modExclOffset;
00196 
00197     ExclSigInfo()
00198     {}
00199     ExclSigInfo(const ExclSigInfo& sig)
00200     {
00201         fullExclOffset.clear();
00202         for(int i=0; i<sig.fullExclOffset.size(); i++)
00203             fullExclOffset.push_back(sig.fullExclOffset[i]);
00204 
00205         modExclOffset.clear();
00206         for(int i=0; i<sig.modExclOffset.size(); i++)
00207             modExclOffset.push_back(sig.modExclOffset[i]);
00208     }
00209 
00210     ~ExclSigInfo()
00211     {
00212         fullExclOffset.clear();
00213         modExclOffset.clear();
00214     }
00215 
00216     void sortExclOffset()
00217     {
00218         sort(fullExclOffset.begin(), fullExclOffset.end());
00219         sort(modExclOffset.begin(), modExclOffset.end());
00220     }
00221 
00222     int hash() const {
00223       unsigned int code = 0x1234;
00224       unsigned int codesz = 8 * sizeof(int);
00225       const unsigned int numFoffset = fullExclOffset.size();
00226       const unsigned int numMoffset = modExclOffset.size();
00227       const unsigned int numOffsets = numFoffset + numMoffset;
00228       
00229       // No excluded atoms? Just hash to 0
00230       if (numOffsets == 0)
00231         return 0;
00232       
00233       unsigned int shift = codesz / numOffsets;
00234       if (shift == 0) shift=1;
00235       unsigned int i;
00236       for(i=0; i < numFoffset; i++) {
00237         code = circShift(code,shift);
00238         code ^= fullExclOffset[i];
00239       }
00240       for(i=0; i < numMoffset; i++) {
00241         code = circShift(code,shift);
00242         code ^= modExclOffset[i];
00243       }
00244       return code;
00245     }
00246 };
00247 int operator==(const ExclSigInfo &s1, const ExclSigInfo &s2)
00248 {
00249     if(s1.fullExclOffset.size()!=s2.fullExclOffset.size())
00250         return 0;
00251     if(s1.modExclOffset.size()!=s2.modExclOffset.size())
00252         return 0;
00253 
00254     for(int i=0; i<s1.fullExclOffset.size(); i++)
00255     {
00256         if(s1.fullExclOffset[i] != s2.fullExclOffset[i])
00257             return 0;
00258     }
00259 
00260     for(int i=0; i<s1.modExclOffset.size(); i++)
00261     {
00262         if(s1.modExclOffset[i] != s2.modExclOffset[i])
00263             return 0;
00264     }
00265     return 1;
00266 }
00267 
00268 class HashString : public string {
00269 public:
00270   int hash() const {
00271     const char* d = this->c_str();
00272     int ret=0;
00273     for (int i=0;d[i]!=0;i++) {
00274       int shift1=((5*i)%16)+0;
00275       int shift2=((6*i)%16)+8;
00276       ret+=((0xa5^d[i])<<shift2)+(d[i]<<shift1);
00277     }
00278     return ret;
00279   }
00280 };
00281 
00282 class HashReal {
00283   Real val;
00284 public:
00285   HashReal(Real v) : val(v) {}
00286   operator Real & () { return val; }
00287   operator const Real & () const { return val; }
00288   
00289   int hash() const {
00290     const char* d = (const char *)&val;
00291     int ret=0;
00292     for (int i=0;i < sizeof(Real);i++) {
00293       int shift1=((5*i)%16)+0;
00294       int shift2=((6*i)%16)+8;
00295       ret+=((0xa5^d[i])<<shift2)+(d[i]<<shift1);
00296     }
00297     return ret;
00298   };
00299 };
00300 
00301 HashPool<HashString> segNamePool;
00302 HashPool<HashString> resNamePool;
00303 HashPool<HashString> atomNamePool;
00304 HashPool<HashString> atomTypePool;
00305 HashPool<HashReal> chargePool;
00306 HashPool<HashReal> massPool;
00307 HashPool<AtomSigInfo> atomSigPool;
00308 BasicAtomInfo *atomData;
00309 
00310 //Recording cluster information after reading all bonds info
00311 int *eachAtomClusterID = NULL;
00312 vector<int> eachClusterSize;
00313 int g_numClusters = 0;
00314 //indicate whether the atom ids in a cluster are contiguous or not
00315 int g_isClusterContiguous = 0;
00316 
00317 HashPool<TupleSignature> sigsOfBonds;
00318 HashPool<TupleSignature> sigsOfAngles;
00319 HashPool<TupleSignature> sigsOfDihedrals;
00320 HashPool<TupleSignature> sigsOfImpropers;
00321 HashPool<TupleSignature> sigsOfCrossterms;
00322 AtomSigInfo *eachAtomSigs;
00323 
00324 HashPool<ExclSigInfo> sigsOfExclusions;
00325 ExclSigInfo *eachAtomExclSigs;
00326 
00327 //Structures for extraBond options
00328 vector<Bond> extraBonds;
00329 vector<Angle> extraAngles;
00330 vector<Dihedral> extraDihedrals;
00331 vector<Improper> extraImpropers;
00332 
00333 vector<BondValue> extraBondParams;
00334 vector<AngleValue> extraAngleParams;
00335 vector<DihedralValue> extraDihedralParams;
00336 vector<ImproperValue> extraImproperParams;
00337 
00338 int operator==(const BondValue &b1, const BondValue &b2)
00339 {
00340     return (b1.k==b2.k) && (b1.x0==b2.x0);
00341 }
00342 
00343 int operator==(const AngleValue &a1, const AngleValue &a2)
00344 {
00345     return (a1.k==a2.k) && (a1.k_ub==a2.k_ub) && (a1.r_ub==a2.r_ub) && (a1.theta0==a2.theta0);
00346 }
00347 
00348 int operator!=(const FourBodyConsts& f1, const FourBodyConsts& f2)
00349 {
00350     return (f1.delta!=f2.delta) || (f1.k!=f2.k) || (f1.n!=f2.n);
00351 }
00352 
00353 int operator==(const DihedralValue &d1, const DihedralValue &d2)
00354 {
00355     if(d1.multiplicity != d2.multiplicity)
00356         return 0;
00357     for(int i=0; i<MAX_MULTIPLICITY; i++)
00358     {
00359         if(d1.values[i] != d2.values[i])
00360             return 0;
00361     }
00362     return 1;
00363 }
00364 
00365 int operator==(const ImproperValue &d1, const ImproperValue &d2)
00366 {
00367     if(d1.multiplicity != d2.multiplicity)
00368         return 0;
00369     for(int i=0; i<MAX_MULTIPLICITY; i++)
00370     {
00371         if(d1.values[i] != d2.values[i])
00372             return 0;
00373     }
00374     return 1;
00375 }
00376 
00377 void readPsfFile(char *psfFileName);
00378 void loadMolInfo();
00379 
00380 void integrateAllAtomSigs();
00381 void outputPsfFile(FILE *ofp);
00382 void outputCompressedFile(FILE *txtOfp, FILE *binOfp);
00383 
00384 //reading extraBond's information
00385 void getExtraBonds(StringList *file);
00386 
00387 //reading atom's basic information
00388 void getAtomData(FILE *ifp);
00389 void getBondData(FILE *ifp);
00390 void getAngleData(FILE *ifp);
00391 void getDihedralData(FILE *ifp);
00392 void getImproperData(FILE *ifp);
00393 void getDonorData(FILE *ifp);
00394 void getAcceptorData(FILE *ifp);
00395 void getExclusionData(FILE *ifp);
00396 void getCrosstermData(FILE *ifp);
00397 
00398 void buildAtomData();
00399 void buildBondData();
00400 void buildAngleData();
00401 void buildDihedralData();
00402 void buildImproperData();
00403 void buildCrosstermData();
00404 
00405 void buildExclusionData();
00406 void buildParamData();
00407 
00408 //Functions related with building exclusions
00409 void buildExclusions();
00410 void build12Excls(UniqueSet<Exclusion>&, vector<int> *);
00411 void build13Excls(UniqueSet<Exclusion>&, vector<int> *);
00412 void build14Excls(UniqueSet<Exclusion>&, vector<int> *, int);
00413 
00414 //reverse the byte-order of every element starting at "elem"
00415 void flipNum(char *elem, int elemSize, int numElems){
00416     int mid = elemSize/2;
00417     char *ptr = elem;
00418     for(int i=0; i<numElems; i++) {
00419         for(int j=0; j<mid; j++) {
00420             char tmp = ptr[j];
00421             ptr[j] = ptr[elemSize-1-j];
00422             ptr[elemSize-1-j] = tmp;
00423         }
00424         ptr += elemSize;
00425     }
00426 }
00427 
00428 void clearGlobalVectors()
00429 {
00430     segNamePool.clear();
00431     resNamePool.clear();
00432     atomNamePool.clear();
00433     atomTypePool.clear();
00434     chargePool.clear();
00435     massPool.clear();
00436     sigsOfBonds.clear();
00437     sigsOfAngles.clear();
00438     sigsOfDihedrals.clear();
00439     sigsOfImpropers.clear();
00440     sigsOfExclusions.clear();
00441 
00442     eachClusterSize.clear();
00443 }
00444 
00445 void compress_psf_file(Molecule *mol, char *psfFileName, Parameters *param, SimParameters *simParam, ConfigList *cfgList)
00446 {
00447 
00448     g_mol = mol;
00449     g_param = param;
00450     g_simParam = simParam; //used for building exclusions
00451     g_cfgList = cfgList; //used for integrating extra bonds
00452 
00453     //read psf files
00454     readPsfFile(psfFileName);
00455 
00456     integrateAllAtomSigs();
00457 
00458     buildExclusions();
00459 
00460 
00461     char *outFileName = new char[strlen(psfFileName)+10];
00462     sprintf(outFileName, "%s.inter", psfFileName);
00463     FILE *ofp = fopen(outFileName, "w");
00464     delete [] outFileName;
00465     //output compressed psf file
00466     outputPsfFile(ofp);
00467     fclose(ofp);
00468 }
00469 
00470 void compress_molecule_info(Molecule *mol, char *psfFileName, Parameters *param, SimParameters *simParam, ConfigList* cfgList)
00471 {
00472     g_mol = mol;
00473     g_param = param;
00474     g_simParam = simParam; //used for building exclusions
00475     g_cfgList = cfgList; //used for integrating extra bonds
00476 
00477     //read psf files
00478     //readPsfFile(psfFileName);
00479     loadMolInfo();
00480 
00481     integrateAllAtomSigs();
00482 
00483     buildExclusions();
00484 
00485     //buildParamData();
00486 
00487     char *outFileName = new char[strlen(psfFileName)+20];
00488     sprintf(outFileName, "%s.inter", psfFileName);
00489     //the text file for signatures and other non-per-atom info
00490     FILE *txtOfp = fopen(outFileName, "w");
00491     sprintf(outFileName, "%s.inter.bin", psfFileName);
00492     //the binary file for per-atom info
00493     FILE *binOfp = fopen(outFileName, "wb");
00494     delete [] outFileName;
00495 
00496     //output compressed psf file
00497     outputCompressedFile(txtOfp, binOfp);
00498 
00499     fclose(txtOfp);
00500     fclose(binOfp);
00501 }
00502 
00503 //Almost same with Molecule::read_psf_file
00504 void readPsfFile(char *fname)
00505 {
00506     char err_msg[512];  //  Error message for NAMD_die
00507     char buffer[512];  //  Buffer for file reading
00508     int i;      //  Loop counter
00509     int NumTitle;    //  Number of Title lines in .psf file
00510     int ret_code;    //  ret_code from NAMD_read_line calls
00511     FILE *psf_file;
00512     Parameters *params = g_param;
00513 
00514     /* Try and open the .psf file           */
00515     if ( (psf_file = fopen(fname, "r")) == NULL)
00516     {
00517         sprintf(err_msg, "UNABLE TO OPEN .psf FILE %s", fname);
00518         NAMD_die(err_msg);
00519     }
00520 
00521     /*  Read till we have the first non-blank line of file    */
00522     ret_code = NAMD_read_line(psf_file, buffer);
00523 
00524     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00525     {
00526         ret_code = NAMD_read_line(psf_file, buffer);
00527     }
00528 
00529     /*  Check to see if we dropped out of the loop because of a     */
00530     /*  read error.  This shouldn't happen unless the file is empty */
00531     if (ret_code!=0)
00532     {
00533         sprintf(err_msg, "EMPTY .psf FILE %s", fname);
00534         NAMD_die(err_msg);
00535     }
00536 
00537     /*  The first non-blank line should contain the word "psf".    */
00538     /*  If we can't find it, die.               */
00539     if (!NAMD_find_word(buffer, "psf"))
00540     {
00541         sprintf(err_msg, "UNABLE TO FIND \"PSF\" STRING IN PSF FILE %s",
00542                 fname);
00543         NAMD_die(err_msg);
00544     }
00545 
00546     /*  Read until we find the next non-blank line      */
00547     ret_code = NAMD_read_line(psf_file, buffer);
00548 
00549     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00550     {
00551         ret_code = NAMD_read_line(psf_file, buffer);
00552     }
00553 
00554     /*  Check to see if we dropped out of the loop because of a     */
00555     /*  read error.  This shouldn't happen unless there is nothing  */
00556     /*  but the PSF line in the file        */
00557     if (ret_code!=0)
00558     {
00559         sprintf(err_msg, "MISSING EVERYTHING BUT PSF FROM %s", fname);
00560         NAMD_die(err_msg);
00561     }
00562 
00563     /*  This line should have the word "NTITLE" in it specifying    */
00564     /*  how many title lines there are        */
00565     if (!NAMD_find_word(buffer, "NTITLE"))
00566     {
00567         sprintf(err_msg,"CAN NOT FIND \"NTITLE\" STRING IN PSF FILE %s",
00568                 fname);
00569         NAMD_die(err_msg);
00570     }
00571 
00572     sscanf(buffer, "%d", &NumTitle);
00573 
00574     /*  Now skip the next NTITLE non-blank lines and then read in the*/
00575     /*  line which should contain NATOM        */
00576     i=0;
00577 
00578     while ( ((ret_code=NAMD_read_line(psf_file, buffer)) == 0) &&
00579             (i<NumTitle) )
00580     {
00581         if (!NAMD_blank_string(buffer))
00582             i++;
00583     }
00584 
00585     /*  Make sure we didn't exit because of a read error    */
00586     if (ret_code!=0)
00587     {
00588         sprintf(err_msg, "FOUND EOF INSTEAD OF NATOM IN PSF FILE %s",
00589                 fname);
00590         NAMD_die(err_msg);
00591     }
00592 
00593     while (NAMD_blank_string(buffer))
00594     {
00595         NAMD_read_line(psf_file, buffer);
00596     }
00597 
00598     /*  Check to make sure we have the line we want      */
00599     if (!NAMD_find_word(buffer, "NATOM"))
00600     {
00601         sprintf(err_msg, "DIDN'T FIND \"NATOM\" IN PSF FILE %s",
00602                 fname);
00603         NAMD_die(err_msg);
00604     }
00605 
00606     /*  Read in the number of atoms, and then the atoms themselves  */
00607     sscanf(buffer, "%d", &g_mol->numAtoms);
00608 
00609     getAtomData(psf_file);
00610 
00611     //read extra bonds/angles/dihedrals/impropers information first
00612     //and then integrate them into the following reading procedures
00613     if(g_simParam->extraBondsOn)
00614     {
00615         getExtraBonds(g_cfgList->find("extraBondsFile"));
00616     }
00617 
00618     //initialize eachAtomSigs
00619     eachAtomSigs = new AtomSigInfo[g_mol->numAtoms];
00620 
00621     /*  Read until we find the next non-blank line      */
00622     ret_code = NAMD_read_line(psf_file, buffer);
00623 
00624     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00625     {
00626         ret_code = NAMD_read_line(psf_file, buffer);
00627     }
00628 
00629     /*  Check to make sure we didn't hit the EOF      */
00630     if (ret_code != 0)
00631     {
00632         NAMD_die("EOF ENCOUNTERED LOOKING FOR NBONDS IN PSF");
00633     }
00634 
00635     /*  Look for the string "NBOND"          */
00636     if (!NAMD_find_word(buffer, "NBOND"))
00637     {
00638         NAMD_die("DID NOT FIND NBOND AFTER ATOM LIST IN PSF");
00639     }
00640 
00641     /*  Read in the number of bonds and then the bonds themselves  */
00642     sscanf(buffer, "%d", &g_mol->numBonds);
00643 
00644     if (g_mol->numBonds)
00645         getBondData(psf_file);
00646 
00647     /*  Read until we find the next non-blank line      */
00648     ret_code = NAMD_read_line(psf_file, buffer);
00649 
00650     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00651     {
00652         ret_code = NAMD_read_line(psf_file, buffer);
00653     }
00654 
00655     /*  Check to make sure we didn't hit the EOF      */
00656     if (ret_code != 0)
00657     {
00658         NAMD_die("EOF ENCOUNTERED LOOKING FOR NTHETA IN PSF");
00659     }
00660 
00661     /*  Look for the string "NTHETA"        */
00662     if (!NAMD_find_word(buffer, "NTHETA"))
00663     {
00664         NAMD_die("DID NOT FIND NTHETA AFTER BOND LIST IN PSF");
00665     }
00666 
00667     /*  Read in the number of angles and then the angles themselves */
00668     sscanf(buffer, "%d", &g_mol->numAngles);
00669 
00670     if (g_mol->numAngles)
00671         getAngleData(psf_file);
00672 
00673     /*  Read until we find the next non-blank line      */
00674     ret_code = NAMD_read_line(psf_file, buffer);
00675 
00676     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00677     {
00678         ret_code = NAMD_read_line(psf_file, buffer);
00679     }
00680 
00681     /*  Check to make sure we didn't hit the EOF      */
00682     if (ret_code != 0)
00683     {
00684         NAMD_die("EOF ENCOUNTERED LOOKING FOR NPHI IN PSF");
00685     }
00686 
00687     /*  Look for the string "NPHI"          */
00688     if (!NAMD_find_word(buffer, "NPHI"))
00689     {
00690         NAMD_die("DID NOT FIND NPHI AFTER ANGLE LIST IN PSF");
00691     }
00692 
00693     /*  Read in the number of dihedrals and then the dihedrals      */
00694     sscanf(buffer, "%d", &g_mol->numDihedrals);
00695 
00696     if (g_mol->numDihedrals)
00697         getDihedralData(psf_file);
00698 
00699     /*  Read until we find the next non-blank line      */
00700     ret_code = NAMD_read_line(psf_file, buffer);
00701 
00702     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00703     {
00704         ret_code = NAMD_read_line(psf_file, buffer);
00705     }
00706 
00707     /*  Check to make sure we didn't hit the EOF      */
00708     if (ret_code != 0)
00709     {
00710         NAMD_die("EOF ENCOUNTERED LOOKING FOR NIMPHI IN PSF");
00711     }
00712 
00713     /*  Look for the string "NIMPHI"        */
00714     if (!NAMD_find_word(buffer, "NIMPHI"))
00715     {
00716         NAMD_die("DID NOT FIND NIMPHI AFTER ATOM LIST IN PSF");
00717     }
00718 
00719     /*  Read in the number of Impropers and then the impropers  */
00720     sscanf(buffer, "%d", &g_mol->numImpropers);
00721 
00722     if (g_mol->numImpropers)
00723         getImproperData(psf_file);
00724 
00725     /*  Read until we find the next non-blank line      */
00726     ret_code = NAMD_read_line(psf_file, buffer);
00727 
00728     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00729     {
00730         ret_code = NAMD_read_line(psf_file, buffer);
00731     }
00732 
00733     /*  Check to make sure we didn't hit the EOF      */
00734     if (ret_code != 0)
00735     {
00736         NAMD_die("EOF ENCOUNTERED LOOKING FOR NDON IN PSF");
00737     }
00738 
00739     /*  Look for the string "NDON"        */
00740     if (!NAMD_find_word(buffer, "NDON"))
00741     {
00742         NAMD_die("DID NOT FIND NDON AFTER ATOM LIST IN PSF");
00743     }
00744 
00745     /*  Read in the number of hydrogen bond donors and then the donors */
00746     sscanf(buffer, "%d", &g_mol->numDonors);
00747 
00748     if (g_mol->numDonors)
00749         getDonorData(psf_file);
00750 
00751     /*  Read until we find the next non-blank line      */
00752     ret_code = NAMD_read_line(psf_file, buffer);
00753 
00754     while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
00755     {
00756         ret_code = NAMD_read_line(psf_file, buffer);
00757     }
00758 
00759     /*  Check to make sure we didn't hit the EOF      */
00760     if (ret_code != 0)
00761     {
00762         NAMD_die("EOF ENCOUNTERED LOOKING FOR NACC IN PSF");
00763     }
00764 
00765     /*  Look for the string "NACC"        */
00766     if (!NAMD_find_word(buffer, "NACC"))
00767     {
00768         NAMD_die("DID NOT FIND NACC AFTER ATOM LIST IN PSF");
00769     }
00770 
00771     /*  Read in the number of hydrogen bond donors and then the donors */
00772     sscanf(buffer, "%d", &g_mol->numAcceptors);
00773 
00774     if (g_mol->numAcceptors)
00775         getAcceptorData(psf_file);
00776 
00777     /*  look for the explicit non-bonded exclusion section.     */
00778     while (!NAMD_find_word(buffer, "NNB"))
00779     {
00780         ret_code = NAMD_read_line(psf_file, buffer);
00781 
00782         if (ret_code != 0)
00783         {
00784             NAMD_die("EOF ENCOUNTERED LOOKING FOR NNB IN PSF FILE");
00785         }
00786     }
00787 
00788     /*  Read in the number of exclusions and then the exclusions    */
00789     sscanf(buffer, "%d", &g_mol->numExclusions);
00790 
00791     if (g_mol->numExclusions)
00792         getExclusionData(psf_file);
00793 
00794     /*  look for the cross-term section.     */
00795     int crossterms_present = 1;
00796     while (!NAMD_find_word(buffer, "NCRTERM"))
00797     {
00798         ret_code = NAMD_read_line(psf_file, buffer);
00799 
00800         if (ret_code != 0)
00801         {
00802             // hit EOF before finding cross-term section
00803             crossterms_present = 0;
00804             break;
00805         }
00806     }
00807 
00808     if ( crossterms_present)
00809     {
00810 
00811         /*  Read in the number of cross-terms and then the cross-terms*/
00812         sscanf(buffer, "%d", &g_mol->numCrossterms);
00813 
00814         if (g_mol->numCrossterms)
00815             getCrosstermData(psf_file);
00816 
00817     }
00818 
00819     //  analyze the data and find the status of each atom
00820     //build_atom_status();
00821 
00822     fclose(psf_file);
00823 }
00824 
00829 void loadMolInfo()
00830 {
00831     char err_msg[512];  //  Error message for NAMD_die
00832     char buffer[512];  //  Buffer for file reading
00833     int i;      //  Loop counter
00834     int NumTitle;    //  Number of Title lines in .psf file
00835     int ret_code;    //  ret_code from NAMD_read_line calls
00836     FILE *psf_file;
00837     Parameters *params = g_param;
00838 
00839     buildAtomData();
00840 
00841     //read extra bonds/angles/dihedrals/impropers information first
00842     //and then integrate them into the following reading procedures
00843     /*if(g_simParam->extraBondsOn)
00844     {
00845         getExtraBonds(g_cfgList->find("extraBondsFile"));
00846     }*/
00847 
00848     //initialize eachAtomSigs
00849     eachAtomSigs = new AtomSigInfo[g_mol->numAtoms];    
00850 
00851     if (g_mol->numBonds)
00852         buildBondData();
00853 
00854     if (g_mol->numAngles)
00855         buildAngleData();
00856 
00857     if (g_mol->numDihedrals)
00858         buildDihedralData();
00859 
00860     if (g_mol->numImpropers)
00861         buildImproperData();
00862 
00863     if (g_mol->numCrossterms)
00864         buildCrosstermData();
00865 
00866     //  analyze the data and find the status of each atom
00867     //build_atom_status();
00868 }
00869 
00870 void integrateAllAtomSigs()
00871 {
00872     printf("Bond sigs:  %d\n", (int)sigsOfBonds.size());
00873     printf("Angle sigs:  %d\n", (int)sigsOfAngles.size());
00874     printf("Dihedral sigs:  %d\n", (int)sigsOfDihedrals.size());
00875     printf("Improper sigs:  %d\n", (int)sigsOfImpropers.size());
00876     printf("Crossterm sigs:  %d\n", (int)sigsOfCrossterms.size());
00877 
00878 
00879     for(int i=0; i<g_mol->numAtoms; i++)
00880     {
00881         eachAtomSigs[i].sortTupleSigIndices();
00882         int poolIndex = atomSigPool.lookupCstPool(eachAtomSigs[i]);
00883         if(poolIndex==-1)
00884         {
00885             atomSigPool.push_back(eachAtomSigs[i]);
00886             poolIndex = atomSigPool.size()-1;
00887         }
00888         atomData[i].atomSigIdx = poolIndex;
00889     }
00890 
00891     printf("Atom's sigs: %d\n", (int)atomSigPool.size());
00892 
00893     delete[] eachAtomSigs;
00894 }
00895 
00896 void outputPsfFile(FILE *ofp)
00897 {
00898     fprintf(ofp, "FORMAT VERSION: %f\n", COMPRESSED_PSF_VER);
00899 
00900     fprintf(ofp, "%d !NSEGMENTNAMES\n", segNamePool.size());
00901     for(int i=0; i<segNamePool.size(); i++)
00902     {
00903         fprintf(ofp, "%s\n", segNamePool[i].c_str());
00904     }
00905 
00906     fprintf(ofp, "%d !NRESIDUENAMES\n", resNamePool.size());
00907     for(int i=0; i<resNamePool.size(); i++)
00908     {
00909         fprintf(ofp, "%s\n", resNamePool[i].c_str());
00910     }
00911 
00912     fprintf(ofp, "%d !NATOMNAMES\n", atomNamePool.size());
00913     for(int i=0; i<atomNamePool.size(); i++)
00914     {
00915         fprintf(ofp, "%s\n", atomNamePool[i].c_str());
00916     }
00917 
00918     fprintf(ofp, "%d !NATOMTYPES\n", atomTypePool.size());
00919     for(int i=0; i<atomTypePool.size(); i++)
00920     {
00921         fprintf(ofp, "%s\n", atomTypePool[i].c_str());
00922     }
00923 
00924     fprintf(ofp, "%d !NCHARGES\n", chargePool.size());
00925     for(int i=0; i<chargePool.size(); i++)
00926     {
00927         const Real charge = chargePool[i];
00928         fprintf(ofp, "%f\n", charge);
00929     }
00930 
00931     fprintf(ofp, "%d !NMASSES\n", massPool.size());
00932     for(int i=0; i<massPool.size(); i++)
00933     {
00934         const Real mass = massPool[i];
00935         fprintf(ofp, "%f\n", mass);
00936     }
00937 
00938 
00939     fprintf(ofp, "%d !NATOMSIGS\n", atomSigPool.size());
00940     for(int i=0; i<atomSigPool.size(); i++)
00941     {
00942         AtomSigInfo& oneAtomSig = atomSigPool[i];
00943         int oneTypeCnt = oneAtomSig.bondSigIndices.size();
00944         fprintf(ofp, "%d !%sSIGS\n", oneTypeCnt, "NBOND");
00945         for(int j=0; j<oneTypeCnt; j++)
00946         {
00947             SigIndex idx = oneAtomSig.bondSigIndices[j];
00948             TupleSignature& tSig = sigsOfBonds[idx];
00949             tSig.output(ofp);
00950         }
00951 
00952         oneTypeCnt = oneAtomSig.angleSigIndices.size();
00953         fprintf(ofp, "%d !%sSIGS\n", oneTypeCnt, "NTHETA");
00954         for(int j=0; j<oneTypeCnt; j++)
00955         {
00956             SigIndex idx = oneAtomSig.angleSigIndices[j];
00957             TupleSignature& tSig = sigsOfAngles[idx];
00958             tSig.output(ofp);
00959         }
00960 
00961         oneTypeCnt = oneAtomSig.dihedralSigIndices.size();
00962         fprintf(ofp, "%d !%sSIGS\n", oneTypeCnt, "NPHI");
00963         for(int j=0; j<oneTypeCnt; j++)
00964         {
00965             SigIndex idx = oneAtomSig.dihedralSigIndices[j];
00966             TupleSignature& tSig = sigsOfDihedrals[idx];
00967             tSig.output(ofp);
00968         }
00969 
00970         oneTypeCnt = oneAtomSig.improperSigIndices.size();
00971         fprintf(ofp, "%d !%sSIGS\n", oneTypeCnt, "NIMPHI");
00972         for(int j=0; j<oneTypeCnt; j++)
00973         {
00974             SigIndex idx = oneAtomSig.improperSigIndices[j];
00975             TupleSignature& tSig = sigsOfImpropers[idx];
00976             tSig.output(ofp);
00977         }
00978 
00979         oneTypeCnt = oneAtomSig.crosstermSigIndices.size();
00980         fprintf(ofp, "%d !%sSIGS\n", oneTypeCnt, "NCRTERM");
00981         for(int j=0; j<oneTypeCnt; j++)
00982         {
00983             SigIndex idx = oneAtomSig.crosstermSigIndices[j];
00984             TupleSignature& tSig = sigsOfCrossterms[idx];
00985             tSig.output(ofp);
00986         }
00987     }
00988 
00989     //2. Output exclusion signatures
00990     int exclSigCnt = sigsOfExclusions.size();
00991     fprintf(ofp, "%d !NEXCLSIGS\n", exclSigCnt);
00992     for(int i=0; i<exclSigCnt; i++)
00993     {
00994         ExclSigInfo *sig = &sigsOfExclusions[i];
00995         //first line is for full exclusions (1-2, 1-3) in the format of count offset1 offset2 offset3 ...
00996         fprintf(ofp, "%d", sig->fullExclOffset.size());
00997         for(int j=0; j<sig->fullExclOffset.size(); j++)
00998             fprintf(ofp, " %d", sig->fullExclOffset[j]);
00999         fprintf(ofp, "\n");
01000 
01001         //second line is for modified exclusions (1-4)
01002         fprintf(ofp, "%d", sig->modExclOffset.size());
01003         for(int j=0; j<sig->modExclOffset.size(); j++)
01004             fprintf(ofp, " %d", sig->modExclOffset[j]);
01005         fprintf(ofp, "\n");
01006     }
01007 
01008     //3. Output the cluster information
01009     fprintf(ofp, "%d !NCLUSTERS\n", g_numClusters);
01010     fprintf(ofp, "%d !CLUSTERCONTIGUITY\n", g_isClusterContiguous);
01011 
01012     //4. Output atom info
01013     fprintf(ofp, "%d !NATOM\n", g_mol->numAtoms);
01014     const float *atomOccupancy = g_mol->getOccupancyData();
01015     const float *atomBFactor = g_mol->getBFactorData();
01016     fprintf(ofp, "%d !OCCUPANCYVALID\n", (atomOccupancy==NULL)?0:1);
01017     fprintf(ofp, "%d !TEMPFACTORVALID\n", (atomBFactor==NULL)?0:1);
01018 
01019     float *zeroFloats = NULL;
01020     if(atomOccupancy==NULL || atomBFactor==NULL) {
01021         zeroFloats = new float[g_mol->numAtoms];
01022         memcpy(zeroFloats, 0, sizeof(float)*g_mol->numAtoms);
01023         if(atomOccupancy==NULL) atomOccupancy = (const float *)zeroFloats;
01024         if(atomBFactor==NULL) atomBFactor = (const float *)zeroFloats;
01025     }
01026 
01027     for(int i=0; i<g_mol->numAtoms; i++)
01028     {
01029         BasicAtomInfo &one = atomData[i];
01030         fprintf(ofp, "%d %d %d %d %d %d %d %d %d %d %f %f\n", one.segNameIdx, one.resID, one.resNameIdx, one.atomNameIdx,
01031                 one.atomTypeIdx, one.chargeIdx, one.massIdx, one.atomSigIdx, one.exclSigIdx, 
01032                 eachAtomClusterID[i], atomOccupancy[i], atomBFactor[i]);
01033     }
01034     //fprintf(ofp, "\n");
01035 
01036     if(zeroFloats) delete[] zeroFloats;
01037     delete[] atomData;
01038     delete[] eachAtomClusterID;
01039 
01040     //4.Output the parameter new values if extraBonds are present.
01041     if(g_simParam->extraBondsOn)
01042     {
01043         // 1) output extra params for bonds
01044         int numExtraParams = extraBondParams.size();
01045         fprintf(ofp, "%d!NEXTRABONDPARAMS\n", numExtraParams);
01046         if(numExtraParams>0)
01047         {
01048             vector<BondValue>::iterator bpIter;
01049             for(bpIter=extraBondParams.begin(); bpIter!=extraBondParams.end(); bpIter++)
01050             {
01051                 fprintf(ofp, "%f %f\n", bpIter->k, bpIter->x0);
01052             }
01053         }
01054 
01055         // 2) output extra params for angles
01056         numExtraParams = extraAngleParams.size();
01057         fprintf(ofp, "%d!NEXTRAANGLEPARAMS\n", numExtraParams);
01058         if(numExtraParams>0)
01059         {
01060             vector<AngleValue>::iterator apIter;
01061             for(apIter=extraAngleParams.begin(); apIter!=extraAngleParams.end(); apIter++)
01062             {
01063                 fprintf(ofp, "%f %f %f %f\n", apIter->k, apIter->theta0, apIter->k_ub, apIter->r_ub);
01064             }
01065         }
01066 
01067         // 3) output extra params for dihedrals
01068         numExtraParams = extraDihedralParams.size();
01069         fprintf(ofp, "%d!NEXTRADIHEDRALPARAMS\n", numExtraParams);
01070         if(numExtraParams>0)
01071         {
01072             vector<DihedralValue>::iterator dpIter;
01073             for(dpIter=extraDihedralParams.begin(); dpIter!=extraDihedralParams.end(); dpIter++)
01074             {
01075                 fprintf(ofp, "%d\n", dpIter->multiplicity);
01076                 for(int i=0; i<dpIter->multiplicity; i++) {
01077                     fprintf(ofp, "%f %d %f\n", dpIter->values[i].k, dpIter->values[i].n, dpIter->values[i].delta);
01078                 }                
01079             }
01080         }
01081 
01082         // 4) output extra params for impropers
01083         numExtraParams = extraImproperParams.size();
01084         fprintf(ofp, "%d!NEXTRAIMPROPERPARAMS\n", numExtraParams);
01085         if(numExtraParams>0)
01086         {
01087             vector<ImproperValue>::iterator ipIter;
01088             for(ipIter=extraImproperParams.begin(); ipIter!=extraImproperParams.end(); ipIter++)
01089             {
01090                 fprintf(ofp, "%d\n", ipIter->multiplicity);
01091                 for(int i=0; i<ipIter->multiplicity; i++) {
01092                     fprintf(ofp, "%f %d %f\n", ipIter->values[i].k, ipIter->values[i].n, ipIter->values[i].delta);
01093                 }                
01094             }
01095         }
01096     }
01097 
01098     //5. Output the "multiplicity" field TUPLE_array of the Parameter object
01099     fprintf(ofp, "!DIHEDRALPARAMARRAY\n");
01100     for(int i=0; i<g_param->NumDihedralParams; i++)
01101     {
01102         fprintf(ofp, "%d ", g_param->dihedral_array[i].multiplicity);
01103     }
01104     fprintf(ofp, "\n");
01105     fprintf(ofp, "!IMPROPERPARAMARRAY\n");
01106     for(int i=0; i<g_param->NumImproperParams; i++)
01107     {
01108         fprintf(ofp, "%d ", g_param->improper_array[i].multiplicity);
01109     }
01110     fprintf(ofp, "\n");
01111 }
01112 
01142 void outputCompressedFile(FILE *txtOfp, FILE *binOfp)
01143 {
01144 #ifndef MEM_OPT_VERSION
01145     fprintf(txtOfp, "FORMAT VERSION: %f\n", COMPRESSED_PSF_VER);
01146 
01147     fprintf(txtOfp, "%d !NSEGMENTNAMES\n", segNamePool.size());
01148     for(int i=0; i<segNamePool.size(); i++)
01149     {
01150         fprintf(txtOfp, "%s\n", segNamePool[i].c_str());
01151     }
01152 
01153     fprintf(txtOfp, "%d !NRESIDUENAMES\n", resNamePool.size());
01154     for(int i=0; i<resNamePool.size(); i++)
01155     {
01156         fprintf(txtOfp, "%s\n", resNamePool[i].c_str());
01157     }
01158 
01159     fprintf(txtOfp, "%d !NATOMNAMES\n", atomNamePool.size());
01160     for(int i=0; i<atomNamePool.size(); i++)
01161     {
01162         fprintf(txtOfp, "%s\n", atomNamePool[i].c_str());
01163     }
01164 
01165     fprintf(txtOfp, "%d !NATOMTYPES\n", atomTypePool.size());
01166     for(int i=0; i<atomTypePool.size(); i++)
01167     {
01168         fprintf(txtOfp, "%s\n", atomTypePool[i].c_str());
01169     }
01170 
01171     fprintf(txtOfp, "%d !NCHARGES\n", chargePool.size());
01172     for(int i=0; i<chargePool.size(); i++)
01173     {
01174         const Real charge = chargePool[i];
01175         fprintf(txtOfp, "%f\n", charge);
01176     }
01177 
01178     fprintf(txtOfp, "%d !NMASSES\n", massPool.size());
01179     for(int i=0; i<massPool.size(); i++)
01180     {
01181         const Real mass = massPool[i];
01182         fprintf(txtOfp, "%f\n", mass);
01183     }
01184 
01185 
01186     fprintf(txtOfp, "%d !NATOMSIGS\n", atomSigPool.size());
01187     for(int i=0; i<atomSigPool.size(); i++)
01188     {
01189         AtomSigInfo& oneAtomSig = atomSigPool[i];
01190         int oneTypeCnt = oneAtomSig.bondSigIndices.size();
01191         fprintf(txtOfp, "%d !%sSIGS\n", oneTypeCnt, "NBOND");
01192         for(int j=0; j<oneTypeCnt; j++)
01193         {
01194             SigIndex idx = oneAtomSig.bondSigIndices[j];
01195             TupleSignature& tSig = sigsOfBonds[idx];
01196             tSig.output(txtOfp);
01197         }
01198 
01199         oneTypeCnt = oneAtomSig.angleSigIndices.size();
01200         fprintf(txtOfp, "%d !%sSIGS\n", oneTypeCnt, "NTHETA");
01201         for(int j=0; j<oneTypeCnt; j++)
01202         {
01203             SigIndex idx = oneAtomSig.angleSigIndices[j];
01204             TupleSignature& tSig = sigsOfAngles[idx];
01205             tSig.output(txtOfp);
01206         }
01207 
01208         oneTypeCnt = oneAtomSig.dihedralSigIndices.size();
01209         fprintf(txtOfp, "%d !%sSIGS\n", oneTypeCnt, "NPHI");
01210         for(int j=0; j<oneTypeCnt; j++)
01211         {
01212             SigIndex idx = oneAtomSig.dihedralSigIndices[j];
01213             TupleSignature& tSig = sigsOfDihedrals[idx];
01214             tSig.output(txtOfp);
01215         }
01216 
01217         oneTypeCnt = oneAtomSig.improperSigIndices.size();
01218         fprintf(txtOfp, "%d !%sSIGS\n", oneTypeCnt, "NIMPHI");
01219         for(int j=0; j<oneTypeCnt; j++)
01220         {
01221             SigIndex idx = oneAtomSig.improperSigIndices[j];
01222             TupleSignature& tSig = sigsOfImpropers[idx];
01223             tSig.output(txtOfp);
01224         }
01225 
01226         oneTypeCnt = oneAtomSig.crosstermSigIndices.size();
01227         fprintf(txtOfp, "%d !%sSIGS\n", oneTypeCnt, "NCRTERM");
01228         for(int j=0; j<oneTypeCnt; j++)
01229         {
01230             SigIndex idx = oneAtomSig.crosstermSigIndices[j];
01231             TupleSignature& tSig = sigsOfCrossterms[idx];
01232             tSig.output(txtOfp);
01233         }
01234     }
01235 
01236     //2. Output exclusion signatures
01237     int exclSigCnt = sigsOfExclusions.size();
01238     fprintf(txtOfp, "%d !NEXCLSIGS\n", exclSigCnt);
01239     for(int i=0; i<exclSigCnt; i++)
01240     {
01241         ExclSigInfo *sig = &sigsOfExclusions[i];
01242         //first line is for full exclusions (1-2, 1-3) in the format of count offset1 offset2 offset3 ...
01243         fprintf(txtOfp, "%d", sig->fullExclOffset.size());
01244         for(int j=0; j<sig->fullExclOffset.size(); j++)
01245             fprintf(txtOfp, " %d", sig->fullExclOffset[j]);
01246         fprintf(txtOfp, "\n");
01247 
01248         //second line is for modified exclusions (1-4)
01249         fprintf(txtOfp, "%d", sig->modExclOffset.size());
01250         for(int j=0; j<sig->modExclOffset.size(); j++)
01251             fprintf(txtOfp, " %d", sig->modExclOffset[j]);
01252         fprintf(txtOfp, "\n");
01253     }
01254 
01255     //3. Output the cluster information
01256     fprintf(txtOfp, "%d !NCLUSTERS\n", g_numClusters);
01257     fprintf(txtOfp, "%d !CLUSTERCONTIGUITY\n", g_isClusterContiguous);
01258 
01259     //4. Output atom info
01260     fprintf(txtOfp, "%d !NATOM\n", g_mol->numAtoms);
01261     fprintf(txtOfp, "%d !NHYDROGENGROUP\n", g_mol->numHydrogenGroups);
01262     const float *atomOccupancy = g_mol->getOccupancyData();
01263     const float *atomBFactor = g_mol->getBFactorData();
01264     fprintf(txtOfp, "%d !OCCUPANCYVALID\n", (atomOccupancy==NULL)?0:1);
01265     fprintf(txtOfp, "%d !TEMPFACTORVALID\n", (atomBFactor==NULL)?0:1);
01266 
01267     float *zeroFloats = NULL;
01268     if(atomOccupancy==NULL || atomBFactor==NULL) {
01269         zeroFloats = new float[g_mol->numAtoms];
01270         memset(zeroFloats, 0, sizeof(float)*g_mol->numAtoms);
01271         if(atomOccupancy==NULL) atomOccupancy = (const float *)zeroFloats;
01272         if(atomBFactor==NULL) atomBFactor = (const float *)zeroFloats;
01273     }
01274 
01275     Atom *atoms = g_mol->getAtoms(); //need to output its partner and hydrogenList
01276     HydrogenGroupID *hg = g_mol->hydrogenGroup.begin();
01277 
01278 #if BINARY_PERATOM_OUTPUT
01279     //First, output magic number
01280     int magicNum = COMPRESSED_PSF_MAGICNUM;
01281     fwrite(&magicNum, sizeof(int), 1, binOfp);
01282     //Second, version number
01283     float verNum = (float)COMPRESSED_PSF_VER;
01284     fwrite(&verNum, sizeof(float), 1, binOfp);
01285     //Third, each atom info
01286     Index sIdx[8];
01287     int iIdx[7];
01288     float tmpf[2];
01289     for(int i=0; i<g_mol->numAtoms; i++)
01290     {                
01291         sIdx[0] = atomData[i].segNameIdx;
01292         sIdx[1] = atomData[i].resNameIdx;
01293         sIdx[2] = atomData[i].atomNameIdx;
01294         sIdx[3] = atomData[i].atomTypeIdx;
01295         sIdx[4] = atomData[i].chargeIdx;
01296         sIdx[5] = atomData[i].massIdx;
01297         sIdx[6] = atomData[i].atomSigIdx;
01298         sIdx[7] = atomData[i].exclSigIdx;        
01299 
01300         iIdx[0] = atomData[i].resID;
01301         iIdx[1] = eachAtomClusterID[i];
01302         iIdx[2] = atoms[i].partner;
01303         iIdx[3] = atoms[i].hydrogenList;
01304         iIdx[4] = hg[iIdx[3]].atomsInGroup;
01305         iIdx[5] = hg[iIdx[3]].GPID;
01306         iIdx[6] = hg[iIdx[3]].sortVal;
01307         tmpf[0] = atomOccupancy[i];
01308         tmpf[1] = atomBFactor[i];
01309         fwrite(sIdx, sizeof(Index), 8, binOfp);
01310         fwrite(iIdx, sizeof(int), 7, binOfp);
01311         fwrite(tmpf, sizeof(float), 2, binOfp);
01312     }
01313 #else
01314     for(int i=0; i<g_mol->numAtoms; i++)
01315     {
01316         BasicAtomInfo &one = atomData[i];
01317         int hgIdx = atoms[i].hydrogenList;
01318         fprintf(txtOfp, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %f %f\n", 
01319                 one.segNameIdx, one.resNameIdx, one.atomNameIdx,
01320                 one.atomTypeIdx, one.chargeIdx, one.massIdx, one.atomSigIdx, one.exclSigIdx, one.resID,
01321                 eachAtomClusterID[i], atoms[i].partner, hgIdx,
01322                 hg[hgIdx].atomsInGroup, hg[hgIdx].GPID, hg[hgIdx].sortVal,
01323                 atomOccupancy[i], atomBFactor[i]);
01324     }
01325 #endif
01326     //fprintf(txtOfp, "\n");
01327 
01328     if(zeroFloats) delete[] zeroFloats;
01329     delete[] atoms;
01330     g_mol->hydrogenGroup.resize(0);
01331     delete[] atomData;
01332     delete[] eachAtomClusterID;
01333 
01334     //4.Output the parameter new values if extraBonds are present.
01335     //The parameters are not needed since now extraBonds' parameters will be
01336     //read again during running the simulation
01337 
01338     //5. Output the "multiplicity" field TUPLE_array of the Parameter object
01339     fprintf(txtOfp, "!DIHEDRALPARAMARRAY\n");
01340     for(int i=0; i<g_param->NumDihedralParams; i++)
01341     {
01342         fprintf(txtOfp, "%d ", g_param->dihedral_array[i].multiplicity);
01343     }
01344     fprintf(txtOfp, "\n");
01345     fprintf(txtOfp, "!IMPROPERPARAMARRAY\n");
01346     for(int i=0; i<g_param->NumImproperParams; i++)
01347     {
01348         fprintf(txtOfp, "%d ", g_param->improper_array[i].multiplicity);
01349     }
01350     fprintf(txtOfp, "\n");
01351 #endif
01352 }
01353 
01354 void getAtomData(FILE *ifp)
01355 {
01356     char buffer[512]; //Buffer for reading from file
01357     int atomID=0;
01358     int lastAtomID=0; //to ensure atoms are in order
01359     char segmentName[11];
01360     int residueID;
01361     char residueName[11];
01362     char atomName[11];
01363     char atomType[11];
01364     Real charge;
01365     Real mass;
01366     int fieldsCnt; //Number of fields read by sscanf
01367 
01368     int numAtoms = g_mol->numAtoms;
01369 
01370     //1. parse atom data to build constant pool (atom name, mass, charge etc.)
01371     atomData = new BasicAtomInfo[numAtoms];
01372     while(atomID < numAtoms)
01373     {
01374         NAMD_read_line(ifp, buffer);
01375         //If it is blank or a comment, skip it
01376         if(NAMD_blank_string(buffer) || buffer[0]=='!')
01377             continue;
01378 
01379         //Fields are arranged as follows:
01380         //atomID, segName, resID, resName, atomName, atomType, charge, mass
01381         fieldsCnt = sscanf(buffer, "%d %s %d %s %s %s %f %f",
01382                            &atomID, segmentName, &residueID, residueName,
01383                            atomName, atomType, &charge, &mass);
01384 
01385         //check to make sure we found what we were expecting
01386         if(fieldsCnt!=8)
01387         {
01388             char errMsg[128];
01389             sprintf(errMsg, "BAD ATOM LINE FORMAT IN PSF FILE FOR ATOM %d (%s)", lastAtomID+1, buffer);
01390             NAMD_die(errMsg);
01391         }
01392 
01393         // check if this is in XPLOR format
01394         int atomTypeNum;
01395         if(sscanf(atomType, "%d", &atomTypeNum)>0)
01396             NAMD_die("Structure (psf) file is either in CHARMM format (with numbers for atoms types, the X-PLOR format using names is required) or the segment name field is empty.");
01397 
01398         //make sure the atoms were in sequence
01399         if(atomID!=lastAtomID+1)
01400         {
01401             char errMsg[128];
01402             sprintf(errMsg, "ATOM NUMBERS OUT OF ORDER AT ATOM #%d IN FSF FILE",
01403                     lastAtomID+1);
01404             NAMD_die(errMsg);
01405         }
01406 
01407         lastAtomID++;
01408 
01409         //building constant pool
01410         int poolIndex;
01411         HashString fieldName;
01412         fieldName.assign(segmentName);
01413         poolIndex = segNamePool.lookupCstPool(fieldName);
01414         if(poolIndex==-1)
01415         {
01416             segNamePool.push_back(fieldName);
01417             poolIndex = segNamePool.size()-1;
01418         }
01419         atomData[atomID-1].segNameIdx = poolIndex;
01420 
01421         //poolIndex = lookupCstPool(resIDPool, residueID);
01422         //if(poolIndex==-1)
01423         //    resIDPool.push_back(residueID);
01424         atomData[atomID-1].resID = residueID;
01425 
01426         fieldName.assign(residueName);
01427         poolIndex = resNamePool.lookupCstPool(fieldName);
01428         if(poolIndex==-1)
01429         {
01430             resNamePool.push_back(fieldName);
01431             poolIndex = resNamePool.size()-1;
01432         }
01433         atomData[atomID-1].resNameIdx = poolIndex;
01434 
01435         fieldName.assign(atomName);
01436         poolIndex = atomNamePool.lookupCstPool(fieldName);
01437         if(poolIndex==-1)
01438         {
01439             atomNamePool.push_back(fieldName);
01440             poolIndex = atomNamePool.size()-1;
01441         }
01442         atomData[atomID-1].atomNameIdx = poolIndex;
01443 
01444         fieldName.assign(atomType);
01445         poolIndex = atomTypePool.lookupCstPool(fieldName);
01446         if(poolIndex==-1)
01447         {
01448             atomTypePool.push_back(fieldName);
01449             poolIndex = atomTypePool.size()-1;
01450         }
01451         atomData[atomID-1].atomTypeIdx = poolIndex;
01452 
01453         poolIndex = chargePool.lookupCstPool(charge);
01454         if(poolIndex==-1)
01455         {
01456             chargePool.push_back(charge);
01457             poolIndex = chargePool.size()-1;
01458         }
01459         atomData[atomID-1].chargeIdx = poolIndex;
01460 
01461         poolIndex = massPool.lookupCstPool(mass);
01462         if(poolIndex==-1)
01463         {
01464             massPool.push_back(mass);
01465             poolIndex = massPool.size()-1;
01466         }
01467         atomData[atomID-1].massIdx = poolIndex;
01468     }
01469 }
01470 
01471 void buildAtomData()
01472 {
01473 #ifndef MEM_OPT_VERSION
01474     int numAtoms = g_mol->numAtoms;
01475 
01476     //1. parse atom data to build constant pool (atom name, mass, charge etc.)
01477     atomData = new BasicAtomInfo[numAtoms];
01478     Atom *atoms = g_mol->getAtoms();
01479     AtomNameInfo *atomNames = g_mol->getAtomNames();
01480     AtomSegResInfo *atomSegResids = g_mol->getAtomSegResInfo();
01481 
01482     for(int atomID=0; atomID < numAtoms; atomID++)
01483     {
01484         //building constant pool
01485         int poolIndex;
01486         HashString fieldName;
01487         fieldName.assign(atomSegResids[atomID].segname);
01488         poolIndex = segNamePool.lookupCstPool(fieldName);
01489         if(poolIndex==-1)
01490         {
01491             segNamePool.push_back(fieldName);
01492             poolIndex = segNamePool.size()-1;
01493         }
01494         atomData[atomID].segNameIdx = poolIndex;
01495         
01496         atomData[atomID].resID = atomSegResids[atomID].resid;
01497 
01498         fieldName.assign(atomNames[atomID].resname);
01499         poolIndex = resNamePool.lookupCstPool(fieldName);
01500         if(poolIndex==-1)
01501         {
01502             resNamePool.push_back(fieldName);
01503             poolIndex = resNamePool.size()-1;
01504         }
01505         atomData[atomID].resNameIdx = poolIndex;
01506 
01507         fieldName.assign(atomNames[atomID].atomname);
01508         poolIndex = atomNamePool.lookupCstPool(fieldName);
01509         if(poolIndex==-1)
01510         {
01511             atomNamePool.push_back(fieldName);
01512             poolIndex = atomNamePool.size()-1;
01513         }
01514         atomData[atomID].atomNameIdx = poolIndex;
01515 
01516         fieldName.assign(atomNames[atomID].atomtype);
01517         poolIndex = atomTypePool.lookupCstPool(fieldName);
01518         if(poolIndex==-1)
01519         {
01520             atomTypePool.push_back(fieldName);
01521             poolIndex = atomTypePool.size()-1;
01522         }
01523         atomData[atomID].atomTypeIdx = poolIndex;
01524 
01525         poolIndex = chargePool.lookupCstPool(atoms[atomID].charge);
01526         if(poolIndex==-1)
01527         {
01528             chargePool.push_back(atoms[atomID].charge);
01529             poolIndex = chargePool.size()-1;
01530         }
01531         atomData[atomID].chargeIdx = poolIndex;
01532 
01533         poolIndex = massPool.lookupCstPool(atoms[atomID].mass);
01534         if(poolIndex==-1)
01535         {
01536             massPool.push_back(atoms[atomID].mass);
01537             poolIndex = massPool.size()-1;
01538         }
01539         atomData[atomID].massIdx = poolIndex;
01540     }
01541 
01542     //Free those space to reduce transient memory usage
01543     //delete [] atoms; (deleted until per-atom info is output)
01544     delete [] atomNames;
01545     delete [] atomSegResids;
01546 #endif
01547 }
01548 
01549 
01550 void getExtraBonds(StringList *file)
01551 {
01552     char err_msg[512];
01553     int a1, a2, a3, a4;
01554     float k, ref;
01555 
01556     int numAtoms = g_mol->numAtoms;
01557 
01558     if(!file)
01559     {
01560         NAMD_die("NO EXTRA BONDS FILES SPECIFIED");
01561     }
01562 
01563     for ( ; file; file = file->next )
01564     {  // loop over files
01565         FILE *f = fopen(file->data,"r");
01566         if ( ! f )
01567         {
01568             sprintf(err_msg, "UNABLE TO OPEN EXTRA BONDS FILE %s", file->data);
01569             NAMD_err(err_msg);
01570         }
01571         else
01572         {
01573             iout << iINFO << "READING EXTRA BONDS FILE " << file->data <<"\n"<<endi;
01574         }
01575 
01576         while ( 1 )
01577         {
01578             char buffer[512];
01579             int ret_code;
01580             int poolIndex;
01581             do
01582             {
01583                 ret_code = NAMD_read_line(f, buffer);
01584             }
01585             while ( (ret_code==0) && (NAMD_blank_string(buffer)) );
01586             if (ret_code!=0)
01587                 break;
01588 
01589             char type[512];
01590             sscanf(buffer,"%s",type);
01591 
01592 #define CHECKATOMID(ATOMID) if ( ATOMID < 0 || ATOMID >= numAtoms ) badatom = 1;
01593 
01594             int badline = 0;
01595             int badatom = 0;
01596             if ( ! strncasecmp(type,"bond",4) )
01597             {
01598                 if ( sscanf(buffer, "%s %d %d %f %f %s",
01599                             type, &a1, &a2, &k, &ref, err_msg) != 5 )
01600                     badline = 1;
01601                 else
01602                 {
01603                     CHECKATOMID(a1)
01604                     CHECKATOMID(a2)
01605                 }
01606                 Bond tmp;                
01607                 tmp.atom1 = a1;
01608                 tmp.atom2 = a2;
01609 
01610                 BondValue tmpv;
01611                 tmpv.k = k;
01612                 tmpv.x0 = ref;
01613 
01614                 poolIndex = lookupCstPool(extraBondParams, tmpv);
01615                 if(poolIndex==-1){               
01616                     extraBondParams.push_back(tmpv);
01617                     poolIndex = extraBondParams.size()-1;
01618                 }                 
01619                 tmp.bond_type = g_param->NumBondParams + poolIndex;
01620                 extraBonds.push_back(tmp);
01621             }
01622             else if ( ! strncasecmp(type,"angle",4) )
01623             {
01624                 if ( sscanf(buffer, "%s %d %d %d %f %f %s",
01625                             type, &a1, &a2, &a3, &k, &ref, err_msg) != 6 )
01626                     badline = 1;
01627                 else
01628                 {
01629                     CHECKATOMID(a1)
01630                     CHECKATOMID(a2)
01631                     CHECKATOMID(a3)
01632                 }
01633                 Angle tmp;
01634                 tmp.atom1 = a1;
01635                 tmp.atom2 = a2;
01636                 tmp.atom3 = a3;
01637                 
01638                 AngleValue tmpv;
01639                 tmpv.k = k;
01640                 tmpv.theta0 = ref / 180. * PI;
01641                 tmpv.k_ub = 0;
01642                 tmpv.r_ub = 0;
01643 
01644                 poolIndex = lookupCstPool(extraAngleParams, tmpv);
01645                 if(poolIndex==-1){               
01646                     extraAngleParams.push_back(tmpv);
01647                     poolIndex = extraAngleParams.size()-1;
01648                 }                 
01649                 tmp.angle_type = g_param->NumAngleParams + poolIndex;
01650                 extraAngles.push_back(tmp);
01651             }
01652             else if ( ! strncasecmp(type,"dihedral",4) )
01653             {
01654                 if ( sscanf(buffer, "%s %d %d %d %d %f %f %s",
01655                             type, &a1, &a2, &a3, &a4, &k, &ref, err_msg) != 7 )
01656                     badline = 1;
01657                 else
01658                 {
01659                     CHECKATOMID(a1)
01660                     CHECKATOMID(a2)
01661                     CHECKATOMID(a3)
01662                     CHECKATOMID(a4)
01663                 }
01664                 Dihedral tmp;
01665                 tmp.atom1 = a1;
01666                 tmp.atom2 = a2;
01667                 tmp.atom3 = a3;
01668                 tmp.atom4 = a4;
01669                 
01670                 DihedralValue tmpv;
01671                 tmpv.multiplicity = 1;
01672                 tmpv.values[0].n = 0;
01673                 tmpv.values[0].k = k;
01674                 tmpv.values[0].delta = ref / 180. * PI;
01675 
01676                 poolIndex = lookupCstPool(extraDihedralParams, tmpv);
01677                 if(poolIndex==-1){               
01678                     extraDihedralParams.push_back(tmpv);
01679                     poolIndex = extraDihedralParams.size()-1;
01680                 }                 
01681                 tmp.dihedral_type = g_param->NumDihedralParams + poolIndex;
01682                 extraDihedrals.push_back(tmp);
01683             }
01684             else if ( ! strncasecmp(type,"improper",4) )
01685             {
01686                 if ( sscanf(buffer, "%s %d %d %d %d %f %f %s",
01687                             type, &a1, &a2, &a3, &a4, &k, &ref, err_msg) != 7 )
01688                     badline = 1;
01689                 else
01690                 {
01691                     CHECKATOMID(a1)
01692                     CHECKATOMID(a2)
01693                     CHECKATOMID(a3)
01694                     CHECKATOMID(a4)
01695                 }
01696                 Improper tmp;
01697                 tmp.atom1 = a1;
01698                 tmp.atom2 = a2;
01699                 tmp.atom3 = a3;
01700                 tmp.atom4 = a4;
01701                 
01702                 ImproperValue tmpv;
01703                 tmpv.multiplicity = 1;
01704                 tmpv.values[0].n = 0;
01705                 tmpv.values[0].k = k;
01706                 tmpv.values[0].delta = ref / 180. * PI;
01707 
01708                 poolIndex = lookupCstPool(extraImproperParams, tmpv);
01709                 if(poolIndex==-1){               
01710                     extraImproperParams.push_back(tmpv);
01711                     poolIndex = extraImproperParams.size()-1;
01712                 }                 
01713                 tmp.improper_type = g_param->NumImproperParams + poolIndex;
01714                 extraImpropers.push_back(tmp);
01715             }
01716             else if ( ! strncasecmp(type,"#",1) )
01717             {
01718                 continue;  // comment
01719             }
01720             else
01721             {
01722                 badline = 1;
01723             }
01724 #undef CHECKATOMID
01725             if ( badline )
01726             {
01727                 sprintf(err_msg, "BAD LINE IN EXTRA BONDS FILE %s: %s",
01728                         file->data, buffer);
01729                 NAMD_die(err_msg);
01730             }
01731             if ( badatom )
01732             {
01733                 sprintf(err_msg, "BAD ATOM ID IN EXTRA BONDS FILE %s: %s",
01734                         file->data, buffer);
01735                 NAMD_die(err_msg);
01736             }
01737         }
01738         fclose(f);
01739     }  // loop over files
01740 }
01741 
01742 void buildParamData()
01743 {
01744 
01745 }
01746 
01747 //In this function, safety check will also be performed:
01748 //1. bond itself 2.duplicate bonds such as (a, b) & (b, a)
01749 void getBondData(FILE *fd)
01750 {
01751 
01752     //first read bonds
01753     int atom_nums[2];  // Atom indexes for the bonded atoms
01754     char atom1name[11];  // Atom type for atom #1
01755     char atom2name[11];  // Atom type for atom #2
01756     register int j;      // Loop counter
01757     int num_read=0;    // Number of bonds read so far
01758 
01759     int numBonds = g_mol->numBonds;
01760     int origNumBonds = numBonds;   // number of bonds in file header
01761 
01762     /*  Allocate the array to hold the bonds      */
01763     Bond *bonds=new Bond[numBonds + extraBonds.size()];
01764 
01765     if (bonds == NULL)
01766     {
01767         NAMD_die("memory allocations failed in Molecule::read_bonds");
01768     }
01769 
01770     /*  Loop through and read in all the bonds      */
01771     while (num_read < numBonds)
01772     {
01773         /*  Loop and read in the two atom indexes    */
01774         for (j=0; j<2; j++)
01775         {
01776             /*  Read the atom number from the file.         */
01777             /*  Subtract 1 to convert the index from the    */
01778             /*  1 to NumAtoms used in the file to the       */
01779             /*  0 to NumAtoms-1 that we need    */
01780             atom_nums[j]=NAMD_read_int(fd, "BONDS")-1;
01781 
01782             /*  Check to make sure the index isn't too big  */
01783             if (atom_nums[j] >= g_mol->numAtoms)
01784             {
01785                 char err_msg[128];
01786 
01787                 sprintf(err_msg, "BOND INDEX %d GREATER THAN NATOM %d IN BOND # %d IN PSF FILE", atom_nums[j]+1, g_mol->numAtoms, num_read+1);
01788                 NAMD_die(err_msg);
01789             }
01790         }
01791 
01792         if(atom_nums[0] == atom_nums[1])
01793         { //bond to itself
01794             char err_msg[128];
01795             sprintf(err_msg, "ATOM %d is bonded to itself!", atom_nums[0]+1);
01796             NAMD_die(err_msg);
01797         }
01798 
01799         /*  Get the atom type for the two atoms.  When we query */
01800         /*  the parameter object, we need to send the atom type */
01801         /*  that is alphabetically first as atom 1.    */
01802         const char *atom1Type = atomTypePool[atomData[atom_nums[0]].atomTypeIdx].c_str();
01803         const char *atom2Type = atomTypePool[atomData[atom_nums[1]].atomTypeIdx].c_str();
01804         if (strcasecmp(atom1Type,atom2Type) < 0)
01805         {
01806             strcpy(atom1name, atom1Type);
01807             strcpy(atom2name, atom2Type);
01808         }
01809         else
01810         {
01811             strcpy(atom2name, atom1Type);
01812             strcpy(atom1name, atom2Type);
01813         }
01814 
01815         /*  Query the parameter object for the constants for    */
01816         /*  this bond            */
01817         Bond *b = &(bonds[num_read]);
01818         g_param->assign_bond_index(atom1name, atom2name, b);
01819 
01820         /*  Assign the atom indexes to the array element  */
01821         b->atom1=atom_nums[0];
01822         b->atom2=atom_nums[1];
01823 
01824         /*  Make sure this isn't a fake bond meant for shake in x-plor.  */
01825         Real k, x0;
01826         g_param->get_bond_params(&k,&x0,b->bond_type);
01827         if ( k == 0. )
01828             --numBonds;  // fake bond
01829         else
01830             ++num_read;  // real bond
01831     }
01832 
01833     /*  Tell user about our subterfuge  */
01834     if ( numBonds != origNumBonds )
01835     {
01836         iout << iWARN << "Ignored " << origNumBonds - numBonds <<
01837         " bonds with zero force constants.\n" << endi;
01838         iout << iWARN <<
01839         "Will get H-H distance in rigid H2O from H-O-H angle.\n" << endi;
01840     }
01841 
01842     //copy extra bonds to bonds structure
01843     int numRealBonds = numBonds;
01844     for(int i=0; i<extraBonds.size(); i++)
01845         bonds[numBonds+i] = extraBonds[i];
01846     numBonds += extraBonds.size();
01847     extraBonds.clear();
01848 
01849     g_mol->numBonds = numBonds;
01850 
01851     //then creating bond's tupleSignature
01852     for(int i=0; i<numBonds; i++)
01853     {
01854         Bond *b = bonds+i;
01855         TupleSignature oneSig(1,BOND,b->bond_type);
01856         oneSig.offset[0] = b->atom2 - b->atom1;
01857         oneSig.isReal = (i<numRealBonds );
01858 
01859         int poolIndex = sigsOfBonds.lookupCstPool(oneSig);
01860         int newSig=0;
01861         if(poolIndex == -1)
01862         {
01863             sigsOfBonds.push_back(oneSig);
01864             poolIndex = (SigIndex)sigsOfBonds.size()-1;
01865             newSig=1;
01866         }
01867 
01868         if(!newSig)
01869         {//check duplicate bonds in the form of (a, b) && (a, b);
01870           CkPrintf("Checking %d\n",poolIndex);
01871           int dupIdx = lookupCstPool(eachAtomSigs[b->atom1].bondSigIndices, (SigIndex)poolIndex);
01872             if(dupIdx!=-1)
01873             {
01874                 char err_msg[128];
01875                 sprintf(err_msg, "Duplicate bond %d-%d!", b->atom1+1, b->atom2+1);
01876                 NAMD_die(err_msg);
01877             }
01878         }
01879         eachAtomSigs[b->atom1].bondSigIndices.push_back(poolIndex);
01880     }
01881 
01882     //check duplicate bonds in the form of (a, b) && (b, a)
01883     for(int i=0; i<numBonds; i++)
01884     {
01885         Bond *b=bonds+i;
01886         int atom2 = b->atom2;
01887         int thisOffset = atom2 - b->atom1;
01888         for(int j=0; j<eachAtomSigs[atom2].bondSigIndices.size(); j++)
01889         {
01890             SigIndex atom2BondId = eachAtomSigs[atom2].bondSigIndices[j];
01891             TupleSignature *secSig = &(sigsOfBonds[atom2BondId]);
01892             if(thisOffset== -(secSig->offset[0]))
01893             {
01894                 char err_msg[128];
01895                 sprintf(err_msg, "Duplicate bond %d-%d because two atoms are just reversed!", b->atom1+1, atom2+1);
01896                 NAMD_die(err_msg);
01897             }
01898         }
01899     }      
01900 
01901     //building clusters for this simulation system in two steps
01902     //1. create a list for each atom where each atom in the list is bonded with that atom
01903     vector<int> *atomListOfBonded = new vector<int>[g_mol->numAtoms];
01904 
01905     for(int i=0; i<numRealBonds; i++)
01906     {
01907         Bond *b=bonds+i;
01908         int atom1 = b->atom1;
01909         int atom2 = b->atom2;
01910         atomListOfBonded[atom1].push_back(atom2);
01911         atomListOfBonded[atom2].push_back(atom1);
01912     }
01913 
01914     delete [] bonds;
01915 
01916     //2. using breadth-first-search to build the clusters. Here, we avoid recursive call
01917     // because the depth of calls may be of thousands which will blow up the stack, and
01918     //recursive call is slower than the stack-based BFS.
01919     //Considering such structure
01920     //1->1245; 7->1243; 1243->1245
01921     eachAtomClusterID = new int[g_mol->numAtoms];
01922     for(int i=0; i<g_mol->numAtoms; i++)
01923         eachAtomClusterID[i] = -1;
01924 
01925     for(int i=0; i<g_mol->numAtoms; i++)
01926     {
01927         int curClusterID=eachAtomClusterID[i];
01928         if(curClusterID==-1)
01929         {
01930             curClusterID=i;
01931         }
01932 
01933         deque<int> toVisitAtoms;
01934         toVisitAtoms.push_back(i);
01935         while(!toVisitAtoms.empty())
01936         {
01937             int visAtomID = toVisitAtoms.front();
01938             toVisitAtoms.pop_front();
01939             eachAtomClusterID[visAtomID] = curClusterID;
01940             for(int j=0; j<atomListOfBonded[visAtomID].size(); j++)
01941             {
01942                 int otherAtom = atomListOfBonded[visAtomID][j];
01943                 if(eachAtomClusterID[otherAtom]!=curClusterID)
01944                     toVisitAtoms.push_back(otherAtom);
01945             }
01946         }
01947     }
01948 
01949     //Now the clusterID of each atom should be usually in the non-decreasing order.
01950     //In other words, the atom ids of a cluster are generally contiguous.
01951     //If this is the case, the temporary memory usage of output IO during
01952     //the simulation can be dramatically reduced. So g_isClusterContiguous
01953     //is used to differentiate the two cases
01954 
01955     int curClusterID;
01956     int prevClusterID=eachAtomClusterID[0];
01957     int curClusterSize=1;
01958     g_isClusterContiguous = 1;
01959     for(int i=1; i<g_mol->numAtoms; i++)
01960     {
01961         curClusterID = eachAtomClusterID[i];
01962         if(curClusterID > prevClusterID)
01963         {
01964             eachClusterSize.push_back(curClusterSize);
01965             curClusterSize=1;
01966         }
01967         else if(curClusterID == prevClusterID)
01968         {
01969             curClusterSize++;
01970         }
01971         else
01972         { 
01973             g_isClusterContiguous = 0;
01974             break;
01975         }
01976         prevClusterID = curClusterID;
01977     }
01978 
01979 
01980     //Now iterate over the cluster size again to filter out the repeating cluster size.
01981     //There are two cases:
01982     //1. if the cluster id of atoms is monotonically increasing, the size of the cluster can be used
01983     //as this cluster's signature.
01984     //After this, eachAtomClusterID will store the cluster signature. Only the atom whose id is "clustersize"
01985     //will store the size. Others will be -1
01986     //2. if the cluster id of atoms is not monotonically increasing, in other words,
01987     //the atom ids of a cluster are not contiguous, then eachAtomClusterID remains
01988     //unchanged.
01989 
01990     if(g_isClusterContiguous) {
01991         eachClusterSize.push_back(curClusterSize); //record the last sequence of cluster
01992         int aid=0;
01993         for(int clusterIdx=0; clusterIdx<eachClusterSize.size(); clusterIdx++)
01994         {
01995             int curSize = eachClusterSize[clusterIdx];
01996             eachAtomClusterID[aid] = curSize;
01997             for(int i=aid+1; i<aid+curSize; i++)
01998                 eachAtomClusterID[i] = -1;
01999             aid += curSize;
02000         }
02001         g_numClusters = eachClusterSize.size();
02002         eachClusterSize.clear();
02003     }else{
02004         eachClusterSize.clear();
02005         //reiterate over the atoms to figure out the number of clusters
02006         char *clusters = new char[g_mol->numAtoms];
02007         memset(clusters, 0, sizeof(char)*g_mol->numAtoms);
02008         for(int i=0; i<g_mol->numAtoms; i++) {
02009             clusters[eachAtomClusterID[i]] = 1;
02010         }
02011         
02012         for(int zeroPos=0; zeroPos<g_mol->numAtoms; zeroPos++) {
02013             if(clusters[zeroPos]==0) {
02014                 //since the cluster ids are contiguous integers starting from 0,
02015                 //if it becomes zero, we know the number of clusters is zeroPos
02016                 g_numClusters = zeroPos;
02017                 break;
02018             }
02019         }
02020         delete [] clusters;
02021     }
02022 
02023     //check whether cluster is built correctly
02024     /*printf("num clusters: %d\n", eachClusterSize.size());
02025     FILE *checkFile = fopen("cluster.opt", "w");
02026     for(int i=0; i<g_mol->numAtoms; i++)  fprintf(checkFile, "%d\n", eachAtomClusterID[i]);
02027     fclose(checkFile);*/
02028 
02029     
02030     for(int i=0; i<g_mol->numAtoms; i++)
02031         atomListOfBonded[i].clear();
02032     delete [] atomListOfBonded;
02033 }
02034 
02035 void buildBondData()
02036 {
02037 #ifndef MEM_OPT_VERSION
02038     Bond *bonds = g_mol->getAllBonds();    
02039 
02040     //then creating bond's tupleSignature
02041     for(int i=0; i<g_mol->numBonds; i++)
02042     {
02043         Bond *b = bonds+i;
02044         TupleSignature oneSig(1,BOND,b->bond_type);
02045         oneSig.offset[0] = b->atom2 - b->atom1;
02046         oneSig.isReal = (i<g_mol->numRealBonds);
02047 
02048         int poolIndex = sigsOfBonds.lookupCstPool(oneSig);
02049         int newSig=0;
02050         if(poolIndex == -1)
02051         {
02052             sigsOfBonds.push_back(oneSig);
02053             poolIndex = (SigIndex)sigsOfBonds.size()-1;
02054             newSig=1;
02055         }
02056 
02057       if(!newSig)
02058         {//check duplicate bonds in the form of (a, b) && (a, b);
02059           int dupIdx = lookupCstPool(eachAtomSigs[b->atom1].bondSigIndices, (SigIndex)poolIndex);
02060             if(dupIdx!=-1)
02061             {
02062                 char err_msg[128];
02063                 sprintf(err_msg, "Duplicate bond %d-%d!", b->atom1+1, b->atom2+1);
02064                 NAMD_die(err_msg);
02065             }
02066         }
02067         eachAtomSigs[b->atom1].bondSigIndices.push_back(poolIndex);
02068     }
02069 
02070     //check duplicate bonds in the form of (a, b) && (b, a)
02071     for(int i=0; i<g_mol->numBonds; i++)
02072     {
02073         Bond *b=bonds+i;
02074         int atom2 = b->atom2;
02075         int thisOffset = atom2 - b->atom1;
02076         for(int j=0; j<eachAtomSigs[atom2].bondSigIndices.size(); j++)
02077         {
02078             SigIndex atom2BondId = eachAtomSigs[atom2].bondSigIndices[j];
02079             TupleSignature *secSig = &(sigsOfBonds[atom2BondId]);
02080             if(thisOffset== -(secSig->offset[0]))
02081             {
02082                 char err_msg[128];
02083                 sprintf(err_msg, "Duplicate bond %d-%d because two atoms are just reversed!", b->atom1+1, atom2+1);
02084                 NAMD_die(err_msg);
02085             }
02086         }
02087     }      
02088 
02089     //building clusters for this simulation system in two steps
02090     //1. create a list for each atom where each atom in the list is bonded with that atom
02091     vector<int> *atomListOfBonded = new vector<int>[g_mol->numAtoms];
02092 
02093     for(int i=0; i<g_mol->numRealBonds; i++)
02094     {
02095         Bond *b=bonds+i;
02096         int atom1 = b->atom1;
02097         int atom2 = b->atom2;
02098         atomListOfBonded[atom1].push_back(atom2);
02099         atomListOfBonded[atom2].push_back(atom1);
02100     }
02101 
02102     delete [] bonds;
02103 
02104     //2. using breadth-first-search to build the clusters. Here, we avoid recursive call
02105     // because the depth of calls may be of thousands which will blow up the stack, and
02106     //recursive call is slower than the stack-based BFS.
02107     //Considering such structure
02108     //1->1245; 7->1243; 1243->1245
02109     eachAtomClusterID = new int[g_mol->numAtoms];
02110     for(int i=0; i<g_mol->numAtoms; i++)
02111         eachAtomClusterID[i] = -1;
02112 
02113     for(int i=0; i<g_mol->numAtoms; i++)
02114     {
02115         int curClusterID=eachAtomClusterID[i];
02116         if(curClusterID==-1)
02117         {
02118             curClusterID=i;
02119         }
02120 
02121         deque<int> toVisitAtoms;
02122         toVisitAtoms.push_back(i);
02123         while(!toVisitAtoms.empty())
02124         {
02125             int visAtomID = toVisitAtoms.front();
02126             toVisitAtoms.pop_front();
02127             eachAtomClusterID[visAtomID] = curClusterID;
02128             for(int j=0; j<atomListOfBonded[visAtomID].size(); j++)
02129             {
02130                 int otherAtom = atomListOfBonded[visAtomID][j];
02131                 if(eachAtomClusterID[otherAtom]!=curClusterID)
02132                     toVisitAtoms.push_back(otherAtom);
02133             }
02134         }
02135     }
02136 
02137     //Now the clusterID of each atom should be usually in the non-decreasing order.
02138     //In other words, the atom ids of a cluster are generally contiguous.
02139     //If this is the case, the temporary memory usage of output IO during
02140     //the simulation can be dramatically reduced. So g_isClusterContiguous
02141     //is used to differentiate the two cases
02142 
02143     int curClusterID;
02144     int prevClusterID=eachAtomClusterID[0];
02145     int curClusterSize=1;
02146     g_isClusterContiguous = 1;
02147     for(int i=1; i<g_mol->numAtoms; i++)
02148     {
02149         curClusterID = eachAtomClusterID[i];
02150         if(curClusterID > prevClusterID)
02151         {
02152             eachClusterSize.push_back(curClusterSize);
02153             curClusterSize=1;
02154         }
02155         else if(curClusterID == prevClusterID)
02156         {
02157             curClusterSize++;
02158         }
02159         else
02160         { 
02161             g_isClusterContiguous = 0;
02162             break;
02163         }
02164         prevClusterID = curClusterID;
02165     }
02166 
02167 
02168     //Now iterate over the cluster size again to filter out the repeating cluster size.
02169     //There are two cases:
02170     //1. if the cluster id of atoms is monotonically increasing, the size of the cluster can be used
02171     //as this cluster's signature.
02172     //After this, eachAtomClusterID will store the cluster signature. Only the atom whose id is "clustersize"
02173     //will store the size. Others will be -1
02174     //2. if the cluster id of atoms is not monotonically increasing, in other words,
02175     //the atom ids of a cluster are not contiguous, then eachAtomClusterID remains
02176     //unchanged.
02177 
02178     if(g_isClusterContiguous) {
02179         eachClusterSize.push_back(curClusterSize); //record the last sequence of cluster
02180         int aid=0;
02181         for(int clusterIdx=0; clusterIdx<eachClusterSize.size(); clusterIdx++)
02182         {
02183             int curSize = eachClusterSize[clusterIdx];
02184             eachAtomClusterID[aid] = curSize;
02185             for(int i=aid+1; i<aid+curSize; i++)
02186                 eachAtomClusterID[i] = -1;
02187             aid += curSize;
02188         }
02189         g_numClusters = eachClusterSize.size();
02190         eachClusterSize.clear();
02191     }else{
02192         eachClusterSize.clear();
02193         //reiterate over the atoms to figure out the number of clusters
02194         char *clusters = new char[g_mol->numAtoms];
02195         memset(clusters, 0, sizeof(char)*g_mol->numAtoms);
02196         for(int i=0; i<g_mol->numAtoms; i++) {
02197             clusters[eachAtomClusterID[i]] = 1;
02198         }
02199         
02200         for(int zeroPos=0; zeroPos<g_mol->numAtoms; zeroPos++) {
02201             if(clusters[zeroPos]==0) {
02202                 //since the cluster ids are contiguous integers starting from 0,
02203                 //if it becomes zero, we know the number of clusters is zeroPos
02204                 g_numClusters = zeroPos;
02205                 break;
02206             }
02207         }
02208         delete [] clusters;
02209     }
02210 
02211     //check whether cluster is built correctly
02212     /*printf("num clusters: %d\n", eachClusterSize.size());
02213     FILE *checkFile = fopen("cluster.opt", "w");
02214     for(int i=0; i<g_mol->numAtoms; i++)  fprintf(checkFile, "%d\n", eachAtomClusterID[i]);
02215     fclose(checkFile);*/
02216 
02217     
02218     for(int i=0; i<g_mol->numAtoms; i++)
02219         atomListOfBonded[i].clear();
02220     delete [] atomListOfBonded;
02221 #endif
02222 }
02223 
02224 void getAngleData(FILE *fd)
02225 {
02226 
02227     int atom_nums[3];  //  Atom numbers for the three atoms
02228     char atom1name[11];  //  Atom type for atom 1
02229     char atom2name[11];  //  Atom type for atom 2
02230     char atom3name[11];  //  Atom type for atom 3
02231     register int j;      //  Loop counter
02232     int num_read=0;    //  Number of angles read so far
02233 
02234     int numAngles = g_mol->numAngles;
02235     int origNumAngles = numAngles;  // Number of angles in file
02236     /*  Alloc the array of angles          */
02237     Angle *angles=new Angle[numAngles + extraAngles.size()];
02238 
02239     if (angles == NULL)
02240     {
02241         NAMD_die("memory allocation failed in Molecule::read_angles");
02242     }
02243 
02244     /*  Loop through and read all the angles      */
02245     while (num_read < numAngles)
02246     {
02247         /*  Loop through the 3 atom indexes in the current angle*/
02248         for (j=0; j<3; j++)
02249         {
02250             /*  Read the atom number from the file.         */
02251             /*  Subtract 1 to convert the index from the    */
02252             /*  1 to NumAtoms used in the file to the       */
02253             /*  0 to NumAtoms-1 that we need    */
02254             atom_nums[j]=NAMD_read_int(fd, "ANGLES")-1;
02255 
02256             /*  Check to make sure the atom index doesn't   */
02257             /*  exceed the Number of Atoms      */
02258             if (atom_nums[j] >= g_mol->numAtoms)
02259             {
02260                 char err_msg[128];
02261 
02262                 sprintf(err_msg, "ANGLES INDEX %d GREATER THAN NATOM %d IN ANGLES # %d IN PSF FILE", atom_nums[j]+1, g_mol->numAtoms, num_read+1);
02263                 NAMD_die(err_msg);
02264             }
02265         }
02266 
02267         /*  Place the bond name that is alphabetically first  */
02268         /*  in the atom1name.  This is OK since the order of    */
02269         /*  atom1 and atom3 are interchangable.  And to search  */
02270         /*  the tree of angle parameters, we need the order     */
02271         /*  to be predictable.          */
02272 
02273         const char *atom1Type = atomTypePool[atomData[atom_nums[0]].atomTypeIdx].c_str();
02274         const char *atom2Type = atomTypePool[atomData[atom_nums[1]].atomTypeIdx].c_str();
02275         const char *atom3Type = atomTypePool[atomData[atom_nums[2]].atomTypeIdx].c_str();
02276 
02277         if (strcasecmp(atom1Type,atom2Type) < 0)
02278         {
02279             strcpy(atom1name, atom1Type);
02280             strcpy(atom2name, atom2Type);
02281             strcpy(atom3name, atom3Type);
02282         }
02283         else
02284         {
02285             strcpy(atom1name, atom1Type);
02286             strcpy(atom2name, atom2Type);
02287             strcpy(atom3name, atom3Type);
02288         }
02289 
02290         /*  Get the constant values for this bond from the  */
02291         /*  parameter object          */
02292         g_param->assign_angle_index(atom1name, atom2name,
02293                                     atom3name, &(angles[num_read]));
02294 
02295         /*  Assign the three atom indices      */
02296         angles[num_read].atom1=atom_nums[0];
02297         angles[num_read].atom2=atom_nums[1];
02298         angles[num_read].atom3=atom_nums[2];
02299 
02300         /*  Make sure this isn't a fake angle meant for shake in x-plor.  */
02301         Real k, t0, k_ub, r_ub;
02302         g_param->get_angle_params(&k,&t0,&k_ub,&r_ub,angles[num_read].angle_type);
02303         if ( k == 0. && k_ub == 0. )
02304             --numAngles;  // fake angle
02305         else
02306             ++num_read;  // real angle
02307     }
02308 
02309     /*  Tell user about our subterfuge  */
02310     if ( numAngles != origNumAngles )
02311     {
02312         iout << iWARN << "Ignored " << origNumAngles - numAngles <<
02313         " angles with zero force constants.\n" << endi;
02314     }
02315 
02316     //copy extra angles to angles structure
02317     for(int i=0; i<extraAngles.size(); i++)
02318         angles[numAngles+i] = extraAngles[i];
02319     numAngles += extraAngles.size();
02320     extraAngles.clear();
02321 
02322     g_mol->numAngles = numAngles;
02323 
02324     //create angles' tupleSignature
02325     for(int i=0; i<numAngles; i++)
02326     {
02327         Angle *tuple = angles+i;
02328         TupleSignature oneSig(2,ANGLE,tuple->angle_type);
02329         int offset[2];
02330         offset[0] = tuple->atom2 - tuple->atom1;
02331         offset[1] = tuple->atom3 - tuple->atom1;
02332         oneSig.setOffsets(offset);
02333 
02334         int poolIndex = sigsOfAngles.lookupCstPool(oneSig);
02335         if(poolIndex == -1)
02336         {
02337             sigsOfAngles.push_back(oneSig);
02338             poolIndex = (SigIndex)sigsOfAngles.size()-1;
02339         }
02340         eachAtomSigs[tuple->atom1].angleSigIndices.push_back(poolIndex);
02341     }
02342 
02343     delete [] angles;
02344 
02345 }
02346 
02347 void buildAngleData()
02348 {
02349 #ifndef MEM_OPT_VERSION
02350     Angle *angles = g_mol->getAllAngles();
02351     //create angles' tupleSignature
02352     for(int i=0; i<g_mol->numAngles; i++)
02353     {
02354         Angle *tuple = angles+i;
02355         TupleSignature oneSig(2,ANGLE,tuple->angle_type);
02356         int offset[2];
02357         offset[0] = tuple->atom2 - tuple->atom1;
02358         offset[1] = tuple->atom3 - tuple->atom1;
02359         oneSig.setOffsets(offset);
02360 
02361         int poolIndex = sigsOfAngles.lookupCstPool(oneSig);
02362         if(poolIndex == -1)
02363         {
02364             sigsOfAngles.push_back(oneSig);
02365             poolIndex = (SigIndex)sigsOfAngles.size()-1;
02366         }
02367         eachAtomSigs[tuple->atom1].angleSigIndices.push_back(poolIndex);
02368     }
02369     delete [] angles;
02370 #endif
02371 }
02372 
02373 void getDihedralData(FILE *fd)
02374 {
02375 
02376     int atom_nums[4];  // The 4 atom indexes
02377     int last_atom_nums[4];  // Atom numbers from previous bond
02378     char atom1name[11];  // Atom type for atom 1
02379     char atom2name[11];  // Atom type for atom 2
02380     char atom3name[11];  // Atom type for atom 3
02381     char atom4name[11];  // Atom type for atom 4
02382     register int j;      // loop counter
02383     int num_read=0;    // number of dihedrals read so far
02384     int multiplicity=1;  // multiplicity of the current bond
02385     Bool duplicate_bond;  // Is this a duplicate of the last bond
02386     int num_unique=0;   // Number of unique dihedral bonds
02387 
02388     //  Initialize the array used to check for duplicate dihedrals
02389     for (j=0; j<4; j++)
02390         last_atom_nums[j] = -1;
02391 
02392     int numDihedrals = g_mol->numDihedrals;
02393     int numAtoms = g_mol->numAtoms;
02394 
02395     /*  Allocate an array to hold the Dihedrals      */
02396     Dihedral *dihedrals = new Dihedral[numDihedrals + extraDihedrals.size()];
02397 
02398     if (dihedrals == NULL)
02399     {
02400         NAMD_die("memory allocation failed in Molecule::read_dihedrals");
02401     }
02402 
02403     /*  Loop through and read all the dihedrals      */
02404     while (num_read < numDihedrals)
02405     {
02406         duplicate_bond = TRUE;
02407 
02408         /*  Loop through and read the 4 indexes for this bond   */
02409         for (j=0; j<4; j++)
02410         {
02411             /*  Read the atom number from the file.         */
02412             /*  Subtract 1 to convert the index from the    */
02413             /*  1 to NumAtoms used in the file to the       */
02414             /*  0 to NumAtoms-1 that we need    */
02415             atom_nums[j]=NAMD_read_int(fd, "DIHEDRALS")-1;
02416 
02417             /*  Check for an atom index that is too large  */
02418             if (atom_nums[j] >= numAtoms)
02419             {
02420                 char err_msg[128];
02421 
02422                 sprintf(err_msg, "DIHEDRALS INDEX %d GREATER THAN NATOM %d IN DIHEDRALS # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
02423                 NAMD_die(err_msg);
02424             }
02425 
02426             //  Check to see if this atom matches the last bond
02427             if (atom_nums[j] != last_atom_nums[j])
02428             {
02429                 duplicate_bond = FALSE;
02430             }
02431 
02432             last_atom_nums[j] = atom_nums[j];
02433         }
02434 
02435         /*  Get the atom types for the 4 atoms so we can look  */
02436         /*  up the constants in the parameter object    */
02437         const char *atom1Type = atomTypePool[atomData[atom_nums[0]].atomTypeIdx].c_str();
02438         const char *atom2Type = atomTypePool[atomData[atom_nums[1]].atomTypeIdx].c_str();
02439         const char *atom3Type = atomTypePool[atomData[atom_nums[2]].atomTypeIdx].c_str();
02440         const char *atom4Type = atomTypePool[atomData[atom_nums[3]].atomTypeIdx].c_str();
02441         strcpy(atom1name, atom1Type);
02442         strcpy(atom2name, atom2Type);
02443         strcpy(atom3name, atom3Type);
02444         strcpy(atom4name, atom4Type);
02445 
02446         //  Check to see if this is really a new bond or just
02447         //  a repeat of the last one
02448         if (duplicate_bond)
02449         {
02450             //  This is a duplicate, so increase the multiplicity
02451             multiplicity++;
02452 
02453             if (multiplicity == 2)
02454             {
02455                 g_mol->numMultipleDihedrals++;
02456             }
02457         }
02458         else
02459         {
02460             multiplicity=1;
02461             num_unique++;
02462         }
02463 
02464         /*  Get the constants for this dihedral bond    */
02465         g_param->assign_dihedral_index(atom1name, atom2name,
02466                                        atom3name, atom4name, &(dihedrals[num_unique-1]),
02467                                        multiplicity);
02468 
02469         /*  Assign the atom indexes        */
02470         dihedrals[num_unique-1].atom1=atom_nums[0];
02471         dihedrals[num_unique-1].atom2=atom_nums[1];
02472         dihedrals[num_unique-1].atom3=atom_nums[2];
02473         dihedrals[num_unique-1].atom4=atom_nums[3];
02474 
02475         num_read++;
02476     }
02477 
02478     //copy extra dihedrals to dihedrals structure
02479     if(extraDihedrals.size()>0){
02480         iout << iWARN << "It's your responsibility to ensure there is no duplicates among these extra dihedrals\n" << endi;
02481     }
02482     for(int i=0; i<extraDihedrals.size(); i++)
02483         dihedrals[num_unique+i] = extraDihedrals[i];
02484     num_unique += extraDihedrals.size();
02485     extraDihedrals.clear();
02486 
02487     g_mol->numDihedrals = num_unique;
02488 
02489     //create dihedrals' tupleSignature
02490     for(int i=0; i<num_unique; i++)
02491     {
02492         Dihedral *tuple = dihedrals+i;
02493         TupleSignature oneSig(3,DIHEDRAL,tuple->dihedral_type);
02494         int offset[3];
02495         offset[0] = tuple->atom2 - tuple->atom1;
02496         offset[1] = tuple->atom3 - tuple->atom1;
02497         offset[2] = tuple->atom4 - tuple->atom1;
02498         oneSig.setOffsets(offset);
02499 
02500         int poolIndex = sigsOfDihedrals.lookupCstPool(oneSig);
02501         if(poolIndex == -1)
02502         {
02503             sigsOfDihedrals.push_back(oneSig);
02504             poolIndex = (SigIndex)sigsOfDihedrals.size()-1;
02505         }
02506         eachAtomSigs[tuple->atom1].dihedralSigIndices.push_back(poolIndex);
02507     }
02508 
02509     delete[] dihedrals;
02510 
02511 }
02512 
02513 void buildDihedralData()
02514 {
02515 #ifndef MEM_OPT_VERSION
02516     Dihedral *dihedrals = g_mol->getAllDihedrals();    
02517 
02518     //create dihedrals' tupleSignature
02519     for(int i=0; i<g_mol->numDihedrals; i++)
02520     {
02521         Dihedral *tuple = dihedrals+i;
02522         TupleSignature oneSig(3,DIHEDRAL,tuple->dihedral_type);
02523         int offset[3];
02524         offset[0] = tuple->atom2 - tuple->atom1;
02525         offset[1] = tuple->atom3 - tuple->atom1;
02526         offset[2] = tuple->atom4 - tuple->atom1;
02527         oneSig.setOffsets(offset);
02528 
02529         int poolIndex = sigsOfDihedrals.lookupCstPool(oneSig);
02530         if(poolIndex == -1)
02531         {
02532             sigsOfDihedrals.push_back(oneSig);
02533             poolIndex = (SigIndex)sigsOfDihedrals.size()-1;
02534         }
02535         eachAtomSigs[tuple->atom1].dihedralSigIndices.push_back(poolIndex);
02536     }
02537 
02538     delete[] dihedrals;
02539 #endif
02540 }
02541 
02542 void getImproperData(FILE *fd)
02543 {
02544     int atom_nums[4];  //  Atom indexes for the 4 atoms
02545     int last_atom_nums[4];  //  Atom indexes from previous bond
02546     char atom1name[11];  //  Atom type for atom 1
02547     char atom2name[11];  //  Atom type for atom 2
02548     char atom3name[11];  //  Atom type for atom 3
02549     char atom4name[11];  //  Atom type for atom 4
02550     register int j;      //  Loop counter
02551     int num_read=0;    //  Number of impropers read so far
02552     int multiplicity=1;  // multiplicity of the current bond
02553     Bool duplicate_bond;  // Is this a duplicate of the last bond
02554     int num_unique=0;   // Number of unique dihedral bonds
02555 
02556     //  Initialize the array used to look for duplicate improper
02557     //  entries.  Set them all to -1 so we know nothing will match
02558     for (j=0; j<4; j++)
02559         last_atom_nums[j] = -1;
02560 
02561     int numImpropers = g_mol->numImpropers;
02562     int numAtoms = g_mol->numAtoms;
02563 
02564     /*  Allocate the array to hold the impropers      */
02565     Improper *impropers=new Improper[numImpropers];
02566 
02567     if (impropers == NULL)
02568     {
02569         NAMD_die("memory allocation failed in Molecule::read_impropers");
02570     }
02571 
02572     /*  Loop through and read all the impropers      */
02573     while (num_read < numImpropers)
02574     {
02575         duplicate_bond = TRUE;
02576 
02577         /*  Loop through the 4 indexes for this improper  */
02578         for (j=0; j<4; j++)
02579         {
02580             /*  Read the atom number from the file.         */
02581             /*  Subtract 1 to convert the index from the    */
02582             /*  1 to NumAtoms used in the file to the       */
02583             /*  0 to NumAtoms-1 that we need    */
02584             atom_nums[j]=NAMD_read_int(fd, "IMPROPERS")-1;
02585 
02586             /*  Check to make sure the index isn't too big  */
02587             if (atom_nums[j] >= numAtoms)
02588             {
02589                 char err_msg[128];
02590 
02591                 sprintf(err_msg, "IMPROPERS INDEX %d GREATER THAN NATOM %d IN IMPROPERS # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
02592                 NAMD_die(err_msg);
02593             }
02594 
02595             if (atom_nums[j] != last_atom_nums[j])
02596             {
02597                 duplicate_bond = FALSE;
02598             }
02599 
02600             last_atom_nums[j] = atom_nums[j];
02601         }
02602 
02603         /*  Get the atom types so we can look up the parameters */
02604         const char *atom1Type = atomTypePool[atomData[atom_nums[0]].atomTypeIdx].c_str();
02605         const char *atom2Type = atomTypePool[atomData[atom_nums[1]].atomTypeIdx].c_str();
02606         const char *atom3Type = atomTypePool[atomData[atom_nums[2]].atomTypeIdx].c_str();
02607         const char *atom4Type = atomTypePool[atomData[atom_nums[3]].atomTypeIdx].c_str();
02608         strcpy(atom1name, atom1Type);
02609         strcpy(atom2name, atom2Type);
02610         strcpy(atom3name, atom3Type);
02611         strcpy(atom4name, atom4Type);
02612 
02613         //  Check to see if this is a duplicate improper
02614         if (duplicate_bond)
02615         {
02616             //  This is a duplicate improper.  So we don't
02617             //  really count this entry, we just update
02618             //  the parameters object
02619             multiplicity++;
02620 
02621             if (multiplicity == 2)
02622             {
02623                 //  Count the number of multiples.
02624                 g_mol->numMultipleImpropers++;
02625             }
02626         }
02627         else
02628         {
02629             //  Not a duplicate
02630             multiplicity = 1;
02631             num_unique++;
02632         }
02633 
02634         /*  Look up the constants for this bond      */
02635         g_param->assign_improper_index(atom1name, atom2name,
02636                                        atom3name, atom4name, &(impropers[num_unique-1]),
02637                                        multiplicity);
02638 
02639         /*  Assign the atom indexes        */
02640         impropers[num_unique-1].atom1=atom_nums[0];
02641         impropers[num_unique-1].atom2=atom_nums[1];
02642         impropers[num_unique-1].atom3=atom_nums[2];
02643         impropers[num_unique-1].atom4=atom_nums[3];
02644 
02645         num_read++;
02646     }
02647 
02648     //copy extra impropers to impropers structure
02649     if(extraImpropers.size()>0){
02650         iout << iWARN << "It's your responsibility to ensure there is no duplicates among these extra impropers\n" << endi;
02651     }
02652     for(int i=0; i<extraImpropers.size(); i++)
02653         impropers[num_unique+i] = extraImpropers[i];
02654     num_unique += extraImpropers.size();
02655     extraImpropers.clear();
02656 
02657     //  Now reset the numImpropers value to the number of UNIQUE
02658     //  impropers.  Sure, we waste a few entries in the improper_array
02659     //  on the master node, but it is very little space . . .
02660     g_mol->numImpropers = num_unique;
02661 
02662     //create improper's tupleSignature
02663     for(int i=0; i<num_unique; i++)
02664     {
02665         Improper *tuple = impropers+i;
02666         TupleSignature oneSig(3,IMPROPER,tuple->improper_type);
02667         int offset[3];
02668         offset[0] = tuple->atom2 - tuple->atom1;
02669         offset[1] = tuple->atom3 - tuple->atom1;
02670         offset[2] = tuple->atom4 - tuple->atom1;
02671         oneSig.setOffsets(offset);
02672 
02673         int poolIndex = sigsOfImpropers.lookupCstPool(oneSig);
02674         if(poolIndex == -1)
02675         {
02676             sigsOfImpropers.push_back(oneSig);
02677             poolIndex = (SigIndex)sigsOfImpropers.size()-1;
02678         }
02679         eachAtomSigs[tuple->atom1].improperSigIndices.push_back(poolIndex);
02680     }
02681 
02682     delete[] impropers;
02683 
02684 }
02685 
02686 void buildImproperData()
02687 { 
02688 #ifndef MEM_OPT_VERSION
02689     Improper *impropers=g_mol->getAllImpropers();
02690 
02691     //create improper's tupleSignature
02692     for(int i=0; i<g_mol->numImpropers; i++)
02693     {
02694         Improper *tuple = impropers+i;
02695         TupleSignature oneSig(3,IMPROPER,tuple->improper_type);
02696         int offset[3];
02697         offset[0] = tuple->atom2 - tuple->atom1;
02698         offset[1] = tuple->atom3 - tuple->atom1;
02699         offset[2] = tuple->atom4 - tuple->atom1;
02700         oneSig.setOffsets(offset);
02701 
02702         int poolIndex = sigsOfImpropers.lookupCstPool(oneSig);
02703         if(poolIndex == -1)
02704         {
02705             sigsOfImpropers.push_back(oneSig);
02706             poolIndex = (SigIndex)sigsOfImpropers.size()-1;
02707         }
02708         eachAtomSigs[tuple->atom1].improperSigIndices.push_back(poolIndex);
02709     }
02710 
02711     delete[] impropers;
02712 #endif
02713 }
02714 
02715 void getDonorData(FILE *fd)
02716 {
02717     int d[2];               // temporary storage of donor atom index
02718     register int j;      // Loop counter
02719     int num_read=0;    // Number of bonds read so far
02720     int num_no_hydr=0;      // Number of bonds with no hydrogen given
02721 
02722     /*  Allocate the array to hold the bonds      */
02723     int numDonors = g_mol->numDonors;
02724     int numAtoms = g_mol->numAtoms;
02725     Bond *donors=new Bond[numDonors];
02726 
02727     if (donors == NULL)
02728     {
02729         NAMD_die("memory allocations failed in Molecule::read_donors");
02730     }
02731 
02732     /*  Loop through and read in all the donors      */
02733     while (num_read < numDonors)
02734     {
02735         /*  Loop and read in the two atom indexes    */
02736         for (j=0; j<2; j++)
02737         {
02738             /*  Read the atom number from the file.         */
02739             /*  Subtract 1 to convert the index from the    */
02740             /*  1 to NumAtoms used in the file to the       */
02741             /*  0 to NumAtoms-1 that we need    */
02742             d[j]=NAMD_read_int(fd, "DONORS")-1;
02743 
02744             /*  Check to make sure the index isn't too big  */
02745             if (d[j] >= numAtoms)
02746             {
02747                 char err_msg[128];
02748 
02749                 sprintf(err_msg,
02750                         "DONOR INDEX %d GREATER THAN NATOM %d IN DONOR # %d IN PSF FILE",
02751                         d[j]+1, numAtoms, num_read+1);
02752                 NAMD_die(err_msg);
02753             }
02754 
02755             /*  Check if there is a hydrogen given */
02756             if (d[j] < 0)
02757                 num_no_hydr++;
02758         }
02759 
02760         /*  Assign the atom indexes to the array element  */
02761         Bond *b = &(donors[num_read]);
02762         b->atom1=d[0];
02763         b->atom2=d[1];
02764 
02765         num_read++;
02766     }
02767 
02768     delete [] donors;
02769 }
02770 
02771 void getAcceptorData(FILE *fd)
02772 {
02773     int d[2];               // temporary storage of atom index
02774     register int j;      // Loop counter
02775     int num_read=0;    // Number of bonds read so far
02776     int num_no_ante=0;      // number of pairs with no antecedent
02777 
02778     int numAcceptors = g_mol->numAcceptors;
02779 
02780     /*  Allocate the array to hold the bonds      */
02781     Bond *acceptors=new Bond[numAcceptors];
02782 
02783     if (acceptors == NULL)
02784     {
02785         NAMD_die("memory allocations failed in Molecule::read_acceptors");
02786     }
02787 
02788     /*  Loop through and read in all the acceptors      */
02789     while (num_read < numAcceptors)
02790     {
02791         /*  Loop and read in the two atom indexes    */
02792         for (j=0; j<2; j++)
02793         {
02794             /*  Read the atom number from the file.         */
02795             /*  Subtract 1 to convert the index from the    */
02796             /*  1 to NumAtoms used in the file to the       */
02797             /*  0 to NumAtoms-1 that we need    */
02798             d[j]=NAMD_read_int(fd, "ACCEPTORS")-1;
02799 
02800             /*  Check to make sure the index isn't too big  */
02801             if (d[j] >= g_mol->numAtoms)
02802             {
02803                 char err_msg[128];
02804 
02805                 sprintf(err_msg, "ACCEPTOR INDEX %d GREATER THAN NATOM %d IN DONOR # %d IN PSF FILE", d[j]+1, g_mol->numAtoms, num_read+1);
02806                 NAMD_die(err_msg);
02807             }
02808 
02809             /*  Check if there is an antecedent given */
02810             if (d[j] < 0)
02811                 num_no_ante++;
02812         }
02813 
02814         /*  Assign the atom indexes to the array element  */
02815         Bond *b = &(acceptors[num_read]);
02816         b->atom1=d[0];
02817         b->atom2=d[1];
02818 
02819         num_read++;
02820     }
02821 
02822     delete [] acceptors;
02823 }
02824 
02825 void getExclusionData(FILE *fd)
02826 {
02827     //reading explicit exclusions from PSF file
02828     //TODO: Implement it
02829     //currently just abort saying it is not supported
02830     printf("ERROR: The current compression doesn't support explicit exclusions!\n");
02831     NAMD_die("Compressing .psf file is not finished!\n");  
02832 }
02833 
02834 void getCrosstermData(FILE *fd)
02835 {
02836   int atom_nums[8];  //  Atom indexes for the 4 atoms
02837   int last_atom_nums[8];  //  Atom indexes from previous bond
02838   char atom1name[11];  //  Atom type for atom 1
02839   char atom2name[11];  //  Atom type for atom 2
02840   char atom3name[11];  //  Atom type for atom 3
02841   char atom4name[11];  //  Atom type for atom 4
02842   char atom5name[11];  //  Atom type for atom 5
02843   char atom6name[11];  //  Atom type for atom 6
02844   char atom7name[11];  //  Atom type for atom 7
02845   char atom8name[11];  //  Atom type for atom 8
02846   int j;      //  Loop counter
02847   int num_read=0;    //  Number of items read so far
02848   Bool duplicate_bond;  // Is this a duplicate of the last bond
02849 
02850   //  Initialize the array used to look for duplicate crossterm
02851   //  entries.  Set them all to -1 so we know nothing will match
02852   for (j=0; j<8; j++)
02853     last_atom_nums[j] = -1;
02854 
02855   int numCrossterms = g_mol->numCrossterms;
02856   int numAtoms = g_mol->numAtoms;
02857 
02858   /*  Allocate the array to hold the cross-terms */
02859   Crossterm* crossterms=new Crossterm[numCrossterms];
02860 
02861   if (crossterms == NULL)
02862   {
02863     NAMD_die("memory allocation failed in getCrosstermData when compressing psf file");
02864   }
02865 
02866   /*  Loop through and read all the cross-terms      */
02867   while (num_read < numCrossterms)
02868   {
02869     duplicate_bond = TRUE;
02870 
02871     /*  Loop through the 8 indexes for this cross-term */
02872     for (j=0; j<8; j++)
02873     {
02874       /*  Read the atom number from the file.         */
02875       /*  Subtract 1 to convert the index from the    */
02876       /*  1 to NumAtoms used in the file to the       */
02877       /*  0 to NumAtoms-1 that we need    */
02878       atom_nums[j]=NAMD_read_int(fd, "CROSS-TERMS")-1;
02879 
02880       /*  Check to make sure the index isn't too big  */
02881       if (atom_nums[j] >= numAtoms)
02882       {
02883         char err_msg[128];
02884 
02885         sprintf(err_msg, "CROSS-TERM INDEX %d GREATER THAN NATOM %d IN CROSS-TERMS # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
02886         NAMD_die(err_msg);
02887       }
02888       
02889       if (atom_nums[j] != last_atom_nums[j]){
02890         duplicate_bond = FALSE;
02891       }
02892       
02893       last_atom_nums[j] = atom_nums[j];
02894     }
02895     
02896     /*  Get the atom types so we can look up the parameters */
02897     const char *atom1Type = atomTypePool[atomData[atom_nums[0]].atomTypeIdx].c_str();
02898     const char *atom2Type = atomTypePool[atomData[atom_nums[1]].atomTypeIdx].c_str();
02899     const char *atom3Type = atomTypePool[atomData[atom_nums[2]].atomTypeIdx].c_str();
02900     const char *atom4Type = atomTypePool[atomData[atom_nums[3]].atomTypeIdx].c_str();
02901     const char *atom5Type = atomTypePool[atomData[atom_nums[4]].atomTypeIdx].c_str();
02902     const char *atom6Type = atomTypePool[atomData[atom_nums[5]].atomTypeIdx].c_str();
02903     const char *atom7Type = atomTypePool[atomData[atom_nums[6]].atomTypeIdx].c_str();
02904     const char *atom8Type = atomTypePool[atomData[atom_nums[7]].atomTypeIdx].c_str();
02905     strcpy(atom1name, atom1Type);
02906     strcpy(atom2name, atom2Type);
02907     strcpy(atom3name, atom3Type);
02908     strcpy(atom4name, atom4Type);
02909     strcpy(atom5name, atom5Type);
02910     strcpy(atom6name, atom6Type);
02911     strcpy(atom7name, atom7Type);
02912     strcpy(atom8name, atom8Type);
02913 
02914     //  Check to see if this is a duplicate term
02915     if (duplicate_bond)
02916     {
02917       iout << iWARN << "Duplicate cross-term detected.\n" << endi;
02918     }
02919 
02920     /*  Look up the constants for this bond      */
02921     g_param->assign_crossterm_index(atom1name, atom2name, 
02922        atom3name, atom4name, atom5name, atom6name,
02923        atom7name, atom8name, &(crossterms[num_read]));
02924 
02925     /*  Assign the atom indexes        */
02926     crossterms[num_read].atom1=atom_nums[0];
02927     crossterms[num_read].atom2=atom_nums[1];
02928     crossterms[num_read].atom3=atom_nums[2];
02929     crossterms[num_read].atom4=atom_nums[3];
02930     crossterms[num_read].atom5=atom_nums[4];
02931     crossterms[num_read].atom6=atom_nums[5];
02932     crossterms[num_read].atom7=atom_nums[6];
02933     crossterms[num_read].atom8=atom_nums[7];
02934 
02935     num_read++;
02936   }
02937 
02938   numCrossterms = num_read;
02939 
02940   //create crossterm's tupleSignature
02941   for(int i=0; i<numCrossterms; i++)
02942   {
02943     Crossterm *tuple = crossterms+i;
02944     TupleSignature oneSig(7, CROSSTERM, tuple->crossterm_type);
02945     int offset[7];
02946     offset[0] = tuple->atom2 - tuple->atom1;
02947     offset[1] = tuple->atom3 - tuple->atom1;
02948     offset[2] = tuple->atom4 - tuple->atom1;
02949     offset[3] = tuple->atom5 - tuple->atom1;
02950     offset[4] = tuple->atom6 - tuple->atom1;
02951     offset[5] = tuple->atom7 - tuple->atom1;
02952     offset[6] = tuple->atom8 - tuple->atom1;
02953     oneSig.setOffsets(offset);
02954    
02955     int poolIndex = sigsOfCrossterms.lookupCstPool(oneSig);
02956     if(poolIndex == -1)
02957     {
02958       sigsOfCrossterms.push_back(oneSig);
02959       poolIndex = (SigIndex)sigsOfCrossterms.size()-1;
02960     }
02961     eachAtomSigs[tuple->atom1].crosstermSigIndices.push_back(poolIndex);
02962   }
02963   
02964   delete[] crossterms;
02965 }
02966 
02967 void buildCrosstermData()
02968 {
02969 #ifndef MEM_OPT_VERSION
02970   Crossterm *crossterms = g_mol->getAllCrossterms();
02971   //create crossterm's tupleSignature
02972   for(int i=0; i<g_mol->numCrossterms; i++)
02973   {
02974     Crossterm *tuple = crossterms+i;
02975     TupleSignature oneSig(7, CROSSTERM, tuple->crossterm_type);
02976     int offset[7];
02977     offset[0] = tuple->atom2 - tuple->atom1;
02978     offset[1] = tuple->atom3 - tuple->atom1;
02979     offset[2] = tuple->atom4 - tuple->atom1;
02980     offset[3] = tuple->atom5 - tuple->atom1;
02981     offset[4] = tuple->atom6 - tuple->atom1;
02982     offset[5] = tuple->atom7 - tuple->atom1;
02983     offset[6] = tuple->atom8 - tuple->atom1;
02984     oneSig.setOffsets(offset);
02985    
02986     int poolIndex = sigsOfCrossterms.lookupCstPool(oneSig);
02987     if(poolIndex == -1)
02988     {
02989       sigsOfCrossterms.push_back(oneSig);
02990       poolIndex = (SigIndex)sigsOfCrossterms.size()-1;
02991     }
02992     eachAtomSigs[tuple->atom1].crosstermSigIndices.push_back(poolIndex);
02993   }
02994   
02995   delete[] crossterms;
02996 #endif
02997 }
02998 
02999 void buildExclusions()
03000 {
03001     //1. Build exclusions: mainly accomplish the function of
03002     //Molecule::build_exclusions (based on the bonds)
03003     UniqueSet<Exclusion> allExclusions;
03004 
03005     int exclude_flag; //Exclusion policy
03006     exclude_flag = g_simParam->exclude;
03007     //int stripHGroupExclFlag = (simParams->splitPatch == SPLIT_PATCH_HYDROGEN);
03008 
03009     //Commented now since no explicit exclusions are read
03010     //  Go through the explicit exclusions and add them to the arrays
03011     //for(i=0; i<numExclusions; i++){
03012     //  exclusionSet.add(exclusions[i]);
03013     //}
03014 
03015     // If this is AMBER force field, and readExclusions is TRUE,
03016     // then all the exclusions were read from parm file, and we
03017     // shouldn't generate any of them.
03018     // Comment on stripHGroupExcl:
03019     // 1. Inside this function, hydrogenGroup is initialized in
03020     // build_atom_status, therefore, not available when reading psf files
03021     // 2. this function's main purpose is to reduce memory usage. Since exclusion
03022     // signatures are used, this function could be overlooked  --Chao Mei
03023 
03024     vector<int> *eachAtomNeighbors = new vector<int>[g_mol->numAtoms];   
03025     for(int atom1=0; atom1<g_mol->numAtoms; atom1++)
03026     {
03027         AtomSigInfo *aSig = &atomSigPool[atomData[atom1].atomSigIdx];
03028         for(int j=0; j<aSig->bondSigIndices.size(); j++)
03029         {
03030             TupleSignature *tSig = &sigsOfBonds[aSig->bondSigIndices[j]];
03031             if(!tSig->isReal) continue;
03032             int atom2 = atom1+tSig->offset[0];
03033             eachAtomNeighbors[atom1].push_back(atom2);
03034             eachAtomNeighbors[atom2].push_back(atom1);
03035         }
03036     }
03037 
03038     if (!g_simParam->amberOn || !g_simParam->readExclusions)
03039     { //  Now calculate the bonded exlcusions based on the exclusion policy
03040         switch (exclude_flag)
03041         {
03042         case NONE:
03043             break;
03044         case ONETWO:
03045             build12Excls(allExclusions, eachAtomNeighbors);
03046             break;
03047         case ONETHREE:
03048             build12Excls(allExclusions, eachAtomNeighbors);
03049             build13Excls(allExclusions, eachAtomNeighbors);
03050             //if ( stripHGroupExclFlag ) stripHGroupExcl();
03051             break;
03052         case ONEFOUR:
03053             build12Excls(allExclusions, eachAtomNeighbors);
03054             build13Excls(allExclusions, eachAtomNeighbors);
03055             build14Excls(allExclusions, eachAtomNeighbors, 0);
03056             //if ( stripHGroupExclFlag ) stripHGroupExcl();
03057             break;
03058         case SCALED14:
03059             build12Excls(allExclusions, eachAtomNeighbors);
03060             build13Excls(allExclusions, eachAtomNeighbors);
03061             build14Excls(allExclusions, eachAtomNeighbors, 1);
03062             //if ( stripHGroupExclFlag ) stripHGroupExcl();
03063             break;
03064         }
03065     }
03066     //else if (stripHGroupExclFlag && exclude_flag!=NONE && exclude_flag!=ONETWO)
03067     //  stripHGroupExcl();
03068 
03069     //Commented since atomFepFlags information is not available when reading psf file
03070     //stripFepExcl();
03071 
03072     for(int i=0; i<g_mol->numAtoms; i++)
03073         eachAtomNeighbors[i].clear();
03074     delete [] eachAtomNeighbors;
03075 
03076     //2. Build each atom's list of exclusions
03077     UniqueSetIter<Exclusion> exclIter(allExclusions);
03078     eachAtomExclSigs = new ExclSigInfo[g_mol->numAtoms];
03079     for(exclIter=exclIter.begin(); exclIter!=exclIter.end(); exclIter++)
03080     {
03081         int atom1 = exclIter->atom1;
03082         int atom2 = exclIter->atom2;
03083         int offset21 = atom2-atom1;
03084         if(exclIter->modified)
03085         {
03086             eachAtomExclSigs[atom1].modExclOffset.push_back(offset21);
03087             eachAtomExclSigs[atom2].modExclOffset.push_back(-offset21);
03088         }
03089         else
03090         {
03091             eachAtomExclSigs[atom1].fullExclOffset.push_back(offset21);
03092             eachAtomExclSigs[atom2].fullExclOffset.push_back(-offset21);
03093         }
03094     }
03095     allExclusions.clear();
03096 
03097     //3. Build up exclusion signatures and determine each atom's
03098     //exclusion signature index
03099     for(int i=0; i<g_mol->numAtoms; i++)
03100     {
03101         eachAtomExclSigs[i].sortExclOffset();
03102         int poolIndex = sigsOfExclusions.lookupCstPool(eachAtomExclSigs[i]);
03103         if(poolIndex==-1)
03104         {
03105             poolIndex = sigsOfExclusions.size();
03106             sigsOfExclusions.push_back(eachAtomExclSigs[i]);
03107         }
03108         atomData[i].exclSigIdx = poolIndex;
03109     }
03110     delete [] eachAtomExclSigs;
03111     eachAtomExclSigs = NULL;
03112     printf("Exclusion signatures: %d\n", (int)sigsOfExclusions.size());
03113 }
03114 
03115 void build12Excls(UniqueSet<Exclusion>& allExcls, vector<int> *eachAtomNeighbors)
03116 {
03117     for(int atom1=0; atom1<g_mol->numAtoms; atom1++)
03118     {
03119         vector<int> *atom1List = &eachAtomNeighbors[atom1];
03120         for(int j=0; j<atom1List->size(); j++)
03121         {
03122             int atom2 = atom1List->at(j);
03123             if(atom1<atom2)
03124                 allExcls.add(Exclusion(atom1, atom2));
03125             else
03126                 allExcls.add(Exclusion(atom2, atom1));
03127         }
03128     }
03129 }
03130 
03131 void build13Excls(UniqueSet<Exclusion>& allExcls, vector<int> *eachAtomNeighbors)
03132 {
03133     for(int atom1=0; atom1<g_mol->numAtoms; atom1++)
03134     {
03135         vector<int> *atom1List = &eachAtomNeighbors[atom1];
03136         for(int j=0; j<atom1List->size(); j++)
03137         {
03138             int atom2 = atom1List->at(j);
03139             vector<int> *atom2List = &eachAtomNeighbors[atom2];
03140             for(int k=0; k<atom2List->size(); k++)
03141             {
03142                 int atom3 = atom2List->at(k);
03143                 //atom1-atom2, so atom2List contains atom1 which should not be considered
03144                 if(atom3 == atom1)
03145                     continue;
03146                 if(atom1<atom3)
03147                     allExcls.add(Exclusion(atom1, atom3));
03148                 else
03149                     allExcls.add(Exclusion(atom3, atom1));
03150             }
03151         }
03152     }
03153 }
03154 
03155 void build14Excls(UniqueSet<Exclusion>& allExcls, vector<int> *eachAtomNeighbors, int modified)
03156 {
03157     for(int atom1=0; atom1<g_mol->numAtoms; atom1++)
03158     {
03159         vector<int> *atom1List = &eachAtomNeighbors[atom1];
03160         for(int j=0; j<atom1List->size(); j++)
03161         {
03162             int atom2 = atom1List->at(j);
03163             vector<int> *atom2List = &eachAtomNeighbors[atom2];
03164             for(int k=0; k<atom2List->size(); k++)
03165             {
03166                 int atom3 = atom2List->at(k);
03167                 //atom1-atom2, so atom2List contains atom1 which should not be considered
03168                 if(atom3 == atom1)
03169                     continue;
03170                 vector<int> *atom3List = &eachAtomNeighbors[atom3];
03171                 for(int l=0; l<atom3List->size(); l++)
03172                 {
03173                     int atom4 = atom3List->at(l);
03174                     //atom1-atom2, so atom2List contains atom1 which should not be considered
03175                     if(atom4 == atom2)
03176                         continue;
03177                     if(atom1<atom4)
03178                         allExcls.add(Exclusion(atom1, atom4, modified));
03179                     else
03180                         allExcls.add(Exclusion(atom4, atom1, modified));
03181                 }
03182             }
03183         }
03184     }
03185 }
03186 
03187 template <class T> void HashPool<T>::dump_tables()
03188 {
03189   for(int j=0; j < pool.size(); j++) {
03190     HashPoolAdaptorT<T>* pval = pool[j];
03191     CmiPrintf("Pool[%d]=%p %p  hash = %d\n",j,pool[j],pval,pval->hash());
03192   }
03193   CkHashtableIterator *iter = index_table.iterator();
03194   void *key,*indx;
03195   while (iter->hasNext()) {
03196     indx = iter->next(&key);
03197     HashPoolAdaptorT<T> *pkey = (HashPoolAdaptorT<T>*)key;
03198     CmiPrintf("key %p indx %p %d hash=%d\n",key,indx,*((int *)indx),pkey->hash());
03199   }
03200 }

Generated on Mon Nov 23 04:59:19 2009 for NAMD by  doxygen 1.3.9.1