GLYLIB  0.3.0b
parse_amber_prmtop.c
Go to the documentation of this file.
00001 /* File parse_amber_prmtop.c begun on 20080610 by BLFoley
00002  * Purpose: parse entries from prmtop file (already read in) into
00003  *      appropriate data locations within an assembly
00004  *      Also adds the prmtop P to the assembly's void pointer
00005  */
00006 #include "AMBER/amber_prmtop.h"
00007 #include "gly_codeutils.h"
00008 
00009 assembly parse_amber_prmtop(amber_prmtop *P){
00010 assembly A;
00011 int *ICO,nICO;
00012 int pa=0,pb=0,pc=0,pd=0,pA1=0,pA2=0,pA3,pA4,pI1=0;
00013 int NextRes=0,nummol=0,*resi; // more utility integers
00014 int sa=0,sr=0,sm=0,ta=0,tr=0,tm=0,ntrue=0,nwhitemid=0;
00015 int IPTRES=0,NSPM=0,NSPSOL=0,*NSP; // solvent/solute info & #atoms per molecule
00016 molbond *MB,*MBTMP;
00017 angle_index *MANG;
00018 torsion_index *MTOR;
00019 molindex *MOLI,*MOLBNDI; // MOLI for here, MOLBNDI for assigning molecules
00020 char **ATNAME,**TREECLASS,*RADTYPE,tmp[80],*PRUNED;
00021 double *R,*SC,*MASS; // radii and screening constants for IS, atom masses
00022 
00023 int compare_array_ws(int ai, char **a, char *flag, int bi){ // Function which checks for whitespace in an array and removes it to compare the length to its expected(true) length 
00024 /*      printf("ai is %d\n",ai);
00025         printf("a[0] is %s\n",a[0]);
00026         printf("flag is %s\n",flag);
00027         printf("bi is %d\n",bi);
00028 */
00029         int ntrue=0,nwhitemid=0,i=0;// ntrue is the number of non-whitespace fields, nwhitemid is the number of non-terminal whitespace residues (>0 will cause error)
00030         for(i=0;i<ai;i++){
00031                 PRUNED=strdup(prune_string_whitespace(a[i])); // Remove whitespace from array elements
00032                 if(PRUNED[0]!='\0'){ // Check for only a string terminator
00033                         if(ntrue==bi){ // Check that ntrue never exceeds the expected number of elements (otherwise exit with an error)
00034                                 printf("ERROR: The declared number of components, %d, in FLAG %s does not equal the number found, %d!\n",(ntrue+1),flag,bi);
00035                                 mywhine("\tExiting for an unequal number of elements between expected and found.\n");
00036                                 }
00037                         if(i>(ntrue+nwhitemid)){ nwhitemid++; } // Increment the non-terminal whitespace index (note that consecutive non-terminal whitespaces are counted as 1)
00038                         ntrue++;
00039                         }
00040                 free(PRUNED);
00041                 }
00042         if(ntrue!=ai){ // Test if the expected (ai) value does not equal the whitespace-removed value
00043                 printf("WARNING: Found whitespace at flag %s\n",flag);
00044                 printf("\tFound %d total",(ai-ntrue));
00045                         if(nwhitemid>0){
00046                                 printf(" and at least %d non-terminal whitespace(s).\nFATAL WARNING: Non-terminal whitespace(s) can allow for mis-assignment of topology components!\n\tCheck that your topology file is correctly built.\n",nwhitemid);
00047                                 mywhine("\tExiting because non-terminal whitespace found.\n");
00048                                 }
00049                         else{ printf(" terminal whitespace(s).\n\tIgnoring whitespace(s).\n");}
00050                 }
00051         return(ntrue);
00052         }
00053 
00054 int count_array_nws(int ai, char **a, char *flag){ // Function to return the number of non-whitespace elements in an array - no comparison to other numbers
00055         int ntrue=0,nwhitemid=0,i=0;// ntrue is the number of non-whitespace fields, nwhitemid is the number of non-terminal whitespace residues (>0 will cause error)
00056         for(i=0;i<ai;i++){
00057                 PRUNED=strdup(prune_string_whitespace(a[i])); // Removing whitespace from the read-in data at position pb 
00058                 if(PRUNED[0]!='\0'){ // Not whitespace
00059                         if(i>(ntrue+nwhitemid)){ nwhitemid++; } // Increment the number of non-terminal whitespaces
00060                         ntrue++;
00061                         }
00062                 free(PRUNED);
00063                 }
00064         if(ntrue!=ai){
00065                 printf("WARNING: Found whitespace at flag %s\n",flag);
00066                 printf("\tFound %d total",(ai-ntrue));
00067                         if(nwhitemid>0){printf(" and at least %d non-terminal whitespace(s).\nFATAL WARNING: Non-terminal whitespace(s) can allow for mis-assignment of topology components!\n\tCheck that your topology file is correctly built.\n",nwhitemid);}
00068                         else{printf(" terminal whitespace(s).\n");}
00069                 printf("\tIgnoring whitespace(s).\n");
00070                 }
00071         return(ntrue);
00072         }
00073 
00074 //fileset F;
00075 //amber_prmtop *aprm;
00076 
00077 MOLI=NULL;
00078 ICO=NULL;
00079 MB=NULL;
00080 MANG=NULL;
00081 MTOR=NULL;
00082 MASS=NULL;
00083 NSP=NULL;
00084 R=NULL;
00085 SC=NULL;
00086 MOLBNDI=NULL;
00087 MBTMP=NULL;
00088 resi=NULL;
00089 ATNAME=NULL;
00090 TREECLASS=NULL;
00091 
00092 /// Drop the contents of the original file in the void pointer space
00093 A.nVP=1; 
00094 A.VP=P;
00095 
00096 // do some initializations
00097 A.nPRM=1;
00098 A.PRM=(parameter_set**)calloc(1,sizeof(parameter_set*));
00099 A.PRM[0]=(parameter_set*)calloc(1,sizeof(parameter_set));
00100 
00101 // First, find the pointers and read them into the top structure
00102 // Also add them to the assembly, as needed
00103 // Any that are not added now can be added later -- chances are that 
00104 //      no one had a use for them previously.  In any case, they will
00105 //      be present as-is in the void pointer
00106 for(pa=0;pa<P[0].nS;pa++){ // get pointers first...
00107         if(strcmp(P[0].SN[pa],"POINTERS")==0){ 
00108                 // total number of atoms
00109                 sscanf(P[0].S[pa].D[0],"%d",&P[0].NATOM); 
00110                 A.na = P[0].NATOM; 
00111                 if(A.na>0){
00112                         A.a=(atom**)calloc(A.na,sizeof(atom*));
00113                         MOLI=(molindex*)calloc(A.na,sizeof(molindex)); // to keep up with locations per atom
00114                         } 
00115                 for(pb=0;pb<A.na;pb++){A.a[pb]=(atom*)calloc(1,sizeof(atom));}
00116                 // number of atom types
00117                 sscanf(P[0].S[pa].D[1],"%d",&P[0].NTYPES); 
00118                 A.PRM[0][0].nAT=P[0].NTYPES; 
00119                 if(A.PRM[0][0].nAT>0){
00120                         A.PRM[0][0].AT=(atype*)calloc(A.PRM[0][0].nAT,sizeof(atype));
00121                         A.PRM[0][0].nNBT=A.PRM[0][0].nAT*(A.PRM[0][0].nAT+1)/2;
00122                         A.PRM[0][0].NBT=(bond_type*)calloc(A.PRM[0][0].nNBT,sizeof(bond_type));
00123                         nICO=A.PRM[0][0].nAT*A.PRM[0][0].nAT;
00124                         ICO=(int*)calloc(nICO,sizeof(int));
00125                         } 
00126                 // Numbers of actual bonds, angles, dihedrals
00127                 // NOT adding these number-of distinctions to the assembly
00128                 // Instead, adding them all as plain bonds, etc. (see "D" description for distinction)
00129                 // See also NBONA, etc., below (constraints)...
00130                 sscanf(P[0].S[pa].D[2],"%d",&P[0].NBONH); // number of bonds containing hydrogen
00131                 sscanf(P[0].S[pa].D[3],"%d",&P[0].MBONA); // number of bonds not containing hydrogen
00132                 sscanf(P[0].S[pa].D[4],"%d",&P[0].NTHETH); // number of angles containing hydrogen
00133                 sscanf(P[0].S[pa].D[5],"%d",&P[0].MTHETA); // number of angles not containing hydrogen
00134                 sscanf(P[0].S[pa].D[6],"%d",&P[0].NPHIH); // number of dihedrals containing hydrogen
00135                 sscanf(P[0].S[pa].D[7],"%d",&P[0].MPHIA); // number of dihedrals not containing hydrogen
00136                 // Unused parameters and the excluded atoms list (probably not used in glycam)
00137                 // NOT adding these at all
00138                 sscanf(P[0].S[pa].D[8],"%d",&P[0].NHPARM); // currently not used
00139                 sscanf(P[0].S[pa].D[9],"%d",&P[0].NPARM); // currently not used
00140                 sscanf(P[0].S[pa].D[10],"%d",&P[0].NEXT); // number of excluded atoms
00141                 // Number of residues
00142                 sscanf(P[0].S[pa].D[11],"%d",&P[0].NRES); 
00143                 A.nr = P[0].NRES; 
00144                 if(A.nr>0){A.r=(residue**)calloc(A.nr,sizeof(residue*));} // will move these later 
00145                 for(pb=0;pb<A.nr;pb++){A.r[pb]=(residue*)calloc(1,sizeof(residue));}
00146                 // The rest of the bonds, angles and torsions (constraints)
00147                 sscanf(P[0].S[pa].D[12],"%d",&P[0].NBONA); // MBONA + number of constraint bonds
00148                 A.nb = P[0].NBONH + P[0].NBONA; // all the bonds
00149                 if(A.nb>0){A.b=(molbond*)calloc(A.nb,sizeof(molbond));}
00150                 if(A.nb>0){MB=(molbond*)calloc(A.nb,sizeof(molbond));}
00151                 sscanf(P[0].S[pa].D[13],"%d",&P[0].NTHETA); // MTHETA + number of constraint angles
00152                 A.nANG=P[0].NTHETH+P[0].NTHETA; // all the angles
00153                 if(A.nANG>0){A.ANG=(angle_index*)calloc(A.nANG,sizeof(angle_index));}
00154                 if(A.nANG>0){MANG=(angle_index*)calloc(A.nANG,sizeof(angle_index));}
00155                 sscanf(P[0].S[pa].D[14],"%d",&P[0].NPHIA); // MPHIA + number of constraint dihedrals
00156                 A.nTOR=P[0].NPHIH+P[0].NPHIA; // all the torsions
00157                 if(A.nTOR>0){A.TOR=(torsion_index*)calloc(A.nTOR,sizeof(torsion_index));}
00158                 if(A.nTOR>0){MTOR=(torsion_index*)calloc(A.nTOR,sizeof(torsion_index));}
00159                 // Numbers of bond, angle and torsion types
00160                 sscanf(P[0].S[pa].D[15],"%d",&P[0].NUMBND); // number of unique bond types
00161                 A.PRM[0][0].nBT = P[0].NUMBND; // number of unique bond types
00162                 if(A.PRM[0][0].nBT>0){A.PRM[0][0].BT=(bond_type*)calloc(A.PRM[0][0].nBT,sizeof(bond_type));}
00163                 sscanf(P[0].S[pa].D[16],"%d",&P[0].NUMANG); // number of unique angle types
00164                 A.PRM[0][0].nANT = P[0].NUMANG; // number of unique angle types
00165                 if(A.PRM[0][0].nANT>0){A.PRM[0][0].ANT=(angle_type*)calloc(A.PRM[0][0].nANT,sizeof(angle_type));}
00166                 sscanf(P[0].S[pa].D[17],"%d",&P[0].NPTRA); // number of unique dihedral types
00167                 A.PRM[0][0].nTRT = P[0].NPTRA; // number of unique dihedral types
00168                 if(A.PRM[0][0].nTRT>0){A.PRM[0][0].TRT=(torsion_type*)calloc(A.PRM[0][0].nTRT,sizeof(torsion_type));}
00169                 // Number of atom types in parameter file
00170                 // NOT adding this at all at present
00171                 sscanf(P[0].S[pa].D[18],"%d",&P[0].NATYP); // number of atom types in parameter file, see SOLTY below
00172                 // Number of Lennard-Jones 10-12 H-Bond pair types
00173                 sscanf(P[0].S[pa].D[19],"%d",&P[0].NPHB); // number of distinct 10-12 hydrogen bond pair types
00174                 A.PRM[0][0].nHBT = P[0].NPHB;
00175                 if(A.PRM[0][0].nHBT>0){A.PRM[0][0].HBT=(bond_type*)calloc(A.PRM[0][0].nHBT,sizeof(bond_type));}
00176                 // Perturbation information
00177                 // NOT adding these at all (no longer used as of AMBER 10)
00178                 sscanf(P[0].S[pa].D[20],"%d",&P[0].IFPERT); // set to 1 if perturbation info is to be read in
00179                 sscanf(P[0].S[pa].D[21],"%d",&P[0].NBPER); // number of bonds to be perturbed
00180                 sscanf(P[0].S[pa].D[22],"%d",&P[0].NGPER); // number of angles to be perturbed
00181                 sscanf(P[0].S[pa].D[23],"%d",&P[0].NDPER); // number of dihedrals to be perturbed
00182                 sscanf(P[0].S[pa].D[24],"%d",&P[0].MBPER); // number of bonds with atoms completely in perturbed group
00183                 sscanf(P[0].S[pa].D[25],"%d",&P[0].MGPER); // number of angles with atoms completely in perturbed group
00184                 sscanf(P[0].S[pa].D[26],"%d",&P[0].MDPER); // number of dihedrals with atoms completely in perturbed groups
00185                 // Box information
00186                 sscanf(P[0].S[pa].D[27],"%d",&P[0].IFBOX); // set to 1 if standard periodic box, 2 when truncated octahedral
00187                 if(P[0].IFBOX==0){A.nBOX=0;} ///< There are no boxes defined in this prmtop
00188                 else{
00189                         A.nBOX=1;
00190                         A.BOX=(boxinfo*)calloc(A.nBOX,sizeof(boxinfo));
00191                         A.BOX[0].nC=A.BOX[0].nCD=2; ///< One for the "boxang" and the other for the x,y,z values
00192                         A.BOX[0].C=(coord_nD*)calloc(A.BOX[0].nC,sizeof(coord_nD));
00193                         A.BOX[0].CD=(char**)calloc(A.BOX[0].nCD,sizeof(char*));
00194                         A.BOX[0].CD[0]=strdup("Periodic box, angle between the XY and YZ planes in degrees.");
00195                         A.BOX[0].C[0].nD=1; ///< Just an angle ("BETA" in the amber file specs)
00196                         A.BOX[0].C[0].D=(double*)calloc(A.BOX[0].C[0].nD,sizeof(double));
00197                         A.BOX[0].CD[1]=strdup("The periodic box lengths in the X, Y, and Z directions");
00198                         A.BOX[0].C[1].nD=3; ///< 3-D coordinate
00199                         A.BOX[0].C[1].D=(double*)calloc(A.BOX[0].C[1].nD,sizeof(double));
00200                         A.BOX[0].STYPE=strdup("standard periodic");
00201                         if(P[0].IFBOX==1){A.BOX[0].GTYPE=strdup("rectangular");}
00202                         if(P[0].IFBOX==2){A.BOX[0].GTYPE=strdup("truncated octahedral");}
00203                         if(P[0].IFBOX>2){A.BOX[0].GTYPE=strdup("unknown box type");} 
00204                         }
00205 
00206                 // NOT adding these at all 
00207                 sscanf(P[0].S[pa].D[28],"%d",&P[0].NMXRS); // number of atoms in the largest residue
00208                 sscanf(P[0].S[pa].D[29],"%d",&P[0].IFCAP); // set to 1 if the CAP option from edit was specified
00209                 //
00210                 break; // no need to keep scanning...
00211                 }
00212         }
00213 
00214 
00215 for(pa=0;pa<P[0].nS;pa++){// Loop through each of the sections
00216         P[0].S[pa].is_standard = 1; // Set is_standard to one as default
00217         //      check against each standard section
00218         //      if there is a match:
00219         //              set is_standard to zero
00220         //              record to assembly as needed
00221         //
00222         //              note that here 1=FALSE and 0=TRUE
00223         //
00224 
00225 //FORMAT(20a4)  (ITITL(i), i=1,20)
00226 if(strcmp(P[0].S[pa].N,"TITLE")==0){ // place in the Assembly description, NOTE: can be whitespace
00227         P[0].ITITL = pa; // the title section 
00228         P[0].S[pa].is_standard=0; // set as a standard section
00229         // copy the title into the assembly's description
00230         A.D=(char*)calloc(P[0].S[pa].nt*P[0].S[pa].nc+1,sizeof(char));
00231         for(pb=0;pb<P[0].S[pa].nt;pb++){strcat(A.D,P[0].S[pa].D[pb]);}
00232 }
00233 //FORMAT(12i6) 
00234 if(strcmp(P[0].S[pa].N,"POINTERS")==0){ // these are already added, no whitespace check 
00235         P[0].POINTERS=pa; // pointer to the section containing the original char-strings
00236         P[0].S[pa].is_standard=0; // set as a standard section
00237 }
00238 // FORMAT(20a4)  (IGRAPH(i), i=1,NATOM)
00239 if(strcmp(P[0].S[pa].N,"ATOM_NAME")==0){ // these eventually go into the molecules/residues/etc
00240         P[0].IGRAPH=pa; // IGRAPH : the user atoms names 
00241         P[0].S[pa].is_standard=0; // set as a standard section
00242         // for now, add these to the straight list of Assembly atoms
00243         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00244         for(pb=0;pb<A.na;pb++){
00245                 sscanf(P[0].S[pa].D[pb],"%s",tmp);
00246                 A.a[pb][0].N=(char*)calloc((strlen(tmp)+1),sizeof(char));
00247                 strcpy(A.a[pb][0].N,tmp); 
00248 //              printf("\tP[0].S[pa].D[pb] = %s\n",P[0].S[pa].D[pb]);
00249                 }
00250 }
00251 // FORMAT(5E16.8)  (CHRG(i), i=1,NATOM)
00252 // (Divide by 18.2223 to convert to charge in units of the electron charge) 
00253 if(strcmp(P[0].S[pa].N,"CHARGE")==0){ // these go with each atom
00254         P[0].CHRG   =pa; // CHRG   : the atom charges.  
00255         P[0].S[pa].is_standard=0; // set as a standard section
00256         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00257         for(pb=0;pb<A.na;pb++){
00258                 A.a[pb][0].nch=1;
00259                 A.a[pb][0].ch=(double*)calloc(1,sizeof(double));
00260                 sscanf(P[0].S[pa].D[pb],"%lf",&A.a[pb][0].ch[0]);
00261                 A.a[pb][0].ch[0]/=18.2223;
00262                 }
00263 }
00264 // FORMAT(5E16.8)  (AMASS(i), i=1,NATOM)
00265 if(strcmp(P[0].S[pa].N,"MASS")==0){ // with each atom
00266         P[0].AMASS  =pa; // AMASS  : the atom masses 
00267         P[0].S[pa].is_standard=0; // set as a standard section
00268         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00269         MASS=(double*)calloc(A.na,sizeof(double));
00270         for(pb=0;pb<A.na;pb++){ sscanf(P[0].S[pa].D[pb],"%lf",&A.a[pb][0].m); }
00271         // for(pb=0;pb<A.na;pb++){ sscanf(P[0].S[pa].D[pb],"%lf",&MASS[pb]); } // before m in atom struct
00272 }
00273 // FORMAT(12I6)  (IAC(i), i=1,NATOM)
00274 // START HERE -- is this really just an atom type index?  One hopes...
00275 if(strcmp(P[0].S[pa].N,"ATOM_TYPE_INDEX")==0){ // into the atype structure
00276         P[0].IAC    =pa; // IAC    : index for the atom types involved in Lennard Jones (6-12) 
00277         P[0].S[pa].is_standard=0; // set as a standard section
00278         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00279         for(pb=0;pb<A.na;pb++){
00280                 sscanf(P[0].S[pa].D[pb],"%d",&A.a[pb][0].t);
00281                 A.a[pb][0].t--;
00282                 if(A.a[pb][0].t<0){mywhine("A.a[pb][0].t<0 in parse_amber_prmtop");}
00283                 if(A.a[pa][0].t>=P[0].NTYPES){mywhine("A.a[pa][0].t>=P[0].NTYPES in parse_amber_prmtop");}
00284                 }
00285 }
00286                 // interactions.  See ICO below.  
00287 // FORMAT(12I6)  (NUMEX(i), i=1,NATOM)
00288 if(strcmp(P[0].S[pa].N,"NUMBER_EXCLUDED_ATOMS")==0){ // unused for now (20080612), no whitespace check since unused
00289         P[0].NUMEX  =pa; // NUMEX  : total number of excluded atoms for atom "i".  See
00290         P[0].S[pa].is_standard=0; // set as a standard section
00291 }
00292                 // NATEX below.  
00293 // FORMAT(12I6)  (ICO(i), i=1,NTYPES*NTYPES)
00294 // START HERE -- figure out how to put this is (efficiently...)
00295 if(strcmp(P[0].S[pa].N,"NONBONDED_PARM_INDEX")==0){ // 
00296         P[0].ICO    =pa; // ICO    : provides the index to the nonbon parameter
00297         P[0].S[pa].is_standard=0; // set as a standard section
00298         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,nICO);
00299         for(pb=0;pb<nICO;pb++){sscanf(P[0].S[pa].D[pb],"%d",&ICO[pb]);}
00300                 // arrays CN1, CN2 and ASOL, BSOL.  All possible 6-12
00301                 // or 10-12 atoms type interactions are represented.
00302                 // NOTE: A particular atom type can have either a 10-12
00303                 // or a 6-12 interaction, but not both.  The index is
00304                 // calculated as follows:
00305                 // index = ICO(NTYPES*(IAC(i)-1)+IAC(j))
00306                 // If index is positive, this is an index into the
00307                 // 6-12 parameter arrays (CN1 and CN2) otherwise it
00308                 // is an index into the 10-12 parameter arrays (ASOL and BSOL).  
00309 }
00310 // FORMAT(20A4)  (LABRES(i), i=1,NRES)
00311 if(strcmp(P[0].S[pa].N,"RESIDUE_LABEL")==0){ // names of residues
00312         P[0].LABRES =pa; // LABRES : the residue labels 
00313         P[0].S[pa].is_standard=0; // set as a standard section
00314         nwhitemid=0; // Total non-terminal whitespace residues
00315         ntrue=0; // Number of actual (non-whitespace) residues found
00316         for(pb=0;pb<P[0].S[pa].nt;pb++){
00317                 PRUNED=strdup(prune_string_whitespace(P[0].S[pa].D[pb])); // Removing whitespace from the read-in data at position pb 
00318 //printf("pb eq %d string eq >>%s<< pruned eq >>%s<<\n",pb,P[0].S[pa].D[pb],PRUNED);
00319                 if(PRUNED[0]!='\0'){ // Not whitespace
00320                         if(ntrue==A.nr){ // If the true number of residues equals the total residues in the assembly
00321 //printf("ntrue eq %d and A.nr eq %d\n",ntrue,A.nr);
00322                                 mywhine("The declared number of residues does not equal the number found! :-(");
00323                                 }
00324                         if(pb>(ntrue+nwhitemid)){ nwhitemid++; } // Increment the number of non-terminal whitespaces, shouldn't this be a "while" loop?
00325                         A.r[ntrue][0].N=(char*)calloc((P[0].S[pa].nc+1),sizeof(char)); // Adjusted for data size, need type-specific functionality
00326                         sscanf(P[0].S[pa].D[pb],"%s",A.r[ntrue][0].N);
00327                         A.r[ntrue][0].N[P[0].S[pa].nc]='\0'; // Adding the 'end of line' character to the end of the string
00328                         ntrue++;
00329                         }
00330                 free(PRUNED);
00331                 }
00332         if(ntrue!=P[0].S[pa].nt){
00333                 printf("WARNING: Found whitespace at flag %s\n",P[0].S[pa].N);
00334                 printf("\tFound %d total",(P[0].S[pa].nt-ntrue));
00335                         if(nwhitemid>0){printf(" and at least %d non-terminal whitespace(s).\nFATAL WARNING: Non-terminal whitespace(s) can allow for mis-assignment of topology components!\n\tCheck that your topology file is correctly built.\n",nwhitemid);}
00336                         else{printf(" terminal whitespace(s).\n");}
00337                 printf("\tIgnoring whitespace(s).\n");
00338                 }
00339 }
00340 // FORMAT(10a8)
00341 if(strcmp(P[0].S[pa].N,"RESIDUE_ID")==0){// ?? Presumably residue numbers, will store there
00342         P[0].IRES =pa; // START HERE -- this is probably the wrong name!!!!!
00343         P[0].S[pa].is_standard=0; // set as a standard section
00344         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.nr);
00345         for(pb=0;pb<A.nr;pb++){sscanf(P[0].S[pa].D[pb],"%d",&A.r[pb][0].n);}
00346 }
00347 // FORMAT(12I6)  (IPRES(i), i=1,NRES)
00348 if(strcmp(P[0].S[pa].N,"RESIDUE_POINTER")==0){ // for adding atoms to residues
00349         P[0].IPRES  =pa; // IPRES  : atoms in each residue are listed for atom "i" in
00350         P[0].S[pa].is_standard=0; // set as a standard section
00351         pc=0;
00352         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.nr);
00353         for(pb=0;pb<(A.nr-1);pb++){
00354                 sscanf(P[0].S[pa].D[pb+1],"%d",&NextRes);
00355                 NextRes-=1;
00356                 A.r[pb][0].na=NextRes-pc;
00357                 A.r[pb][0].a=(atom*)calloc(A.r[pb][0].na,sizeof(atom));
00358                 pd=0;
00359                 for(pc=pc;pc<NextRes;pc++){
00360                         A.r[pb][0].a[pd]=A.a[pc][0]; // copy atom into residue
00361                         A.a[pc]=&A.r[pb][0].a[pd]; // set atom pointer to new location
00362                         A.a[pc][0].n=pc+1; // set the amber original number
00363                         MOLI[pc].i=pc; // set absolute atom number in array terms
00364                         MOLI[pc].m=-1; // we don't know this yet
00365                         MOLI[pc].r=pb; // check this later
00366                         MOLI[pc].a=pd; // check this later
00367                         pd++;
00368                         }
00369                 }
00370                 A.r[pb][0].na=P[0].NATOM-pc;
00371                 A.r[pb][0].a=(atom*)calloc(A.r[pb][0].na,sizeof(atom));
00372                 pd=0;
00373                 for(pc=pc;pc<P[0].NATOM;pc++){
00374                         A.r[pb][0].a[pd]=A.a[pc][0]; // copy atom into residue
00375                         A.a[pc]=&A.r[pb][0].a[pd]; // set atom pointer to new location
00376                         A.a[pc][0].n=pc+1; // set the amber original number
00377                         MOLI[pc].i=pc; // set absolute atom number in array terms
00378                         MOLI[pc].m=-1; // we don't know this yet
00379                         MOLI[pc].r=pb; // check this later
00380                         MOLI[pc].a=pd; // check this later
00381                         pd++;
00382                         }
00383 
00384         
00385 }
00386 // FORMAT(5E16.8)  (RK(i), i=1,NUMBND)
00387 if(strcmp(P[0].S[pa].N,"BOND_FORCE_CONSTANT")==0){ // 
00388         P[0].RK     =pa; // RK     : force constant for the bonds of each type, kcal/mol 
00389         P[0].S[pa].is_standard=0; // set as a standard section
00390         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nBT);
00391         for(pb=0;pb<A.PRM[0][0].nBT;pb++){
00392                 sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].BT[pb].k);
00393                 }
00394 }
00395 // FORMAT(5E16.8)  (REQ(i), i=1,NUMBND)
00396 if(strcmp(P[0].S[pa].N,"BOND_EQUIL_VALUE")==0){
00397         P[0].REQ    =pa; // REQ    : the equilibrium bond length for the bonds of each type, angstroms 
00398         P[0].S[pa].is_standard=0; // set as a standard section
00399         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nBT);
00400         for(pb=0;pb<A.PRM[0][0].nBT;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].BT[pb].l);}
00401 }
00402 // FORMAT(5E16.8)  (TK(i), i=1,NUMANG)
00403 if(strcmp(P[0].S[pa].N,"ANGLE_FORCE_CONSTANT")==0){
00404         P[0].TK     =pa; // TK     : force constant for the angles of each type, kcal/mol A**2 
00405         P[0].S[pa].is_standard=0; // set as a standard section
00406         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nANT);
00407         for(pb=0;pb<A.PRM[0][0].nANT;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].ANT[pb].k);}
00408 }
00409 // FORMAT(5E16.8)  (TEQ(i), i=1,NUMANG)
00410 if(strcmp(P[0].S[pa].N,"ANGLE_EQUIL_VALUE")==0){
00411         P[0].TEQ    =pa; // TEQ    : the equilibrium angle for the angles of each type, radians 
00412         P[0].S[pa].is_standard=0; // set as a standard section
00413         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nANT);
00414         for(pb=0;pb<A.PRM[0][0].nANT;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].ANT[pb].l);}
00415 }
00416 // FORMAT(5E16.8)  (PK(i), i=1,NPTRA)
00417 if(strcmp(P[0].S[pa].N,"DIHEDRAL_FORCE_CONSTANT")==0){
00418         P[0].PK     =pa; // PK     : force constant for the dihedrals of each type, kcal/mol 
00419         P[0].S[pa].is_standard=0; // set as a standard section
00420         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nTRT);
00421         for(pb=0;pb<A.PRM[0][0].nTRT;pb++){
00422                 if(A.PRM[0][0].TRT[pb].n>1){mywhine("A.PRM[0][0].TRT[pb].n>1 in parse_amber_prmtop!");}
00423                 A.PRM[0][0].TRT[pb].n=1;
00424                 A.PRM[0][0].TRT[pb].k=(double*)calloc(1,sizeof(double));
00425                 sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].TRT[pb].k[0]);
00426                 }
00427 }
00428 // FORMAT(5E16.8)  (PN(i), i=1,NPTRA)
00429 if(strcmp(P[0].S[pa].N,"DIHEDRAL_PERIODICITY")==0){
00430         P[0].PN     =pa; // PN     : periodicity of the dihedral of a given type 
00431         P[0].S[pa].is_standard=0; // set as a standard section
00432         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nTRT);
00433         for(pb=0;pb<A.PRM[0][0].nTRT;pb++){
00434                 if(A.PRM[0][0].TRT[pb].n>1){mywhine("A.PRM[0][0].TRT[pb].n>1 in parse_amber_prmtop!");}
00435                 A.PRM[0][0].TRT[pb].n=1;
00436                 A.PRM[0][0].TRT[pb].N=(double*)calloc(1,sizeof(double));
00437                 sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].TRT[pb].N[0]);
00438                 }
00439 }
00440 // FORMAT(5E16.8)  (PHASE(i), i=1,NPTRA)
00441 if(strcmp(P[0].S[pa].N,"DIHEDRAL_PHASE")==0){
00442         P[0].PHASE  =pa; // PHASE  : phase of the dihedral of a given type, radians 
00443         P[0].S[pa].is_standard=0; // set as a standard section
00444         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nTRT);
00445         for(pb=0;pb<A.PRM[0][0].nTRT;pb++){
00446                 if(A.PRM[0][0].TRT[pb].n>1){mywhine("A.PRM[0][0].TRT[pb].n>1 in parse_amber_prmtop!");}
00447                 A.PRM[0][0].TRT[pb].n=1;
00448                 A.PRM[0][0].TRT[pb].P=(double*)calloc(1,sizeof(double));
00449                 sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].TRT[pb].P[0]);
00450                 }
00451 }
00452 // FORMAT(5E16.8)  (SOLTY(i), i=1,NATYP)
00453 if(strcmp(P[0].S[pa].N,"SOLTY")==0){ // not much to do here at the moment, no whitespace check
00454         P[0].SOLTY  =pa; // SOLTY  : currently unused (reserved for future use) 
00455         P[0].S[pa].is_standard=0; // set as a standard section
00456 }
00457 // FORMAT(5E16.8)  (CN1(i), i=1,NTYPES*(NTYPES+1)/2)
00458 if(strcmp(P[0].S[pa].N,"LENNARD_JONES_ACOEF")==0){
00459         P[0].CN1    =pa; // CN1    : Lennard Jones r**12 terms for all possible atom type
00460         P[0].S[pa].is_standard=0; // set as a standard section
00461         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nNBT);
00462         // record the LJ parameters to the bond type info
00463         for(pb=0;pb<A.PRM[0][0].nNBT;pb++){ sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].NBT[pb].LJ12_612); }
00464                 // interactions, indexed by ICO and IAC; for atom i and j
00465                 // where i < j, the index into this array is as follows
00466                 // (assuming the value of ICO(index) is positive):
00467                 // CN1(ICO(NTYPES*(IAC(i)-1)+IAC(j))).  
00468 }
00469 // FORMAT(5E16.8)  (CN2(i), i=1,NTYPES*(NTYPES+1)/2)
00470 if(strcmp(P[0].S[pa].N,"LENNARD_JONES_BCOEF")==0){
00471         P[0].CN2    =pa; // CN2    : Lennard Jones r**6 terms for all possible atom type
00472         P[0].S[pa].is_standard=0; // set as a standard section
00473         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.PRM[0][0].nNBT);
00474         for(pb=0;pb<A.PRM[0][0].nNBT;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].NBT[pb].LJ6_612);}
00475                 // interactions.  Indexed like CN1 above.  
00476 }
00477 /* NOTE: the atom numbers in the following arrays that describe bonds, 
00478         angles, and dihedrals are coordinate array indexes for runtime speed. 
00479         The true atom number equals the absolute value of the number divided by 
00480         three, plus one. In the case of the dihedrals, if the fourth atom is negative, 
00481         this implies that the dihedral is an improper. If the third atom is negative, 
00482         this implies that the end group interations are to be ignored. End group 
00483         interactions are ignored, for example, in dihedrals of various ring systems 
00484         (to prevent double counting of 1-4 interactions) and in multiterm dihedrals.  */
00485 // FORMAT(12I6)  (IBH(i),JBH(i),ICBH(i), i=1,NBONH)
00486 if(strcmp(P[0].S[pa].N,"BONDS_INC_HYDROGEN")==0){
00487         P[0].IBH    =pa; // IBH    : atom involved in bond "i", bond contains hydrogen
00488         P[0].JBH    =pa; // JBH    : atom involved in bond "i", bond contains hydrogen
00489         P[0].ICBH   =pa; // ICBH   : index into parameter arrays RK and REQ 
00490         P[0].S[pa].is_standard=0; // set as a standard section
00491         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,(3*P[0].NBONH));
00492         for(pb=0;pb<P[0].NBONH;pb++){
00493                 // read in the values from the section structure
00494                 sscanf(P[0].S[pa].D[3*pb],"%d",&pA1);
00495                 sscanf(P[0].S[pa].D[3*pb+1],"%d",&pA2);
00496                 sscanf(P[0].S[pa].D[3*pb+2],"%d",&pI1); 
00497                 // find the actual atom numbers
00498                 pA1/=3;  // CAREFUL !! these can be negative
00499                 pA2/=3; 
00500                 // set the bond info for these two atoms
00501                 // -- at this point, everything is in the same molecule, so the molecule index
00502                 //      will be set to -1 (to prevent confusion later).
00503                 //      Also, since we don't know the ordering in the file, most info will not be set
00504                 MB[pb].i=pI1; // holder for the index into the RK & REQ arrays
00505                 MB[pb].D=strdup("BONDS_INC_HYDROGEN");
00506                 MB[pb].s.m=-1; // we don't know the molecule number yet
00507                 MB[pb].s.r=-1; // we can't assume we know the residue number yet
00508                 MB[pb].s.a=pA1; // 
00509                 MB[pb].s.i=pA1; // 
00510                 MB[pb].t.m=-1; 
00511                 MB[pb].t.r=-1; 
00512                 MB[pb].t.i=pA2; 
00513                 MB[pb].t.a=pA2; 
00514                 }
00515 }
00516 // FORMAT(12I6)  (IB(i),JB(i),ICB(i), i=1,NBONA)
00517 if(strcmp(P[0].S[pa].N,"BONDS_WITHOUT_HYDROGEN")==0){
00518         P[0].IB     =pa; // IB     : atom involved in bond "i", bond does not contain hydrogen
00519         P[0].JB     =pa; // JB     : atom involved in bond "i", bond does not contain hydrogen
00520         P[0].ICB    =pa; // ICB    : index into parameter arrays RK and REQ 
00521         P[0].S[pa].is_standard=0; // set as a standard section
00522         //for(pb=P[0].NBONH;pb<(P[0].NBONH+P[0].MBONA);pb++) // save this line for use later...
00523         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,(3*P[0].MBONA));
00524         for(pb=0;pb<P[0].MBONA;pb++){ // save this line for use later...
00525                 // read in the values from the section structure
00526                 sscanf(P[0].S[pa].D[3*pb],"%d",&pA1);
00527                 sscanf(P[0].S[pa].D[3*pb+1],"%d",&pA2);
00528                 sscanf(P[0].S[pa].D[3*pb+2],"%d",&pI1); 
00529                 // find the actual atom numbers
00530                 if(pA1<0) pA1*=-1;
00531                 if(pA2<0) pA2*=-1;
00532                 pA1/=3; // CAREFUL !! these can be negative
00533                 pA2/=3; 
00534                 // set the bond info for these two atoms
00535                 // -- at this point, everything is in the same molecule, so the molecule index
00536                 //      will be set to -1 (to prevent confusion later).
00537                 //      Also, since we don't know the ordering in the file, most info will not be set
00538                 MB[pb+P[0].NBONH].i=pI1; // holder for the index into the RK & REQ arrays
00539                 MB[pb+P[0].NBONH].D=strdup("BONDS_WITHOUT_HYDROGEN");
00540                 MB[pb+P[0].NBONH].s.m=-1; // we don't know the molecule number yet
00541                 MB[pb+P[0].NBONH].s.r=-1; // we can't assume we know the residue number yet
00542                 MB[pb+P[0].NBONH].s.a=pA1; // the best atom number we have at the moment
00543                 MB[pb+P[0].NBONH].s.i=pA1; // for assigning molecules based on bonds, later
00544                 MB[pb+P[0].NBONH].t.m=-1; 
00545                 MB[pb+P[0].NBONH].t.r=-1; 
00546                 MB[pb+P[0].NBONH].t.a=pA2; 
00547                 MB[pb+P[0].NBONH].t.i=pA2; 
00548                 }
00549 }
00550 // FORMAT(12I6)  (ITH(i),JTH(i),KTH(i),ICTH(i), i=1,NTHETH)
00551 if(strcmp(P[0].S[pa].N,"ANGLES_INC_HYDROGEN")==0){
00552         P[0].ITH    =pa; // ITH    : atom involved in angle "i", angle contains hydrogen
00553         P[0].JTH    =pa; // JTH    : atom involved in angle "i", angle contains hydrogen
00554         P[0].KTH    =pa; // KTH    : atom involved in angle "i", angle contains hydrogen
00555         P[0].ICTH   =pa; // ICTH   : index into parameter arrays TK and TEQ for angle
00556         P[0].S[pa].is_standard=0; // set as a standard section
00557         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,(4*P[0].NTHETH));
00558         for(pb=0;pb<P[0].NTHETH;pb++){ // angles with hydrogen
00559                 // read in the values from the section structure
00560                 sscanf(P[0].S[pa].D[4*pb],"%d",&pA1);
00561                 sscanf(P[0].S[pa].D[4*pb+1],"%d",&pA2);
00562                 sscanf(P[0].S[pa].D[4*pb+2],"%d",&pA3);
00563                 sscanf(P[0].S[pa].D[4*pb+3],"%d",&pI1); 
00564                 // find the actual atom numbers
00565                 pA1/=3; // CAREFUL !! these can be negative
00566                 pA2/=3; 
00567                 pA3/=3; 
00568                 // set the bond info for these two atoms
00569                 // -- at this point, everything is in the same molecule, so the molecule index
00570                 //      will be set to -1 (to prevent confusion later).
00571                 //      Also, since we don't know the ordering in the file, most info will not be set
00572                 MANG[pb].i=pI1; // holder for the index into the RK & REQ arrays
00573                 MANG[pb].D=strdup("ANGLES_INC_HYDROGEN");
00574                 MANG[pb].a.m=-1; // we don't know the molecule number yet
00575                 MANG[pb].a.r=-1; // we can't assume we know the residue number yet
00576                 MANG[pb].a.a=pA1; // we can't assume the atoms are already read in
00577                 MANG[pb].b.m=-1; 
00578                 MANG[pb].b.r=-1;
00579                 MANG[pb].b.a=pA2; 
00580                 MANG[pb].c.m=-1; 
00581                 MANG[pb].c.r=-1; 
00582                 MANG[pb].c.a=pA3; 
00583                 }
00584 }
00585                 // ITH(i)-JTH(i)-KTH(i) 
00586 // FORMAT(12I6)  (IT(i),JT(i),KT(i),ICT(i), i=1,NTHETA)
00587 if(strcmp(P[0].S[pa].N,"ANGLES_WITHOUT_HYDROGEN")==0){
00588         P[0].IT     =pa; // IT     : atom involved in angle "i", angle does not contain hydrogen
00589         P[0].JT     =pa; // JT     : atom involved in angle "i", angle does not contain hydrogen
00590         P[0].KT     =pa; // KT     : atom involved in angle "i", angle does not contain hydrogen
00591         P[0].ICT    =pa; // ICT    : index into parameter arrays TK and TEQ for angle
00592         P[0].S[pa].is_standard=0; // set as a standard section
00593         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,(4*P[0].MTHETA));
00594         for(pb=0;pb<P[0].MTHETA;pb++){ // angles without hydrogen
00595                 // read in the values from the section structure
00596                 sscanf(P[0].S[pa].D[4*pb],"%d",&pA1);
00597                 sscanf(P[0].S[pa].D[4*pb+1],"%d",&pA2);
00598                 sscanf(P[0].S[pa].D[4*pb+2],"%d",&pA3);
00599                 sscanf(P[0].S[pa].D[4*pb+3],"%d",&pI1); 
00600                 // find the actual atom numbers
00601                 pA1/=3; // CAREFUL !! these can be negative
00602                 pA2/=3; 
00603                 pA3/=3; 
00604                 // set the bond info for these two atoms
00605                 // -- at this point, everything is in the same molecule, so the molecule index
00606                 //      will be set to -1 (to prevent confusion later).
00607                 //      Also, since we don't know the ordering in the file, most info will not be set
00608                 MANG[pb+P[0].NTHETH].i=pI1; // holder for the index into the RK & REQ arrays
00609                 MANG[pb+P[0].NTHETH].D=strdup("ANGLES_WITHOUT_HYDROGEN");
00610                 MANG[pb+P[0].NTHETH].a.m=-1; // we don't know the molecule number yet
00611                 MANG[pb+P[0].NTHETH].a.r=-1; // we can't assume we know the residue number yet
00612                 MANG[pb+P[0].NTHETH].a.a=pA1; // we can't assume the atoms are read in already
00613                 MANG[pb+P[0].NTHETH].b.m=-1; 
00614                 MANG[pb+P[0].NTHETH].b.r=-1; 
00615                 MANG[pb+P[0].NTHETH].b.a=pA2; 
00616                 MANG[pb+P[0].NTHETH].c.m=-1; 
00617                 MANG[pb+P[0].NTHETH].c.r=-1; 
00618                 MANG[pb+P[0].NTHETH].c.a=pA3; 
00619                 }
00620 }
00621                 // IT(i)-JT(i)-KT(i) 
00622 // FORMAT(12I6)  (IPH(i),JPH(i),KPH(i),LPH(i),ICPH(i), i=1,NPHIH)
00623 if(strcmp(P[0].S[pa].N,"DIHEDRALS_INC_HYDROGEN")==0){
00624         P[0].IPH    =pa; // IPH    : atom involved in dihedral "i", dihedral contains hydrogen
00625         P[0].JPH    =pa; // JPH    : atom involved in dihedral "i", dihedral contains hydrogen
00626         P[0].KPH    =pa; // KPH    : atom involved in dihedral "i", dihedral contains hydrogen
00627         P[0].LPH    =pa; // LPH    : atom involved in dihedral "i", dihedral contains hydrogen
00628         P[0].ICPH   =pa; // ICPH   : index into parameter arrays PK, PN, and PHASE for
00629         P[0].S[pa].is_standard=0; // set as a standard section
00630         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,(5*P[0].NPHIH));
00631         for(pb=0;pb<P[0].NPHIH;pb++){ // dihedrals with hydrogen
00632                 // read in the values from the section structure
00633                 sscanf(P[0].S[pa].D[5*pb],"%d",&pA1);
00634                 sscanf(P[0].S[pa].D[5*pb+1],"%d",&pA2);
00635                 sscanf(P[0].S[pa].D[5*pb+2],"%d",&pA3);
00636                 sscanf(P[0].S[pa].D[5*pb+3],"%d",&pA3);
00637                 sscanf(P[0].S[pa].D[5*pb+4],"%d",&pI1); 
00638                 // find the actual atom numbers
00639                 pA1/=3; // CAREFUL !! these can be negative
00640                 pA2/=3; 
00641                 pA3/=3; 
00642                 pA4/=3; 
00643                 // set the bond info for these two atoms
00644                 // -- at this point, everything is in the same molecule, so the molecule index
00645                 //      will be set to -1 (to prevent confusion later).
00646                 //      Also, since we don't know the ordering in the file, most info will not be set
00647                 MTOR[pb].i=pI1; // holder for the index into the RK & REQ arrays
00648                 MTOR[pb].D=strdup("DIHEDRALS_INC_HYDROGEN");
00649                 MTOR[pb].a.m=-1; // we don't know the molecule number yet
00650                 MTOR[pb].a.r=-1; // we can't assume we know the residue number yet
00651                 MTOR[pb].a.a=pA1; // we can't assume the atoms are read in already
00652                 MTOR[pb].b.m=-1; 
00653                 MTOR[pb].b.r=-1; 
00654                 MTOR[pb].b.a=pA2; 
00655                 MTOR[pb].c.m=-1; 
00656                 MTOR[pb].c.r=-1; 
00657                 MTOR[pb].c.a=pA3; 
00658                 MTOR[pb].d.m=-1; 
00659                 MTOR[pb].d.r=-1; 
00660                 MTOR[pb].d.a=pA4; 
00661                 }
00662 }
00663                 // dihedral IPH(i)-JPH(i)-KPH(i)-LPH(i) 
00664 // FORMAT(12I6)  (IP(i),JP(i),KP(i),LP(i),ICP(i), i=1,NPHIA)
00665 
00666 if(strcmp(P[0].S[pa].N,"DIHEDRALS_WITHOUT_HYDROGEN")==0){
00667         P[0].IP     =pa; // IP     : atom involved in dihedral "i", dihedral does not contain hydrogen
00668         P[0].JP     =pa; // JP     : atom involved in dihedral "i", dihedral does not contain hydrogen
00669         P[0].KP     =pa; // KP     : atom involved in dihedral "i", dihedral does not contain hydrogen
00670         P[0].LP     =pa; // LP     : atom involved in dihedral "i", dihedral does not contain hydrogen
00671         P[0].ICP    =pa; // ICP    : index into parameter arrays PK, PN, and PHASE for
00672         P[0].S[pa].is_standard=0; // set as a standard section
00673         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,(5*P[0].MPHIA));
00674         for(pb=0;pb<P[0].MPHIA;pb++){ // dihedrals with hydrogen
00675                 // read in the values from the section structure
00676                 sscanf(P[0].S[pa].D[5*pb],"%d",&pA1);
00677                 sscanf(P[0].S[pa].D[5*pb+1],"%d",&pA2);
00678                 sscanf(P[0].S[pa].D[5*pb+2],"%d",&pA3);
00679                 sscanf(P[0].S[pa].D[5*pb+3],"%d",&pA3);
00680                 sscanf(P[0].S[pa].D[5*pb+4],"%d",&pI1); 
00681                 // find the actual atom numbers
00682                 pA1/=3; // CAREFUL !! these can be negative
00683                 pA2/=3; 
00684                 pA3/=3; 
00685                 pA4/=3; 
00686                 // set the bond info for these two atoms
00687                 // -- at this point, everything is in the same molecule, so the molecule index
00688                 //      will be set to -1 (to prevent confusion later).
00689                 //      Also, since we don't know the ordering in the file, most info will not be set
00690                 MTOR[pb+P[0].NPHIH].i=pI1; // holder for the index into the RK & REQ arrays
00691                 MTOR[pb+P[0].NPHIH].D=strdup("DIHEDRALS_INC_HYDROGEN");
00692                 MTOR[pb+P[0].NPHIH].a.m=-1; // we don't know the molecule number yet
00693                 MTOR[pb+P[0].NPHIH].a.r=-1; // we can't assume we know the residue number yet
00694                 MTOR[pb+P[0].NPHIH].a.a=pA1; // we can't assume the atoms are read in already
00695                 MTOR[pb+P[0].NPHIH].b.m=-1; 
00696                 MTOR[pb+P[0].NPHIH].b.r=-1; 
00697                 MTOR[pb+P[0].NPHIH].b.a=pA2; 
00698                 MTOR[pb+P[0].NPHIH].c.m=-1; 
00699                 MTOR[pb+P[0].NPHIH].c.r=-1; 
00700                 MTOR[pb+P[0].NPHIH].c.a=pA3; 
00701                 MTOR[pb+P[0].NPHIH].d.m=-1; 
00702                 MTOR[pb+P[0].NPHIH].d.r=-1; 
00703                 MTOR[pb+P[0].NPHIH].d.a=pA4; 
00704                 }
00705 }
00706 
00707                 // dihedral IPH(i)-JPH(i)-KPH(i)-LPH(i).  Note, if the
00708                 // periodicity is negative, this implies the following entry
00709                 // in the PK, PN, and PHASE arrays is another term in a
00710                 // multitermed dihedral.  
00711 // FORMAT(12I6)  (NATEX(i), i=1,NEXT)
00712 if(strcmp(P[0].S[pa].N,"EXCLUDED_ATOMS_LIST")==0){  // Not currently stored so no whitespace check
00713         P[0].NATEX  =pa; // NATEX  : the excluded atom list.  To get the excluded list for atom
00714         P[0].S[pa].is_standard=0; // set as a standard section
00715 }
00716                 // "i" you need to traverse the NUMEX list, adding up all
00717                 // the previous NUMEX values, since NUMEX(i) holds the number
00718                 // of excluded atoms for atom "i", not the index into the 
00719                 // NATEX list.  Let IEXCL = SUM(NUMEX(j), j=1,i-1), then
00720                 // excluded atoms are NATEX(IEXCL) to NATEX(IEXCL+NUMEX(i)).  
00721 // FORMAT(5E16.8)  (ASOL(i), i=1,NPHB)
00722 if(strcmp(P[0].S[pa].N,"HBOND_ACOEF")==0){
00723         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,P[0].NPHB);// NOTE: Not sure if these values match - no files to compare to, MBT 2010-10-26
00724         P[0].ASOL   =pa; // ASOL   : the value for the r**12 term for hydrogen bonds of all
00725         P[0].S[pa].is_standard=0; // set as a standard section
00726         if(P[0].NPHB>0){
00727         if(P[0].S[pa].nt>0){
00728         for(pb=0;pb<P[0].S[pa].nt;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].NBT[pb].LJ12_1012);}
00729                 }
00730                 }
00731 }
00732                 // possible types.  Index into these arrays is equivalent
00733                 // to the CN1 and CN2 arrays, however the index is negative.
00734                 // For example, for atoms i and j, with i < j, the index is
00735                 // ICO(NTYPES*(IAC(i)-1+IAC(j)).  
00736 // FORMAT(5E16.8)  (BSOL(i), i=1,NPHB)
00737 if(strcmp(P[0].S[pa].N,"HBOND_BCOEF")==0){
00738         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,P[0].NPHB);// NOTE: Not sure if these values match - no files to compare to, MBT 2010-10-26
00739         P[0].BSOL   =pa; // BSOL   : the value for the r**10 term for hydrogen bonds of all
00740         P[0].S[pa].is_standard=0; // set as a standard section
00741         if(P[0].NPHB>0){
00742         if(P[0].S[pa].nt>0){
00743                 for(pb=0;pb<P[0].S[pa].nt;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&A.PRM[0][0].NBT[pb].LJ10_1012);}
00744                 }
00745                 }
00746 }
00747                 // possible types.  Indexed like ASOL.  
00748 // FORMAT(5E16.8)  (HBCUT(i), i=1,NPHB)
00749 if(strcmp(P[0].S[pa].N,"HBCUT")==0){ // no whitespace check used
00750         P[0].HBCUT  =pa; // HBCUT  : no longer in use 
00751         P[0].S[pa].is_standard=0; // set as a standard section
00752 }
00753 // FORMAT(20A4)  (ISYMBL(i), i=1,NATOM)
00754 if(strcmp(P[0].S[pa].N,"AMBER_ATOM_TYPE")==0){
00755         P[0].ISYMBL =pa; // ISYMBL : the AMBER atom types for each atom 
00756         P[0].S[pa].is_standard=0; // set as a standard section
00757         // Can't assume we've already read in the type numbers...
00758         // read one per each atom, just like it is in the file
00759         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00760         ATNAME=(char**)calloc(A.na,sizeof(char*));
00761         for(pb=0;pb<A.na;pb++){
00762                 ATNAME[pb]=(char*)calloc(P[0].S[pa].nc+1,sizeof(char));
00763                 sscanf(P[0].S[pa].D[pb],"%s",ATNAME[pb]);
00764                 }
00765 }
00766 // FORMAT(20A4)  (ITREE(i), i=1,NATOM)
00767 if(strcmp(P[0].S[pa].N,"TREE_CHAIN_CLASSIFICATION")==0){
00768         P[0].ITREE  =pa; // ITREE  : the list of tree joining information, classified into five
00769         P[0].S[pa].is_standard=0; // set as a standard section
00770         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00771         TREECLASS=(char**)calloc(A.na,sizeof(char*));
00772         for(pb=0;pb<A.na;pb++){
00773                 TREECLASS[pb]=(char*)calloc(P[0].S[pa].nc+1,sizeof(char));
00774                 sscanf(P[0].S[pa].D[pb],"%s",TREECLASS[pb]);
00775                 }
00776 }
00777                 // types.  M -- main chain, S -- side chain, B -- branch point, 
00778                 // 3 -- branch into three chains, E -- end of the chain 
00779 // FORMAT(12I6)  (JOIN(i), i=1,NATOM)
00780 if(strcmp(P[0].S[pa].N,"JOIN_ARRAY")==0){ // no whitespace check used
00781         P[0].JOIN   =pa; // JOIN   : tree joining information, potentially used in ancient
00782                 // analysis programs.  Currently unused in sander or gibbs.  
00783         P[0].S[pa].is_standard=0; // set as a standard section
00784 }
00785 // FORMAT(12I6)  (IROTAT(i), i = 1, NATOM)
00786 if(strcmp(P[0].S[pa].N,"IROTAT")==0){ //no whitespace check used
00787         P[0].IROTAT =pa; // IROTAT : apparently the last atom that would move if atom i was
00788                 // rotated, however the meaning has been lost over time.
00789                 // Currently unused in sander or gibbs.
00790         P[0].S[pa].is_standard=0; // set as a standard section
00791 }
00792 // FORMAT(12I6)  IPTRES, NSPM, NSPSOL
00793 if(strcmp(P[0].S[pa].N,"SOLVENT_POINTERS")==0){
00794         P[0].IPTRES =pa; // IPTRES : final residue that is considered part of the solute,
00795                 // reset in sander and gibbs
00796         P[0].NSPM   =pa; // NSPM   : total number of molecules
00797         P[0].NSPSOL =pa; // NSPSOL : the first solvent "molecule" 
00798         P[0].S[pa].is_standard=0; // set as a standard section
00799         ntrue=count_array_nws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N);
00800         if(ntrue==3){
00801                 sscanf(P[0].S[pa].D[0],"%d",&IPTRES);
00802                 sscanf(P[0].S[pa].D[1],"%d",&NSPM);
00803                 sscanf(P[0].S[pa].D[2],"%d",&NSPSOL);
00804                 }
00805         else{printf("WARNING: Non-standard or non-existent solvent pointer information\n\tIgnoring this section...\n");}
00806 }
00807 // FORMAT(12I6)  (NSP(i), i=1,NSPM)
00808 if(strcmp(P[0].S[pa].N,"ATOMS_PER_MOLECULE")==0){ // Need to add a comparison to A.m[i][0].na (if not set, then add all the A.m[i][0].r[j].na's up) and WHITESPACE CHECK
00809 // Note that a check for this is not currently available until AFTER the A.nm value is defined (near the end of this program)
00810         P[0].NSP    =pa; // NSP    : the total number of atoms in each molecule,
00811                 // necessary to correctly perform the pressure scaling.  
00812         P[0].S[pa].is_standard=0; // set as a standard section
00813         NSP=(int*)calloc(P[0].S[pa].nt,sizeof(int));
00814         for(pb=0;pb<P[0].S[pa].nt;pb++){sscanf(P[0].S[pa].D[pb],"%d",&NSP[pb]);}
00815 }
00816 // FORMAT(5E16.8)  BETA, BOX(1), BOX(2), BOX(3)
00817 if(strcmp(P[0].S[pa].N,"BOX_DIMENSIONS")==0){
00818         P[0].BETA   =pa; // BETA   : periodic box, angle between the XY and YZ planes in degrees.
00819         P[0].BOX    =pa; // BOX    : the periodic box lengths in the X, Y, and Z directions 
00820         P[0].S[pa].is_standard=0; // set as a standard section
00821         ntrue=count_array_nws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N); // Non-comparative whitespace check
00822 // Checks for box definitions
00823         if(P[0].IFBOX==1 && ntrue==4){ // Cubic box definition from the header
00824                 sscanf(P[0].S[pa].D[0],"%lf",&A.BOX[0].C[0].D[0]); ///< Record value of BETA
00825                 sscanf(P[0].S[pa].D[1],"%lf",&A.BOX[0].C[1].D[0]); ///< Record BOX X
00826                 sscanf(P[0].S[pa].D[2],"%lf",&A.BOX[0].C[1].D[1]); ///< Record BOX Y
00827                 sscanf(P[0].S[pa].D[3],"%lf",&A.BOX[0].C[1].D[2]); ///< Record BOX Z
00828                 }
00829         else if(P[0].IFBOX==2){ //Octahedral box definition from the header ADD an ntrue comparison for octahedral box definitions
00830                 fprintf(stderr,"\nWARNING: Octahedral box definitions are not currently stored in the assembly.\n\tPlease include a parsing function. Ignoring any contents in this section.\nALERT: Any call to A.BOX or A.nBOX variables may cause memory issues without a segmentation fault.\n");
00831                 }
00832         else{fprintf(stderr,"\nIn parse_amber_prmtop.c : unexpected number of entries in section BOX_DIMENSIONS.  Ignoring contents.\nALERT: Any call to A.BOX or A.nBOX variables may cause memory issues without a segmentation fault.\n\n");}
00833 }
00834 // The following are only present if IFCAP .gt. 0 
00835 // FORMAT(12I6)  NATCAP
00836 if(strcmp(P[0].S[pa].N,"CAP_INFO")==0){ // no whitespace check
00837         P[0].NATCAP =pa; // NATCAP : last atom before the start of the cap of waters placed by edit 
00838         P[0].S[pa].is_standard=0; // set as a standard section
00839 }
00840 // FORMAT(5E16.8)  CUTCAP, XCAP, YCAP, ZCAP
00841 if(strcmp(P[0].S[pa].N,"CAP_INFO2")==0){ // not putting this in quite yet, no whitespace check
00842         P[0].CUTCAP =pa; // CUTCAP : the distance from the center of the cap to the outside
00843         P[0].XCAP   =pa; // XCAP   : X coordinate for the center of the cap
00844         P[0].YCAP   =pa; // YCAP   : Y coordinate for the center of the cap
00845         P[0].ZCAP   =pa; // ZCAP   : Z coordinate for the center of the cap 
00846         P[0].S[pa].is_standard=0; // set as a standard section
00847 }
00848 if(strcmp(P[0].S[pa].N,"RADIUS_SET")==0){
00849         P[0].S[pa].is_standard=0; // set as a standard section
00850         ntrue=count_array_nws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N); // Non-comparative whitespace check
00851         if(ntrue>0){RADTYPE=strdup(P[0].S[pa].D[0]);}
00852 }
00853 if(strcmp(P[0].S[pa].N,"RADII")==0){
00854         P[0].S[pa].is_standard=0; // set as a standard section
00855         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00856         R=(double*)calloc(A.na,sizeof(double));
00857         for(pb=0;pb<A.na;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&R[pb]);}
00858 }
00859 if(strcmp(P[0].S[pa].N,"SCREEN")==0){
00860         P[0].S[pa].is_standard=0; // set as a standard section
00861         compare_array_ws(P[0].S[pa].nt,P[0].S[pa].D,P[0].S[pa].N,A.na);
00862         SC=(double*)calloc(A.na,sizeof(double));
00863         for(pb=0;pb<A.na;pb++){sscanf(P[0].S[pa].D[pb],"%lf",&SC[pb]);}
00864 }
00865 if(strcmp(P[0].S[pa].N,"LES_NTYP")==0){ // leave these out for now, no whitespace check
00866         P[0].S[pa].is_standard=0; // set as a standard section
00867 }
00868 if(strcmp(P[0].S[pa].N,"LES_TYPE")==0){ // no whitespace check
00869         P[0].S[pa].is_standard=0; // set as a standard section
00870 }
00871 if(strcmp(P[0].S[pa].N,"LES_FAC")==0){ // no whitespace check
00872         P[0].S[pa].is_standard=0; // set as a standard section
00873 }
00874 if(strcmp(P[0].S[pa].N,"LES_CNUM")==0){ // no whitespace check
00875         P[0].S[pa].is_standard=0; // set as a standard section
00876 }
00877 if(strcmp(P[0].S[pa].N,"LES_ID")==0){ // no whitespace check
00878         P[0].S[pa].is_standard=0; // set as a standard section
00879 }
00880 // The following is only present if IFPERT .gt. 0
00881 /* Note that the initial state, or equivalently the prep/link/edit state, 
00882         is represented by lambda=1 and the perturbed state, or final state 
00883         specified in parm, is the lambda=0 state. */ 
00884 // FORMAT(12I6)  (IBPER(i), JBPER(i), i=1,NBPER)
00885 if(strcmp(P[0].S[pa].N,"PERT_BOND_ATOMS")==0){ // no whitespace check
00886 // The following are only present if IFBOX .gt. 0 
00887         P[0].IBPER  =pa; // IBPER  : atoms involved in perturbed bonds
00888         P[0].JBPER  =pa; // JBPER  : atoms involved in perturbed bonds 
00889         P[0].S[pa].is_standard=0; // set as a standard section
00890 }
00891 // FORMAT(12I6)  (ICBPER(i), i=1,2*NBPER)
00892 if(strcmp(P[0].S[pa].N,"PERT_BOND_PARAMS")==0){ // no whitespace check
00893         P[0].ICBPER =pa; // ICBPER : pointer into the bond parameter arrays RK and REQ for the
00894         P[0].S[pa].is_standard=0; // set as a standard section
00895 }
00896                 // perturbed bonds.  ICBPER(i) represents lambda=1 and 
00897                 // ICBPER(i+NBPER) represents lambda=0.  
00898 // FORMAT(12I6)  (ITPER(i), JTPER(i), KTPER(i), i=1,NGPER)
00899 if(strcmp(P[0].S[pa].N,"PERT_ANGLE_ATOMS")==0){ // no whitespace check
00900         P[0].IPTER  =pa; // IPTER  : atoms involved in perturbed angles
00901         P[0].JTPER  =pa; // JTPER  : atoms involved in perturbed angles
00902         P[0].KTPER  =pa; // KTPER  : atoms involved in perturbed angles 
00903         P[0].S[pa].is_standard=0; // set as a standard section
00904 }
00905 // FORMAT(12I6)  (ICTPER(i), i=1,2*NGPER)
00906 if(strcmp(P[0].S[pa].N,"PERT_ANGLE_PARAMS")==0){ // no whitespace check
00907         P[0].ICTPER =pa; // ICTPER : pointer into the angle parameter arrays TK and TEQ for 
00908         P[0].S[pa].is_standard=0; // set as a standard section
00909 }
00910                 // the perturbed angles.  ICTPER(i) represents lambda=0 and 
00911                 // ICTPER(i+NGPER) represents lambda=1.  
00912 // FORMAT(12I6)  (IPPER(i), JPPER(i), KPPER(i), LPPER(i), i=1,NDPER)
00913 if(strcmp(P[0].S[pa].N,"PERT_DIHEDRAL_ATOMS")==0){ // no whitespace checkf
00914         P[0].IPPER  =pa; // IPPER  : atoms involved in perturbed dihedrals
00915         P[0].JPPER  =pa; // JPPER  : atoms involved in perturbed dihedrals
00916         P[0].KPPER  =pa; // KPPER  : atoms involved in perturbed dihedrals
00917         P[0].LPPER  =pa; // LPPER  : atoms involved in pertrubed dihedrals 
00918         P[0].S[pa].is_standard=0; // set as a standard section
00919 }
00920 // FORMAT(12I6)  (ICPPER(i), i=1,2*NDPER)
00921 if(strcmp(P[0].S[pa].N,"PERT_DIHEDRAL_PARAMS")==0){ // no whitespace check
00922         P[0].ICPPER =pa; // ICPPER : pointer into the dihedral parameter arrays PK, PN and
00923         P[0].S[pa].is_standard=0; // set as a standard section
00924 }
00925                 // PHASE for the perturbed dihedrals.  ICPPER(i) represents 
00926                 // lambda=1 and ICPPER(i+NGPER) represents lambda=0.  
00927 // FORMAT(20A4)  (LABRES(i), i=1,NRES)
00928 if(strcmp(P[0].S[pa].N,"PERT_RESIDUE_NAME")==0){ // no whitespace check
00929         P[0].LABRES =pa; // LABRES : residue names at lambda=0 
00930         P[0].S[pa].is_standard=0; // set as a standard section
00931 }
00932 // FORMAT(20A4)  (IGRPER(i), i=1,NATOM)
00933 if(strcmp(P[0].S[pa].N,"PERT_ATOM_NAME")==0){ // no whitespace check
00934         P[0].IGRPER =pa; // IGRPER : atomic names at lambda=0 
00935         P[0].S[pa].is_standard=0; // set as a standard section
00936 }
00937 // FORMAT(20A4)  (ISMPER(i), i=1,NATOM)
00938 if(strcmp(P[0].S[pa].N,"PERT_ATOM_SYMBOL")==0){ // no whitespace check
00939         P[0].ISMPER =pa; // ISMPER : atomic symbols at lambda=0 
00940         P[0].S[pa].is_standard=0; // set as a standard section
00941 }
00942 // FORMAT(5E16.8)  (ALMPER(i), i=1,NATOM)
00943 if(strcmp(P[0].S[pa].N,"ALMPER")==0){ // no whitespace check
00944         P[0].ALMPER =pa; // ALMPER : unused currently in gibbs 
00945         P[0].S[pa].is_standard=0; // set as a standard section
00946 }
00947 // FORMAT(12I6)  (IAPER(i), i=1,NATOM)
00948 if(strcmp(P[0].S[pa].N,"IAPER")==0){ // no whitespace check
00949         P[0].IAPER  =pa; // IAPER  : IAPER(i) = 1 if the atom is being perturbed 
00950         P[0].S[pa].is_standard=0; // set as a standard section
00951 }
00952 // FORMAT(12I6)  (IACPER(i), i=1,NATOM)
00953 if(strcmp(P[0].S[pa].N,"PERT_ATOM_TYPE_INDEX")==0){ // no whitespace check
00954         P[0].IACPER =pa; // IACPER : index for the atom types involved in Lennard Jones
00955         P[0].S[pa].is_standard=0; // set as a standard section
00956 }
00957                 // interactions at lambda=0.  Similar to IAC above.  See ICO above.  
00958 // FORMAT(5E16.8)  (CGPER(i), i=1,NATOM)
00959 if(strcmp(P[0].S[pa].N,"PERT_CHARGE")==0){ // no whitespace check
00960         P[0].CGPER  =pa; // CGPER  : atomic charges at lambda=0 
00961         P[0].S[pa].is_standard=0; // set as a standard section
00962 }
00963 // The following is only present if IPOL .eq. 1 
00964 // FORMAT(5E18.8) (ATPOL(i), i=1,NATOM)
00965 if(strcmp(P[0].S[pa].N,"POLARIZABILITY")==0){ // leave out for now, // no whitespace check
00966         P[0].ATPOL  =pa; // ATPOL  : atomic polarizabilities 
00967         P[0].S[pa].is_standard=0; // set as a standard section
00968 }
00969 // The following is only present if IPOL .eq. 1 .and. IFPERT .eq. 1 
00970 // FORMAT(5E18.8) (ATPOL1(i), i=1,NATOM)
00971 if(strcmp(P[0].S[pa].N,"PERT_POLARIZABILITY")==0){ // no whitespace check
00972         P[0].ATPOL1 =pa; // ATPOL1 : atomic polarizabilities at lambda = 1 (above is at lambda = 0) 
00973         P[0].S[pa].is_standard=0; // set as a standard section
00974 }
00975         } // close loop through each section in the prmtop structure
00976 
00977 /*  The following code prints out the prmtop file exactly as read in from the unparsed read */
00978 /*
00979 fileset F;
00980 F.N=strdup("test_rewrite_of_prmtop");
00981 F.F=myfopen(F.N,"w");
00982 fprintf(F.F,"%s",P[0].VERSION);
00983 for(pa=0;pa<P[0].nS;pa++){ // for each section found
00984         fprintf(F.F,"%%FLAG %s\n",P[0].S[pa].N);
00985         fprintf(F.F,"%%FORMAT(%s)\n",P[0].S[pa].FORMAT);
00986         for(pb=0;pb<P[0].S[pa].nt;pb++){
00987                 fprintf(F.F,"%s",P[0].S[pa].D[pb]);
00988                 //fprintf(F.F,"D[%d] is >>>%s<<<\n",pb,P[0].S[pa].D[pb]);
00989                 fflush(F.F);
00990 //printf("\npb is %d ; P[0].S[%d].npl is %d ; (pb+1)%%npl is %d\n",pb,pa,P[0].S[pa].npl,);
00991                 if((((pb+1)%P[0].S[pa].npl))==0){fprintf(F.F,"\n");} 
00992                 //if((((pb+1)*P[0].S[pa].nc))%80==0){printf("\n");} 
00993                 }
00994         if(P[0].S[pa].nt==0){fprintf(F.F,"\n");}
00995         if(((pb)*P[0].S[pa].nc)%80!=0){fprintf(F.F,"\n");} 
00996         }
00997 fclose(F.F);
00998 */
00999 
01000 // Set the names of the atom types in the type array and in the atom struct
01001 for(pa=0;pa<A.na;pa++){ 
01002         A.a[pa][0].T=strdup(ATNAME[pa]); 
01003         A.PRM[0][0].AT[A.a[pa][0].t].N=strdup(ATNAME[pa]); 
01004         }
01005 // Now set the names in the non-bonded bond type array
01006 // -- set atom information in the LJ type arrays
01007 //int *ICO,nICO;
01008 if(nICO!=(A.PRM[0][0].nAT*A.PRM[0][0].nAT)){mywhine("nICO!=(A.PRM[0][0].nAT*A.PRM[0][0].nAT) in parse_amber_prmtop");}
01009 // For example, for atoms i and j, with i < j, the index is
01010 // ICO(NTYPES*(IAC(i)-1)+IAC(j)).  
01011 pI1=P[0].NTYPES*(P[0].NTYPES+1)/2;
01012 for(pa=0;pa<A.PRM[0][0].nAT;pa++){ // this is index 'j' in the prmtop file
01013 for(pb=0;pb<(pa+1);pb++){ // this is index 'i' in the prmtop file
01014         // allocate space for the names of the two atom types
01015         pc=P[0].NTYPES*pb+pa;
01016         if(pc>nICO){mywhine("pc>nICO in parse_amber_prmtop");}
01017         if(ICO[pc]>pI1){mywhine("ICO[pc]>(P[0].NTYPES*(P[0].NTYPES+1)/2) in parse_amber_prmtop");}
01018         A.PRM[0][0].NBT[ICO[pc]].NT=(char**)calloc(2,sizeof(char*));
01019         A.PRM[0][0].NBT[ICO[pc]].NT[0]=strdup(A.PRM[0][0].AT[pb].N);
01020         A.PRM[0][0].NBT[ICO[pc]].NT[1]=strdup(A.PRM[0][0].AT[pa].N);
01021         }
01022 }
01023 
01024 // set molecule information
01025 //      First, copy MOLI & MB arrays for safety & record
01026 MOLBNDI=(molindex*)calloc(P[0].NATOM,sizeof(molindex));
01027 MBTMP=(molbond*)calloc(A.nb,sizeof(molbond));
01028 for(pa=0;pa<P[0].NATOM;pa++){ MOLBNDI[pa]=MOLI[pa]; }
01029 for(pa=0;pa<A.nb;pa++){ 
01030         MBTMP[pa]=MB[pa]; 
01031         }
01032 // call the "find molecules" function
01033 find_molecules_molbond_array(A.nb, MBTMP, P[0].NATOM, MOLBNDI);
01034 
01035 // Rearrange the structures to reflect the new molecule information
01036 // 1. Find numbers of molecules and make space
01037 //      The molecules, coming from find_molecules_molbond_array, should count 
01038 //      sequentially starting with zero.
01039 // 2. While we're at it, associate each residue with a molecule in a convenient array (resi)
01040 nummol=0;
01041 resi=(int*)calloc(P[0].NRES,sizeof(int));
01042 for(pa=0;pa<P[0].NRES;pa++){ resi[pa]=-1; }
01043 for(pa=0;pa<P[0].NATOM;pa++){ 
01044         if(MOLBNDI[pa].m>nummol){ nummol = MOLBNDI[pa].m; }  // find numbers of molecules
01045         if(resi[MOLBNDI[pa].r]==-1) resi[MOLBNDI[pa].r]=MOLBNDI[pa].m;
01046         else if(resi[MOLBNDI[pa].r]!=MOLBNDI[pa].m){
01047                 if(resi[MOLBNDI[pa].r]!=-1) mywhine("resi[MOLBNDI[pa].r]!=MOLBNDI[pa].m in parse_amber_prmtop");} 
01048         }
01049 for(pa=0;pa<P[0].NATOM;pa++){ 
01050         if(resi[MOLBNDI[pa].r]==-1) { // this one isn't assigned a molecule yet
01051                 nummol++;
01052                 resi[MOLBNDI[pa].r]=MOLBNDI[pa].m=nummol; // Assign a new molecule number
01053                 MOLBNDI[pa].r=0; // since there are no bonds, this is a single atom, so only one residue
01054                 }
01055         }
01056 nummol++; // because the count starts with zero, but the total number doesn't
01057 A.nm=nummol; // make space for the molecules
01058 A.m=(molecule**)calloc(A.nm,sizeof(molecule*));
01059 for(pa=0;pa<A.nm;pa++){ 
01060         A.m[pa]=(molecule*)calloc(1,sizeof(molecule)); 
01061         A.m[pa][0].na=0;
01062         A.m[pa][0].nr=0;
01063         A.m[pa][0].a=(atom**)calloc(1,sizeof(atom*));
01064         A.m[pa][0].r=(residue*)calloc(1,sizeof(residue));
01065         }
01066 // place residues into molecule structures -- and do a little housekeeping
01067 for(pa=0;pa<P[0].NRES;pa++){
01068         A.r[pa][0].n=pa+1; // the file-print residue "number"
01069         A.m[resi[pa]][0].nr++;
01070         A.m[resi[pa]][0].r=(residue*)realloc(A.m[resi[pa]][0].r,A.m[resi[pa]][0].nr*sizeof(residue));
01071         A.m[resi[pa]][0].r[A.m[resi[pa]][0].nr-1]=A.r[pa][0]; // copy over residue 
01072         A.r[pa]=&A.m[resi[pa]][0].r[A.m[resi[pa]][0].nr-1];// reassign pointer
01073         for(pb=0;pb<A.r[pa][0].na;pb++){
01074                 MOLBNDI[A.r[pa][0].a[pb].n-1].r=A.m[resi[pa]][0].nr-1;
01075                 }
01076         }
01077 
01078 
01079 // Use the following to print info for all molecules to screen (for debugging)
01080 //for(pa=0;pa<A.nm;pa++){
01081 //printf("============== there are %d molecules =================\n",A.nm);
01082 //dprint_molecule(A.m[pa],1000);}
01083 
01084 // if the NSPM & NSP information is present, check results for consistency
01085 // NSPM = number of molecules
01086 // *NSP = number of atoms in each molecule
01087 // IPTRES = last residue that is solute
01088 // NSPSOL = first solvent residue
01089 //
01090 
01091 
01092 // Use new molecule information to reset residue numbers and molecule affiliations
01093 //      set the MOLI indices, too...
01094 for(pa=0;pa<A.nm;pa++){
01095         // set ensemble indices
01096         A.m[pa][0].nensi=1;
01097         A.m[pa][0].ensi=(ensindex*)calloc(1,sizeof(ensindex));
01098         A.m[pa][0].ensi[0].E=A.m[pa][0].ensi[0].r=A.m[pa][0].ensi[0].a=-1;
01099         A.m[pa][0].ensi[0].A=0;
01100         A.m[pa][0].ensi[0].m=pa;
01101         for(pb=0;pb<A.m[pa][0].nr;pb++){
01102                 // set ensemble indices
01103                 A.m[pa][0].r[pb].nensi=1;
01104                 A.m[pa][0].r[pb].ensi=(ensindex*)calloc(1,sizeof(ensindex));
01105                 A.m[pa][0].r[pb].ensi[0].E=A.m[pa][0].r[pb].ensi[0].a=-1;
01106                 A.m[pa][0].r[pb].ensi[0].A=0;
01107                 A.m[pa][0].r[pb].ensi[0].m=pa;
01108                 A.m[pa][0].r[pb].ensi[0].r=pb;
01109                 // set molecule indices
01110                 A.m[pa][0].r[pb].moli.m=pa;
01111                 A.m[pa][0].r[pb].moli.r=pb;
01112                 A.m[pa][0].r[pb].moli.a=-1;
01113                 for(pc=0;pc<A.m[pa][0].r[pb].na;pc++){ 
01114                         // set ensemble indices
01115                         A.m[pa][0].r[pb].a[pc].nensi=1;
01116                         A.m[pa][0].r[pb].a[pc].ensi=(ensindex*)calloc(1,sizeof(ensindex));
01117                         A.m[pa][0].r[pb].a[pc].ensi[0].E=-1;
01118                         A.m[pa][0].r[pb].a[pc].ensi[0].A=0;
01119                         A.m[pa][0].r[pb].a[pc].ensi[0].m=pa;
01120                         A.m[pa][0].r[pb].a[pc].ensi[0].r=pb;
01121                         A.m[pa][0].r[pb].a[pc].ensi[0].a=pc;
01122                         // set molecule indices
01123                         A.m[pa][0].r[pb].a[pc].moli.m=pa;
01124                         A.m[pa][0].r[pb].a[pc].moli.r=pb;
01125                         A.m[pa][0].r[pb].a[pc].moli.a=pc;
01126                         }
01127                 } 
01128         }
01129 
01130 // printf("============== there are %d molecules =================\n",A.nm);
01131 
01132 // Set the bond information at the atom level
01133 for(pa=0;pa<A.nm;pa++){
01134 A.m[pa][0].N=strdup("unknown");
01135 A.m[pa][0].D=strdup("Molecule determined by read of Amber prmtop file");
01136 //printf("\tMolecule %d contains %d residues\n",pa,A.m[pa][0].nr);
01137 for(pb=0;pb<A.m[pa][0].nr;pb++){
01138 //printf("\t\tResidue %d contains %d atoms\n",pb,A.m[pa][0].r[pb].na);
01139 for(pc=0;pc<A.m[pa][0].r[pb].na;pc++){
01140         A.m[pa][0].r[pb].a[pc].mb=(molbond*)calloc(1,sizeof(molbond)); 
01141 //printf("Atom %s (# %d) belongs to residue # %d and molecule # %d\n",A.m[pa][0].r[pb].a[pc].N,pc,pb,pa);
01142         }
01143         }
01144         }
01145 
01146 for(pa=0;pa<A.nb;pa++){
01147         // set global bonds
01148         A.b[pa].i=MBTMP[pa].i;
01149         A.b[pa].D=strdup(MBTMP[pa].D);
01150         A.b[pa].s.m=sm=MOLBNDI[MBTMP[pa].s.i].m;
01151         A.b[pa].s.r=sr=MOLBNDI[MBTMP[pa].s.i].r;
01152         A.b[pa].s.a=sa=MOLBNDI[MBTMP[pa].s.i].a;
01153         A.b[pa].t.m=tm=MOLBNDI[MBTMP[pa].t.i].m;
01154         A.b[pa].t.r=tr=MOLBNDI[MBTMP[pa].t.i].r;
01155         A.b[pa].t.a=ta=MOLBNDI[MBTMP[pa].t.i].a;
01156 
01157 /* If you're trying to fix the code, the following might be instructive. */
01158 /*
01159 printf("bond number, pa=%d \n",pa);
01160 printf("  MBTMP[pa].s.i is %d \n",MBTMP[pa].s.i);
01161 printf("    MBTMP[pa].t.i is %d\n",MBTMP[pa].t.i);
01162 printf("\tMOLBNDI[(s)].m =%d \n",MOLBNDI[MBTMP[pa].s.i].m);
01163 printf("\t\t .r=%d \n",MOLBNDI[MBTMP[pa].s.i].r);
01164 printf("\t\t    .a=%d\n",MOLBNDI[MBTMP[pa].s.i].a);
01165 printf("\t\tMOLBNDI[(t)].m =%d \n",MOLBNDI[MBTMP[pa].t.i].m);
01166 printf("\t\t\t  .r=%d \n",MOLBNDI[MBTMP[pa].t.i].r);
01167 printf("\t\t\t    .a=%d\n",MOLBNDI[MBTMP[pa].t.i].a);
01168 */
01169         // -- set local bonds to molbond structure (later to local bond structure)
01170         A.m[sm][0].r[sr].a[sa].nmb++;
01171         A.m[tm][0].r[tr].a[ta].nmb++;
01172         A.m[sm][0].r[sr].a[sa].mb=(molbond*)realloc(A.m[sm][0].r[sr].a[sa].mb,A.m[sm][0].r[sr].a[sa].nmb*sizeof(molbond));
01173         A.m[tm][0].r[tr].a[ta].mb=(molbond*)realloc(A.m[tm][0].r[tr].a[ta].mb,A.m[tm][0].r[tr].a[ta].nmb*sizeof(molbond));
01174         // set both atoms as being bonded to the other
01175         A.m[sm][0].r[sr].a[sa].mb[A.m[sm][0].r[sr].a[sa].nmb-1]=A.b[pa]; // if already "source", all is ok
01176         // if the atom is a "target", we have to turn things around a bit
01177         A.m[tm][0].r[tr].a[ta].mb[A.m[tm][0].r[tr].a[ta].nmb-1].s.a = A.b[pa].t.a;
01178         A.m[tm][0].r[tr].a[ta].mb[A.m[tm][0].r[tr].a[ta].nmb-1].s.r = A.b[pa].t.r;
01179         A.m[tm][0].r[tr].a[ta].mb[A.m[tm][0].r[tr].a[ta].nmb-1].s.m = A.b[pa].t.m;
01180         A.m[tm][0].r[tr].a[ta].mb[A.m[tm][0].r[tr].a[ta].nmb-1].t.a = A.b[pa].s.a ;
01181         A.m[tm][0].r[tr].a[ta].mb[A.m[tm][0].r[tr].a[ta].nmb-1].t.r = A.b[pa].s.r ;
01182         A.m[tm][0].r[tr].a[ta].mb[A.m[tm][0].r[tr].a[ta].nmb-1].t.m = A.b[pa].s.m ;
01183         }
01184 
01185 /* uncomment this to check the function's work
01186 for(pa=0;pa<A.nm;pa++){
01187 printf("MOLECULE #%d\n",pa);
01188 for(pb=0;pb<A.m[pa][0].nr;pb++){
01189 printf("\tRESIDUE #%d (name %s)\n",pb,A.m[pa][0].r[pb].N); 
01190 for(pc=0;pc<A.m[pa][0].r[pb].na;pc++){
01191 printf("\t\tATOM #%d (name %s) has %d bonds\n",pc,A.m[pa][0].r[pb].a[pc].N,A.m[pa][0].r[pb].a[pc].nmb); 
01192 for(pd=0;pd<A.m[pa][0].r[pb].a[pc].nmb;pd++){
01193 tm=A.m[pa][0].r[pb].a[pc].mb[pd].t.m;
01194 tr=A.m[pa][0].r[pb].a[pc].mb[pd].t.r;
01195 ta=A.m[pa][0].r[pb].a[pc].mb[pd].t.a;
01196 printf("\t\t\tTo %s (atom number %d)\n",A.m[tm][0].r[tr].a[ta].N,A.m[tm][0].r[tr].a[ta].n);
01197 }
01198 }
01199 }
01200 }
01201 */
01202 
01203 
01204 // One day when we know how the connection tree will be structured:
01205 // -- set local torsions and angles
01206 // -- set connection tree after all that...
01207 //      -- check this tree against the amber tree info for sanity
01208 
01209 // free temporary spaces
01210 if(MOLI!=NULL){free(MOLI);}
01211 if(ICO!=NULL){free(ICO);}
01212 if(MB!=NULL){free(MB);}
01213 if(MANG!=NULL){free(MANG);}
01214 if(MTOR!=NULL){free(MTOR);}
01215 if(MASS!=NULL){free(MASS);}
01216 if(NSP!=NULL){free(NSP);}
01217 if(R!=NULL){free(R);}
01218 if(SC!=NULL){free(SC);}
01219 if(MOLBNDI!=NULL){free(MOLBNDI);}
01220 if(MBTMP!=NULL){free(MBTMP);}
01221 if(resi!=NULL){free(resi);}
01222 for(pa=0;pa<A.na;pa++){
01223         if(ATNAME[pa]!=NULL){free(ATNAME[pa]);}
01224         if(TREECLASS[pa]!=NULL){free(TREECLASS[pa]);}
01225 }
01226 if(ATNAME!=NULL){free(ATNAME);}
01227 if(TREECLASS!=NULL){free(TREECLASS);}
01228 
01229 return A;
01230 }
01231 
01232 
 All Classes Files Functions Variables Typedefs Defines