2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
48 #include "gmx_fatal.h"
53 #include "fflibutil.h"
55 gpp_atomtype_t read_atype(const char *ffdir,t_symtab *tab)
60 char buf[STRLEN],name[STRLEN];
67 nfile = fflib_search_file_end(ffdir,".atp",TRUE,&file);
72 for(f=0; f<nfile; f++)
74 in = fflib_open(file[f]);
77 /* Skip blank or comment-only lines */
80 fgets2(buf,STRLEN,in);
87 while (!feof(in) && NULL!=buf && strlen(buf)==0);
89 if ((buf != NULL) && (sscanf(buf,"%s%lf",name,&m) == 2))
92 add_atomtype(at,tab,a,name,nb, 0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 );
93 fprintf(stderr,"\rAtomtype %d",nratt+1);
105 static void print_resatoms(FILE *out,gpp_atomtype_t atype,t_restp *rtp)
110 /* fprintf(out,"%5s\n",rtp->resname);
111 fprintf(out,"%5d\n",rtp->natom); */
112 fprintf(out,"[ %s ]\n",rtp->resname);
113 fprintf(out," [ atoms ]\n");
115 for(j=0; (j<rtp->natom); j++) {
116 tp = rtp->atom[j].type;
117 tpnm = get_atomtype_name(tp,atype);
119 gmx_fatal(FARGS,"Incorrect atomtype (%d)",tp);
120 fprintf(out,"%6s %6s %8.3f %6d\n",
121 *(rtp->atomname[j]),tpnm,rtp->atom[j].q,rtp->cgnr[j]);
125 static gmx_bool read_atoms(FILE *in,char *line,
126 t_restp *r0,t_symtab *tab,gpp_atomtype_t atype)
128 int i,j,cg,maxentries;
129 char buf[256],buf1[256];
138 while (get_a_line(in,line,STRLEN) && (strchr(line,'[')==NULL)) {
139 if (sscanf(line,"%s%s%lf%d",buf,buf1,&q,&cg) != 4)
143 srenew(r0->atom, maxentries);
144 srenew(r0->atomname, maxentries);
145 srenew(r0->cgnr, maxentries);
147 r0->atomname[i] = put_symtab(tab,buf);
150 j = get_atomtype_type(buf1,atype);
152 gmx_fatal(FARGS,"Atom type %s (residue %s) not found in atomtype "
153 "database",buf1,r0->resname);
155 r0->atom[i].m=get_atomtype_massA(j,atype);
160 srenew(r0->atomname,i);
166 gmx_bool read_bondeds(int bt, FILE *in, char *line, t_restp *rtp)
171 maxrb = rtp->rb[bt].nb;
172 while (get_a_line(in,line,STRLEN) && (strchr(line,'[')==NULL)) {
173 if ( rtp->rb[bt].nb >= maxrb ) {
175 srenew(rtp->rb[bt].b,maxrb);
178 for(j=0; j < btsNiatoms[bt]; j++) {
179 if ( sscanf(line+n,"%s%n",str,&ni)==1 )
180 rtp->rb[bt].b[rtp->rb[bt].nb].a[j]=strdup(str);
185 for( ; j < MAXATOMLIST; j++)
186 rtp->rb[bt].b[rtp->rb[bt].nb].a[j]=NULL;
187 while (isspace(line[n]))
190 rtp->rb[bt].b[rtp->rb[bt].nb].s=strdup(line+n);
193 /* give back unused memory */
194 srenew(rtp->rb[bt].b,rtp->rb[bt].nb);
199 static void print_resbondeds(FILE *out, int bt, t_restp *rtp)
203 if (rtp->rb[bt].nb) {
204 fprintf(out," [ %s ]\n",btsNames[bt]);
206 for(i=0; i < rtp->rb[bt].nb; i++) {
207 for(j=0; j<btsNiatoms[bt]; j++)
208 fprintf(out,"%6s ",rtp->rb[bt].b[i].a[j]);
209 if (rtp->rb[bt].b[i].s[0])
210 fprintf(out," %s",rtp->rb[bt].b[i].s);
216 static void check_rtp(int nrtp,t_restp rtp[],char *libfn)
220 /* check for double entries, assuming list is already sorted */
221 for(i=1; (i<nrtp); i++) {
222 if (gmx_strcasecmp(rtp[i-1].resname,rtp[i].resname) == 0)
223 fprintf(stderr,"WARNING double entry %s in file %s\n",
224 rtp[i].resname,libfn);
228 static int comprtp(const void *a,const void *b)
235 return gmx_strcasecmp(ra->resname,rb->resname);
238 int get_bt(char* header)
242 for(i=0; i<ebtsNR; i++)
243 if ( gmx_strcasecmp(btsNames[i],header)==0 )
248 void clear_t_restp(t_restp *rrtp)
250 memset((void *)rrtp, 0, sizeof(t_restp));
253 /* print all the ebtsNR type numbers */
254 void print_resall_header(FILE *out, t_restp rtp[])
256 fprintf(out,"[ bondedtypes ]\n");
257 fprintf(out,"; bonds angles dihedrals impropers all_dihedrals nr_exclusions HH14 remove_dih\n");
258 fprintf(out," %5d %6d %9d %9d %14d %14d %14d %14d\n\n",
263 rtp[0].bKeepAllGeneratedDihedrals,
265 rtp[0].bGenerateHH14Interactions,
266 rtp[0].bRemoveDihedralIfWithImproper);
269 void print_resall(FILE *out, int nrtp, t_restp rtp[],
270 gpp_atomtype_t atype)
278 print_resall_header(out, rtp);
280 for(i=0; i<nrtp; i++) {
281 if (rtp[i].natom > 0) {
282 print_resatoms(out,atype,&rtp[i]);
283 for(bt=0; bt<ebtsNR; bt++)
284 print_resbondeds(out,bt,&rtp[i]);
289 void read_resall(char *rrdb, int *nrtpptr, t_restp **rtp,
290 gpp_atomtype_t atype, t_symtab *tab,
291 gmx_bool bAllowOverrideRTP)
294 char filebase[STRLEN],*ptr,line[STRLEN],header[STRLEN];
295 int i,nrtp,maxrtp,bt,nparam;
297 t_restp *rrtp, *header_settings;
298 gmx_bool bNextResidue,bError;
301 fflib_filename_base(rrdb,filebase,STRLEN);
303 in = fflib_open(rrdb);
306 fprintf(debug,"%9s %5s", "Residue", "atoms");
307 for(i=0; i<ebtsNR; i++)
308 fprintf(debug," %10s",btsNames[i]);
311 snew(header_settings, 1);
313 /* these bonded parameters will overwritten be when *
314 * there is a [ bondedtypes ] entry in the .rtp file */
315 header_settings->rb[ebtsBONDS].type = 1; /* normal bonds */
316 header_settings->rb[ebtsANGLES].type = 1; /* normal angles */
317 header_settings->rb[ebtsPDIHS].type = 1; /* normal dihedrals */
318 header_settings->rb[ebtsIDIHS].type = 2; /* normal impropers */
319 header_settings->rb[ebtsEXCLS].type = 1; /* normal exclusions */
320 header_settings->rb[ebtsCMAP].type = 1; /* normal cmap torsions */
322 header_settings->bKeepAllGeneratedDihedrals = FALSE;
323 header_settings->nrexcl = 3;
324 header_settings->bGenerateHH14Interactions = TRUE;
325 header_settings->bRemoveDihedralIfWithImproper = TRUE;
327 /* Column 5 & 6 aren't really bonded types, but we include
328 * them here to avoid introducing a new section:
329 * Column 5 : This controls the generation of dihedrals from the bonding.
330 * All possible dihedrals are generated automatically. A value of
331 * 1 here means that all these are retained. A value of
332 * 0 here requires generated dihedrals be removed if
333 * * there are any dihedrals on the same central atoms
334 * specified in the residue topology, or
335 * * there are other identical generated dihedrals
336 * sharing the same central atoms, or
337 * * there are other generated dihedrals sharing the
338 * same central bond that have fewer hydrogen atoms
339 * Column 6: Number of bonded neighbors to exclude.
340 * Column 7: Generate 1,4 interactions between two hydrogen atoms
341 * Column 8: Remove proper dihedrals if centered on the same bond
342 * as an improper dihedral
344 get_a_line(in,line,STRLEN);
345 if (!get_header(line,header))
346 gmx_fatal(FARGS,"in .rtp file at line:\n%s\n",line);
347 if (gmx_strncasecmp("bondedtypes",header,5)==0) {
348 get_a_line(in,line,STRLEN);
349 if ((nparam=sscanf(line,"%d %d %d %d %d %d %d %d",
350 &header_settings->rb[ebtsBONDS].type,&header_settings->rb[ebtsANGLES].type,
351 &header_settings->rb[ebtsPDIHS].type,&header_settings->rb[ebtsIDIHS].type,
352 &dum1,&header_settings->nrexcl,&dum2,&dum3)) < 4 )
354 gmx_fatal(FARGS,"need 4 to 8 parameters in the header of .rtp file %s at line:\n%s\n", rrdb, line);
356 header_settings->bKeepAllGeneratedDihedrals = (dum1 != 0);
357 header_settings->bGenerateHH14Interactions = (dum2 != 0);
358 header_settings->bRemoveDihedralIfWithImproper = (dum3 != 0);
359 get_a_line(in,line,STRLEN);
361 fprintf(stderr,"Using default: not generating all possible dihedrals\n");
362 header_settings->bKeepAllGeneratedDihedrals = FALSE;
365 fprintf(stderr,"Using default: excluding 3 bonded neighbors\n");
366 header_settings->nrexcl = 3;
369 fprintf(stderr,"Using default: generating 1,4 H--H interactions\n");
370 header_settings->bGenerateHH14Interactions = TRUE;
373 fprintf(stderr,"Using default: removing proper dihedrals found on the same bond as a proper dihedral\n");
374 header_settings->bRemoveDihedralIfWithImproper = TRUE;
378 "Reading .rtp file without '[ bondedtypes ]' directive,\n"
379 "Will proceed as if the entry was:\n");
380 print_resall_header(stderr, header_settings);
382 /* We don't know the current size of rrtp, but simply realloc immediately */
387 if (nrtp >= maxrtp) {
392 /* Initialise rtp entry structure */
393 rrtp[nrtp] = *header_settings;
394 if (!get_header(line,header))
395 gmx_fatal(FARGS,"in .rtp file at line:\n%s\n",line);
396 rrtp[nrtp].resname = strdup(header);
397 rrtp[nrtp].filebase = strdup(filebase);
399 get_a_line(in,line,STRLEN);
403 if (!get_header(line,header)) {
408 /* header is an bonded directive */
409 bError = !read_bondeds(bt,in,line,&rrtp[nrtp]);
410 } else if (gmx_strncasecmp("atoms",header,5) == 0) {
411 /* header is the atoms directive */
412 bError = !read_atoms(in,line,&(rrtp[nrtp]),tab,atype);
414 /* else header must be a residue name */
419 gmx_fatal(FARGS,"in .rtp file in residue %s at line:\n%s\n",
420 rrtp[nrtp].resname,line);
421 } while (!feof(in) && !bNextResidue);
423 if (rrtp[nrtp].natom == 0)
424 gmx_fatal(FARGS,"No atoms found in .rtp file in residue %s\n",
427 fprintf(debug,"%3d %5s %5d",
428 nrtp+1,rrtp[nrtp].resname,rrtp[nrtp].natom);
429 for(i=0; i<ebtsNR; i++)
430 fprintf(debug," %10d",rrtp[nrtp].rb[i].nb);
435 for(i=0; i<nrtp; i++) {
436 if (gmx_strcasecmp(rrtp[i].resname,rrtp[nrtp].resname) == 0) {
441 if (firstrtp == -1) {
443 fprintf(stderr,"\rResidue %d",nrtp);
445 if (firstrtp >= *nrtpptr)
447 gmx_fatal(FARGS,"Found a second entry for '%s' in '%s'",
448 rrtp[nrtp].resname,rrdb);
450 if (bAllowOverrideRTP)
452 fprintf(stderr,"\n");
453 fprintf(stderr,"Found another rtp entry for '%s' in '%s', ignoring this entry and keeping the one from '%s.rtp'\n",
454 rrtp[nrtp].resname,rrdb,rrtp[firstrtp].filebase);
455 /* We should free all the data for this entry.
456 * The current code gives a lot of dangling pointers.
458 clear_t_restp(&rrtp[nrtp]);
462 gmx_fatal(FARGS,"Found rtp entries for '%s' in both '%s' and '%s'. If you want the first definition to override the second one, set the -rtpo option of pdb2gmx.",rrtp[nrtp].resname,rrtp[firstrtp].filebase,rrdb);
467 /* give back unused memory */
470 fprintf(stderr,"\nSorting it all out...\n");
471 qsort(rrtp,nrtp,(size_t)sizeof(rrtp[0]),comprtp);
473 check_rtp(nrtp,rrtp,rrdb);
479 /************************************************************
483 ***********************************************************/
484 static gmx_bool is_sign(char c)
486 return (c == '+' || c == '-');
489 /* Compares if the strins match except for a sign at the end
490 * of (only) one of the two.
492 static int neq_str_sign(const char *a1,const char *a2)
496 l1 = (int)strlen(a1);
497 l2 = (int)strlen(a2);
501 ((l1 == l2+1 && is_sign(a1[l1-1])) ||
502 (l2 == l1+1 && is_sign(a2[l2-1]))) &&
503 gmx_strncasecmp(a1,a2,lm) == 0)
513 char *search_rtp(const char *key,int nrtp,t_restp rtp[])
515 int i,n,nbest,best,besti;
516 char bestbuf[STRLEN];
520 /* We want to match at least one character */
522 for(i=0; (i<nrtp); i++)
524 if (gmx_strcasecmp(key,rtp[i].resname) == 0)
532 /* Allow a mismatch of at most a sign character (with warning) */
533 n = neq_str_sign(key,rtp[i].resname);
535 n+1 >= (int)strlen(key) &&
536 n+1 >= (int)strlen(rtp[i].resname))
542 strcpy(bestbuf,rtp[besti].resname);
546 strcat(bestbuf," or ");
547 strcat(bestbuf,rtp[i].resname);
562 gmx_fatal(FARGS,"Residue '%s' not found in residue topology database, looks a bit like %s",key,bestbuf);
564 else if (besti == -1)
566 gmx_fatal(FARGS,"Residue '%s' not found in residue topology database",key);
568 if (gmx_strcasecmp(rtp[besti].resname,key) != 0)
571 "\nWARNING: '%s' not found in residue topology database, "
572 "trying to use '%s'\n\n", key, rtp[besti].resname);
575 return rtp[besti].resname;
578 t_restp *get_restp(const char *rtpname,int nrtp,t_restp rtp[])
583 while (i < nrtp && gmx_strcasecmp(rtpname,rtp[i].resname) != 0)
589 /* This should never happen, since search_rtp should have been called
590 * before calling get_restp.
592 gmx_fatal(FARGS,"Residue type '%s' not found in residue topology database",rtpname);