GLYLIB
0.3.0b
|
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