Added documentation about proper use of pdb2gmx -ter.
[gromacs/rigid-bodies.git] / src / kernel / pdb2gmx.c
blob0f0ab3657674f58708c40ff965e664fb3b9cd86a
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include <time.h>
41 #include <ctype.h>
42 #include "sysstuff.h"
43 #include "typedefs.h"
44 #include "gmxfio.h"
45 #include "smalloc.h"
46 #include "copyrite.h"
47 #include "string2.h"
48 #include "confio.h"
49 #include "symtab.h"
50 #include "vec.h"
51 #include "statutil.h"
52 #include "futil.h"
53 #include "gmx_fatal.h"
54 #include "pdbio.h"
55 #include "toputil.h"
56 #include "h_db.h"
57 #include "physics.h"
58 #include "pgutil.h"
59 #include "calch.h"
60 #include "resall.h"
61 #include "pdb2top.h"
62 #include "ter_db.h"
63 #include "strdb.h"
64 #include "gbutil.h"
65 #include "genhydro.h"
66 #include "readinp.h"
67 #include "atomprop.h"
68 #include "xlate.h"
69 #include "specbond.h"
70 #include "index.h"
71 #include "hizzie.h"
72 #include "fflibutil.h"
75 typedef struct {
76 char gmx[6];
77 char main[6];
78 char nter[6];
79 char cter[6];
80 char bter[6];
81 } rtprename_t;
84 static const char *res2bb_notermini(const char *name,
85 int nrr,const rtprename_t *rr)
87 /* NOTE: This function returns the main building block name,
88 * it does not take terminal renaming into account.
90 int i;
92 i = 0;
93 while (i < nrr && gmx_strcasecmp(name,rr[i].gmx) != 0) {
94 i++;
97 return (i < nrr ? rr[i].main : name);
100 static const char *select_res(int nr,int resnr,
101 const char *name[],const char *expl[],
102 const char *title,
103 int nrr,const rtprename_t *rr)
105 int sel=0;
107 printf("Which %s type do you want for residue %d\n",title,resnr+1);
108 for(sel=0; (sel < nr); sel++) {
109 printf("%d. %s (%s)\n",
110 sel,expl[sel],res2bb_notermini(name[sel],nrr,rr));
112 printf("\nType a number:"); fflush(stdout);
114 if (scanf("%d",&sel) != 1)
115 gmx_fatal(FARGS,"Answer me for res %s %d!",title,resnr+1);
117 return name[sel];
120 static const char *get_asptp(int resnr,int nrr,const rtprename_t *rr)
122 enum { easp, easpH, easpNR };
123 const char *lh[easpNR] = { "ASP", "ASPH" };
124 const char *expl[easpNR] = {
125 "Not protonated (charge -1)",
126 "Protonated (charge 0)"
129 return select_res(easpNR,resnr,lh,expl,"ASPARTIC ACID",nrr,rr);
132 static const char *get_glutp(int resnr,int nrr,const rtprename_t *rr)
134 enum { eglu, egluH, egluNR };
135 const char *lh[egluNR] = { "GLU", "GLUH" };
136 const char *expl[egluNR] = {
137 "Not protonated (charge -1)",
138 "Protonated (charge 0)"
141 return select_res(egluNR,resnr,lh,expl,"GLUTAMIC ACID",nrr,rr);
144 static const char *get_glntp(int resnr,int nrr,const rtprename_t *rr)
146 enum { egln, eglnH, eglnNR };
147 const char *lh[eglnNR] = { "GLN", "QLN" };
148 const char *expl[eglnNR] = {
149 "Not protonated (charge 0)",
150 "Protonated (charge +1)"
153 return select_res(eglnNR,resnr,lh,expl,"GLUTAMINE",nrr,rr);
156 static const char *get_lystp(int resnr,int nrr,const rtprename_t *rr)
158 enum { elys, elysH, elysNR };
159 const char *lh[elysNR] = { "LYSN", "LYS" };
160 const char *expl[elysNR] = {
161 "Not protonated (charge 0)",
162 "Protonated (charge +1)"
165 return select_res(elysNR,resnr,lh,expl,"LYSINE",nrr,rr);
168 static const char *get_argtp(int resnr,int nrr,const rtprename_t *rr)
170 enum { earg, eargH, eargNR };
171 const char *lh[eargNR] = { "ARGN", "ARG" };
172 const char *expl[eargNR] = {
173 "Not protonated (charge 0)",
174 "Protonated (charge +1)"
177 return select_res(eargNR,resnr,lh,expl,"ARGININE",nrr,rr);
180 static const char *get_cystp(int resnr,int nrr,const rtprename_t *rr)
182 enum { ecys, ecysH, ecysNR };
183 const char *lh[ecysNR] = { "CYS2", "CYS" };
184 const char *expl[ecysNR] = {
185 "Cysteine in disulfide bridge",
186 "Protonated"
189 return select_res(ecysNR,resnr,lh,expl,"CYSTEINE",nrr,rr);
193 static const char *get_histp(int resnr,int nrr,const rtprename_t *rr)
195 const char *expl[ehisNR] = {
196 "H on ND1 only",
197 "H on NE2 only",
198 "H on ND1 and NE2",
199 "Coupled to Heme"
202 return select_res(ehisNR,resnr,hh,expl,"HISTIDINE",nrr,rr);
205 static void read_rtprename(const char *fname,FILE *fp,
206 int *nrtprename,rtprename_t **rtprename)
208 char line[STRLEN],buf[STRLEN];
209 int n;
210 rtprename_t *rr;
211 int ncol,nc;
213 n = *nrtprename;
214 rr = *rtprename;
216 ncol = 0;
217 while(get_a_line(fp,line,STRLEN)) {
218 srenew(rr,n+1);
219 nc = sscanf(line,"%s %s %s %s %s %s",
220 rr[n].gmx,rr[n].main,rr[n].nter,rr[n].cter,rr[n].bter,buf);
221 if (ncol == 0) {
222 if (nc != 2 && nc != 5) {
223 gmx_fatal(FARGS,"Residue renaming database '%s' has %d columns instead of %d, %d or %d",fname,ncol,2,5);
225 ncol = nc;
226 } else if (nc != ncol) {
227 gmx_fatal(FARGS,"A line in residue renaming database '%s' has %d columns, while previous lines have %d columns",fname,nc,ncol);
230 if (nc == 2) {
231 /* This file does not have special termini names, copy them from main */
232 strcpy(rr[n].nter,rr[n].main);
233 strcpy(rr[n].cter,rr[n].main);
234 strcpy(rr[n].bter,rr[n].main);
237 n++;
240 *nrtprename = n;
241 *rtprename = rr;
244 static char *search_resrename(int nrr,rtprename_t *rr,
245 const char *name,
246 gmx_bool bStart,gmx_bool bEnd,
247 gmx_bool bCompareFFRTPname)
249 char *nn;
250 int i;
252 nn = NULL;
254 i = 0;
255 while (i<nrr && ((!bCompareFFRTPname && strcmp(name,rr[i].gmx) != 0) ||
256 ( bCompareFFRTPname && strcmp(name,rr[i].main) != 0)))
258 i++;
261 /* If found in the database, rename this residue's rtp building block,
262 * otherwise keep the old name.
264 if (i < nrr)
266 if (bStart && bEnd)
268 nn = rr[i].bter;
270 else if (bStart)
272 nn = rr[i].nter;
274 else if (bEnd)
276 nn = rr[i].cter;
278 else
280 nn = rr[i].main;
282 if (nn[0] == '-')
284 gmx_fatal(FARGS,"In the chosen force field there is no residue type for '%s'%s",name,bStart ? " as a starting terminus" : (bEnd ? " as an ending terminus" : ""));
288 return nn;
292 static void rename_resrtp(t_atoms *pdba,int nterpairs,int *r_start,int *r_end,
293 int nrr,rtprename_t *rr,t_symtab *symtab,
294 gmx_bool bVerbose)
296 int r,i,j;
297 gmx_bool bStart,bEnd;
298 char *nn;
299 gmx_bool bFFRTPTERRNM;
301 bFFRTPTERRNM = (getenv("GMX_NO_FFRTP_TER_RENAME") == NULL);
303 for(r=0; r<pdba->nres; r++)
305 bStart = FALSE;
306 bEnd = FALSE;
307 for(j=0; j<nterpairs; j++)
309 if (r == r_start[j])
311 bStart = TRUE;
314 for(j=0; j<nterpairs; j++)
316 if (r == r_end[j])
318 bEnd = TRUE;
322 nn = search_resrename(nrr,rr,*pdba->resinfo[r].rtp,bStart,bEnd,FALSE);
324 if (bFFRTPTERRNM && nn == NULL && (bStart || bEnd))
326 /* This is a terminal residue, but the residue name,
327 * currently stored in .rtp, is not a standard residue name,
328 * but probably a force field specific rtp name.
329 * Check if we need to rename it because it is terminal.
331 nn = search_resrename(nrr,rr,
332 *pdba->resinfo[r].rtp,bStart,bEnd,TRUE);
335 if (nn != NULL && strcmp(*pdba->resinfo[r].rtp,nn) != 0)
337 if (bVerbose)
339 printf("Changing rtp entry of residue %d %s to '%s'\n",
340 pdba->resinfo[r].nr,*pdba->resinfo[r].name,nn);
342 pdba->resinfo[r].rtp = put_symtab(symtab,nn);
347 static void pdbres_to_gmxrtp(t_atoms *pdba)
349 int i;
351 for(i=0; (i<pdba->nres); i++)
353 if (pdba->resinfo[i].rtp == NULL)
355 pdba->resinfo[i].rtp = pdba->resinfo[i].name;
360 static void rename_pdbres(t_atoms *pdba,const char *oldnm,const char *newnm,
361 gmx_bool bFullCompare,t_symtab *symtab)
363 char *resnm;
364 int i;
366 for(i=0; (i<pdba->nres); i++)
368 resnm = *pdba->resinfo[i].name;
369 if ((bFullCompare && (gmx_strcasecmp(resnm,oldnm) == 0)) ||
370 (!bFullCompare && strstr(resnm,oldnm) != NULL))
372 /* Rename the residue name (not the rtp name) */
373 pdba->resinfo[i].name = put_symtab(symtab,newnm);
378 static void rename_bb(t_atoms *pdba,const char *oldnm,const char *newnm,
379 gmx_bool bFullCompare,t_symtab *symtab)
381 char *bbnm;
382 int i;
384 for(i=0; (i<pdba->nres); i++)
386 /* We have not set the rtp name yes, use the residue name */
387 bbnm = *pdba->resinfo[i].name;
388 if ((bFullCompare && (gmx_strcasecmp(bbnm,oldnm) == 0)) ||
389 (!bFullCompare && strstr(bbnm,oldnm) != NULL))
391 /* Change the rtp builing block name */
392 pdba->resinfo[i].rtp = put_symtab(symtab,newnm);
397 static void rename_bbint(t_atoms *pdba,const char *oldnm,
398 const char *gettp(int,int,const rtprename_t *),
399 gmx_bool bFullCompare,
400 t_symtab *symtab,
401 int nrr,const rtprename_t *rr)
403 int i;
404 const char *ptr;
405 char *bbnm;
407 for(i=0; i<pdba->nres; i++)
409 /* We have not set the rtp name yes, use the residue name */
410 bbnm = *pdba->resinfo[i].name;
411 if ((bFullCompare && (strcmp(bbnm,oldnm) == 0)) ||
412 (!bFullCompare && strstr(bbnm,oldnm) != NULL))
414 ptr = gettp(i,nrr,rr);
415 pdba->resinfo[i].rtp = put_symtab(symtab,ptr);
420 static void check_occupancy(t_atoms *atoms,const char *filename,gmx_bool bVerbose)
422 int i,ftp;
423 int nzero=0;
424 int nnotone=0;
426 ftp = fn2ftp(filename);
427 if (!atoms->pdbinfo || ((ftp != efPDB) && (ftp != efBRK) && (ftp != efENT)))
428 fprintf(stderr,"No occupancies in %s\n",filename);
429 else {
430 for(i=0; (i<atoms->nr); i++) {
431 if (atoms->pdbinfo[i].occup != 1) {
432 if (bVerbose)
433 fprintf(stderr,"Occupancy for atom %s%d-%s is %f rather than 1\n",
434 *atoms->resinfo[atoms->atom[i].resind].name,
435 atoms->resinfo[ atoms->atom[i].resind].nr,
436 *atoms->atomname[i],
437 atoms->pdbinfo[i].occup);
438 if (atoms->pdbinfo[i].occup == 0)
439 nzero++;
440 else
441 nnotone++;
444 if (nzero == atoms->nr) {
445 fprintf(stderr,"All occupancy fields zero. This is probably not an X-Ray structure\n");
446 } else if ((nzero > 0) || (nnotone > 0)) {
447 fprintf(stderr,
448 "\n"
449 "WARNING: there were %d atoms with zero occupancy and %d atoms with\n"
450 " occupancy unequal to one (out of %d atoms). Check your pdb file.\n"
451 "\n",
452 nzero,nnotone,atoms->nr);
453 } else {
454 fprintf(stderr,"All occupancies are one\n");
459 void write_posres(char *fn,t_atoms *pdba,real fc)
461 FILE *fp;
462 int i;
464 fp=gmx_fio_fopen(fn,"w");
465 fprintf(fp,
466 "; In this topology include file, you will find position restraint\n"
467 "; entries for all the heavy atoms in your original pdb file.\n"
468 "; This means that all the protons which were added by pdb2gmx are\n"
469 "; not restrained.\n"
470 "\n"
471 "[ position_restraints ]\n"
472 "; %4s%6s%8s%8s%8s\n","atom","type","fx","fy","fz"
474 for(i=0; (i<pdba->nr); i++) {
475 if (!is_hydrogen(*pdba->atomname[i]) && !is_dummymass(*pdba->atomname[i]))
476 fprintf(fp,"%6d%6d %g %g %g\n",i+1,1,fc,fc,fc);
478 gmx_fio_fclose(fp);
481 static int read_pdball(const char *inf, const char *outf,char *title,
482 t_atoms *atoms, rvec **x,
483 int *ePBC,matrix box, gmx_bool bRemoveH,
484 t_symtab *symtab,gmx_residuetype_t rt,const char *watres,
485 gmx_atomprop_t aps,gmx_bool bVerbose)
486 /* Read a pdb file. (containing proteins) */
488 int natom,new_natom,i;
490 /* READ IT */
491 printf("Reading %s...\n",inf);
492 get_stx_coordnum(inf,&natom);
493 init_t_atoms(atoms,natom,TRUE);
494 snew(*x,natom);
495 read_stx_conf(inf,title,atoms,*x,NULL,ePBC,box);
496 if (fn2ftp(inf) == efPDB)
497 get_pdb_atomnumber(atoms,aps);
498 if (bRemoveH) {
499 new_natom=0;
500 for(i=0; i<atoms->nr; i++)
501 if (!is_hydrogen(*atoms->atomname[i])) {
502 atoms->atom[new_natom]=atoms->atom[i];
503 atoms->atomname[new_natom]=atoms->atomname[i];
504 atoms->pdbinfo[new_natom]=atoms->pdbinfo[i];
505 copy_rvec((*x)[i],(*x)[new_natom]);
506 new_natom++;
508 atoms->nr=new_natom;
509 natom=new_natom;
512 printf("Read");
513 if (title && title[0])
514 printf(" '%s',",title);
515 printf(" %d atoms\n",natom);
517 /* Rename residues */
518 rename_pdbres(atoms,"HOH",watres,FALSE,symtab);
519 rename_pdbres(atoms,"SOL",watres,FALSE,symtab);
520 rename_pdbres(atoms,"WAT",watres,FALSE,symtab);
522 rename_atoms("xlateat.dat",NULL,
523 atoms,symtab,NULL,TRUE,rt,TRUE,bVerbose);
525 if (natom == 0)
526 return 0;
528 if (outf)
529 write_sto_conf(outf,title,atoms,*x,NULL,*ePBC,box);
531 return natom;
534 void process_chain(t_atoms *pdba, rvec *x,
535 gmx_bool bTrpU,gmx_bool bPheU,gmx_bool bTyrU,
536 gmx_bool bLysMan,gmx_bool bAspMan,gmx_bool bGluMan,
537 gmx_bool bHisMan,gmx_bool bArgMan,gmx_bool bGlnMan,
538 real angle,real distance,t_symtab *symtab,
539 int nrr,const rtprename_t *rr)
541 /* Rename aromatics, lys, asp and histidine */
542 if (bTyrU) rename_bb(pdba,"TYR","TYRU",FALSE,symtab);
543 if (bTrpU) rename_bb(pdba,"TRP","TRPU",FALSE,symtab);
544 if (bPheU) rename_bb(pdba,"PHE","PHEU",FALSE,symtab);
545 if (bLysMan)
546 rename_bbint(pdba,"LYS",get_lystp,FALSE,symtab,nrr,rr);
547 if (bArgMan)
548 rename_bbint(pdba,"ARG",get_argtp,FALSE,symtab,nrr,rr);
549 if (bGlnMan)
550 rename_bbint(pdba,"GLN",get_glntp,FALSE,symtab,nrr,rr);
551 if (bAspMan)
552 rename_bbint(pdba,"ASP",get_asptp,FALSE,symtab,nrr,rr);
553 else
554 rename_bb(pdba,"ASPH","ASP",FALSE,symtab);
555 if (bGluMan)
556 rename_bbint(pdba,"GLU",get_glutp,FALSE,symtab,nrr,rr);
557 else
558 rename_bb(pdba,"GLUH","GLU",FALSE,symtab);
560 if (!bHisMan)
561 set_histp(pdba,x,angle,distance);
562 else
563 rename_bbint(pdba,"HIS",get_histp,TRUE,symtab,nrr,rr);
565 /* Initialize the rtp builing block names with the residue names
566 * for the residues that have not been processed above.
568 pdbres_to_gmxrtp(pdba);
570 /* Now we have all rtp names set.
571 * The rtp names will conform to Gromacs naming,
572 * unless the input pdb file contained one or more force field specific
573 * rtp names as residue names.
577 /* struct for sorting the atoms from the pdb file */
578 typedef struct {
579 int resnr; /* residue number */
580 int j; /* database order index */
581 int index; /* original atom number */
582 char anm1; /* second letter of atom name */
583 char altloc; /* alternate location indicator */
584 } t_pdbindex;
586 int pdbicomp(const void *a,const void *b)
588 t_pdbindex *pa,*pb;
589 int d;
591 pa=(t_pdbindex *)a;
592 pb=(t_pdbindex *)b;
594 d = (pa->resnr - pb->resnr);
595 if (d==0) {
596 d = (pa->j - pb->j);
597 if (d==0) {
598 d = (pa->anm1 - pb->anm1);
599 if (d==0)
600 d = (pa->altloc - pb->altloc);
604 return d;
607 static void sort_pdbatoms(int nrtp,t_restp restp[],t_hackblock hb[],
608 int natoms,t_atoms **pdbaptr,rvec **x,
609 t_blocka *block,char ***gnames)
611 t_atoms *pdba,*pdbnew;
612 rvec **xnew;
613 int i,j;
614 t_restp *rptr;
615 t_hackblock *hbr;
616 t_pdbindex *pdbi;
617 atom_id *a;
618 char *atomnm;
620 pdba=*pdbaptr;
621 natoms=pdba->nr;
622 pdbnew=NULL;
623 snew(xnew,1);
624 snew(pdbi, natoms);
626 for(i=0; i<natoms; i++)
628 atomnm = *pdba->atomname[i];
629 rptr = &restp[pdba->atom[i].resind];
630 for(j=0; (j<rptr->natom); j++)
632 if (gmx_strcasecmp(atomnm,*(rptr->atomname[j])) == 0)
634 break;
637 if (j==rptr->natom)
639 char buf[STRLEN];
641 sprintf(buf,
642 "Atom %s in residue %s %d was not found in rtp entry %s with %d atoms\n"
643 "while sorting atoms.\n%s",atomnm,
644 *pdba->resinfo[pdba->atom[i].resind].name,
645 pdba->resinfo[pdba->atom[i].resind].nr,
646 rptr->resname,
647 rptr->natom,
648 is_hydrogen(atomnm) ?
649 "\nFor a hydrogen, this can be a different protonation state, or it\n"
650 "might have had a different number in the PDB file and was rebuilt\n"
651 "(it might for instance have been H3, and we only expected H1 & H2).\n"
652 "Note that hydrogens might have been added to the entry for the N-terminus.\n"
653 "Remove this hydrogen or choose a different protonation state to solve it.\n"
654 "Option -ignh will ignore all hydrogens in the input." : ".");
655 gmx_fatal(FARGS,buf);
657 /* make shadow array to be sorted into indexgroup */
658 pdbi[i].resnr = pdba->atom[i].resind;
659 pdbi[i].j = j;
660 pdbi[i].index = i;
661 pdbi[i].anm1 = atomnm[1];
662 pdbi[i].altloc = pdba->pdbinfo[i].altloc;
664 qsort(pdbi,natoms,(size_t)sizeof(pdbi[0]),pdbicomp);
666 /* pdba is sorted in pdbnew using the pdbi index */
667 snew(a,natoms);
668 snew(pdbnew,1);
669 init_t_atoms(pdbnew,natoms,TRUE);
670 snew(*xnew,natoms);
671 pdbnew->nr=pdba->nr;
672 pdbnew->nres=pdba->nres;
673 sfree(pdbnew->resinfo);
674 pdbnew->resinfo=pdba->resinfo;
675 for (i=0; i<natoms; i++) {
676 pdbnew->atom[i] = pdba->atom[pdbi[i].index];
677 pdbnew->atomname[i] = pdba->atomname[pdbi[i].index];
678 pdbnew->pdbinfo[i] = pdba->pdbinfo[pdbi[i].index];
679 copy_rvec((*x)[pdbi[i].index],(*xnew)[i]);
680 /* make indexgroup in block */
681 a[i]=pdbi[i].index;
683 /* clean up */
684 sfree(pdba->atomname);
685 sfree(pdba->atom);
686 sfree(pdba->pdbinfo);
687 sfree(pdba);
688 sfree(*x);
689 /* copy the sorted pdbnew back to pdba */
690 *pdbaptr=pdbnew;
691 *x=*xnew;
692 add_grp(block, gnames, natoms, a, "prot_sort");
693 sfree(xnew);
694 sfree(a);
695 sfree(pdbi);
698 static int remove_duplicate_atoms(t_atoms *pdba,rvec x[],gmx_bool bVerbose)
700 int i,j,oldnatoms,ndel;
701 t_resinfo *ri;
703 printf("Checking for duplicate atoms....\n");
704 oldnatoms = pdba->nr;
705 ndel = 0;
706 /* NOTE: pdba->nr is modified inside the loop */
707 for(i=1; (i < pdba->nr); i++) {
708 /* compare 'i' and 'i-1', throw away 'i' if they are identical
709 this is a 'while' because multiple alternate locations can be present */
710 while ( (i < pdba->nr) &&
711 (pdba->atom[i-1].resind == pdba->atom[i].resind) &&
712 (strcmp(*pdba->atomname[i-1],*pdba->atomname[i])==0) ) {
713 ndel++;
714 if (bVerbose) {
715 ri = &pdba->resinfo[pdba->atom[i].resind];
716 printf("deleting duplicate atom %4s %s%4d%c",
717 *pdba->atomname[i],*ri->name,ri->nr,ri->ic);
718 if (ri->chainid && (ri->chainid != ' '))
719 printf(" ch %c", ri->chainid);
720 if (pdba->pdbinfo) {
721 if (pdba->pdbinfo[i].atomnr)
722 printf(" pdb nr %4d",pdba->pdbinfo[i].atomnr);
723 if (pdba->pdbinfo[i].altloc && (pdba->pdbinfo[i].altloc!=' '))
724 printf(" altloc %c",pdba->pdbinfo[i].altloc);
726 printf("\n");
728 pdba->nr--;
729 /* We can not free, since it might be in the symtab */
730 /* sfree(pdba->atomname[i]); */
731 for (j=i; j < pdba->nr; j++) {
732 pdba->atom[j] = pdba->atom[j+1];
733 pdba->atomname[j] = pdba->atomname[j+1];
734 pdba->pdbinfo[j] = pdba->pdbinfo[j+1];
735 copy_rvec(x[j+1],x[j]);
737 srenew(pdba->atom, pdba->nr);
738 /* srenew(pdba->atomname, pdba->nr); */
739 srenew(pdba->pdbinfo, pdba->nr);
742 if (pdba->nr != oldnatoms)
743 printf("Now there are %d atoms. Deleted %d duplicates.\n",pdba->nr,ndel);
745 return pdba->nr;
748 void find_nc_ter(t_atoms *pdba,int r0,int r1,int *r_start,int *r_end,gmx_residuetype_t rt)
750 int i;
751 const char *p_startrestype;
752 const char *p_restype;
753 int nstartwarn,nendwarn;
755 *r_start = -1;
756 *r_end = -1;
758 nstartwarn = 0;
759 nendwarn = 0;
761 /* Find the starting terminus (typially N or 5') */
762 for(i=r0;i<r1 && *r_start==-1;i++)
764 gmx_residuetype_get_type(rt,*pdba->resinfo[i].name,&p_startrestype);
765 if( !gmx_strcasecmp(p_startrestype,"Protein") || !gmx_strcasecmp(p_startrestype,"DNA") || !gmx_strcasecmp(p_startrestype,"RNA") )
767 printf("Identified residue %s%d as a starting terminus.\n",*pdba->resinfo[i].name,pdba->resinfo[i].nr);
768 *r_start=i;
770 else
772 if(nstartwarn < 5)
774 printf("Warning: Starting residue %s%d in chain not identified as Protein/RNA/DNA.\n",*pdba->resinfo[i].name,pdba->resinfo[i].nr);
776 if(nstartwarn == 5)
778 printf("More than 5 unidentified residues at start of chain - disabling further warnings.\n");
780 nstartwarn++;
784 if(*r_start>=0)
786 /* Go through the rest of the residues, check that they are the same class, and identify the ending terminus. */
787 for(i=*r_start;i<r1;i++)
789 gmx_residuetype_get_type(rt,*pdba->resinfo[i].name,&p_restype);
790 if( !gmx_strcasecmp(p_restype,p_startrestype) && nendwarn==0)
792 *r_end=i;
794 else
796 if(nendwarn < 5)
798 printf("Warning: Residue %s%d in chain has different type (%s) from starting residue %s%d (%s).\n",
799 *pdba->resinfo[i].name,pdba->resinfo[i].nr,p_restype,
800 *pdba->resinfo[*r_start].name,pdba->resinfo[*r_start].nr,p_startrestype);
802 if(nendwarn == 5)
804 printf("More than 5 unidentified residues at end of chain - disabling further warnings.\n");
806 nendwarn++;
811 if(*r_end>=0)
813 printf("Identified residue %s%d as a ending terminus.\n",*pdba->resinfo[*r_end].name,pdba->resinfo[*r_end].nr);
818 static void
819 modify_chain_numbers(t_atoms * pdba,
820 const char * chainsep)
822 int i;
823 char old_prev_chainid;
824 char old_this_chainid;
825 int old_prev_chainnum;
826 int old_this_chainnum;
827 t_resinfo *ri;
828 int new_chainnum;
830 enum
832 SPLIT_ID_OR_TER,
833 SPLIT_ID_AND_TER,
834 SPLIT_ID_ONLY,
835 SPLIT_TER_ONLY
837 splitting;
839 printf("Splitting PDB chains based on ");
840 splitting = SPLIT_TER_ONLY; /* keep compiler happy */
842 /* Be a bit flexible to catch typos */
843 if (!strncmp(chainsep,"id_o",4) || !strncmp(chainsep,"int",3))
845 /* For later interactive splitting we tentatively assign new chain numbers at either changing id or ter records */
846 splitting = SPLIT_ID_OR_TER;
847 printf("TER records or changing chain id.\n");
849 else if (!strncmp(chainsep,"id_a",4))
851 splitting = SPLIT_ID_AND_TER;
852 printf("TER records and chain id.\n");
854 else if (strlen(chainsep)==2 && !strncmp(chainsep,"id",4))
856 splitting = SPLIT_ID_ONLY;
857 printf("changing chain id only (ignoring TER records).\n");
859 else if (chainsep[0]=='t')
861 splitting = SPLIT_TER_ONLY;
862 printf("TER records only (ignoring chain id).\n");
864 else
866 gmx_fatal(FARGS,"Unidentified setting for chain separation: %s\n",chainsep);
869 /* The default chain enumeration is based on TER records only, which is reflected in chainnum below */
871 old_prev_chainid = '?';
872 old_prev_chainnum = -1;
873 new_chainnum = -1;
875 for(i=0;i<pdba->nres;i++)
877 ri = &pdba->resinfo[i];
878 old_this_chainid = ri->chainid;
879 old_this_chainnum = ri->chainnum;
881 switch (splitting)
883 case SPLIT_ID_OR_TER:
884 if(old_this_chainid != old_prev_chainid || old_this_chainnum != old_prev_chainnum)
886 new_chainnum++;
888 break;
890 case SPLIT_ID_AND_TER:
891 if(old_this_chainid != old_prev_chainid && old_this_chainnum != old_prev_chainnum)
893 new_chainnum++;
895 break;
897 case SPLIT_ID_ONLY:
898 if(old_this_chainid != old_prev_chainid)
900 new_chainnum++;
902 break;
904 case SPLIT_TER_ONLY:
905 if(old_this_chainnum != old_prev_chainnum)
907 new_chainnum++;
909 break;
910 default:
911 gmx_fatal(FARGS,"Internal inconsistency - this shouldn't happen...");
912 break;
914 old_prev_chainid = old_this_chainid;
915 old_prev_chainnum = old_this_chainnum;
917 ri->chainnum = new_chainnum;
922 typedef struct {
923 char chainid;
924 char chainnum;
925 int start;
926 int natom;
927 gmx_bool bAllWat;
928 int nterpairs;
929 int *chainstart;
930 } t_pdbchain;
932 typedef struct {
933 char chainid;
934 int chainnum;
935 gmx_bool bAllWat;
936 int nterpairs;
937 int *chainstart;
938 t_hackblock **ntdb;
939 t_hackblock **ctdb;
940 int *r_start;
941 int *r_end;
942 t_atoms *pdba;
943 rvec *x;
944 } t_chain;
946 int main(int argc, char *argv[])
948 const char *desc[] = {
949 "This program reads a [TT].pdb[tt] (or [TT].gro[tt]) file, reads",
950 "some database files, adds hydrogens to the molecules and generates",
951 "coordinates in GROMACS (GROMOS), or optionally [TT].pdb[tt], format",
952 "and a topology in GROMACS format.",
953 "These files can subsequently be processed to generate a run input file.",
954 "[PAR]",
955 "[TT]pdb2gmx[tt] will search for force fields by looking for",
956 "a [TT]forcefield.itp[tt] file in subdirectories [TT]<forcefield>.ff[tt]",
957 "of the current working directory and of the GROMACS library directory",
958 "as inferred from the path of the binary or the [TT]GMXLIB[tt] environment",
959 "variable.",
960 "By default the forcefield selection is interactive,",
961 "but you can use the [TT]-ff[tt] option to specify one of the short names",
962 "in the list on the command line instead. In that case [TT]pdb2gmx[tt] just looks",
963 "for the corresponding [TT]<forcefield>.ff[tt] directory.",
964 "[PAR]",
965 "After choosing a force field, all files will be read only from",
966 "the corresponding force field directory.",
967 "If you want to modify or add a residue types, you can copy the force",
968 "field directory from the GROMACS library directory to your current",
969 "working directory. If you want to add new protein residue types,",
970 "you will need to modify [TT]residuetypes.dat[tt] in the library directory",
971 "or copy the whole library directory to a local directory and set",
972 "the environment variable [TT]GMXLIB[tt] to the name of that directory.",
973 "Check Chapter 5 of the manual for more information about file formats.",
974 "[PAR]",
976 "Note that a [TT].pdb[tt] file is nothing more than a file format, and it",
977 "need not necessarily contain a protein structure. Every kind of",
978 "molecule for which there is support in the database can be converted.",
979 "If there is no support in the database, you can add it yourself.[PAR]",
981 "The program has limited intelligence, it reads a number of database",
982 "files, that allow it to make special bonds (Cys-Cys, Heme-His, etc.),",
983 "if necessary this can be done manually. The program can prompt the",
984 "user to select which kind of LYS, ASP, GLU, CYS or HIS residue is",
985 "desired. For Lys the choice is between neutral (two protons on NZ) or",
986 "protonated (three protons, default), for Asp and Glu unprotonated",
987 "(default) or protonated, for His the proton can be either on ND1,",
988 "on NE2 or on both. By default these selections are done automatically.",
989 "For His, this is based on an optimal hydrogen bonding",
990 "conformation. Hydrogen bonds are defined based on a simple geometric",
991 "criterion, specified by the maximum hydrogen-donor-acceptor angle",
992 "and donor-acceptor distance, which are set by [TT]-angle[tt] and",
993 "[TT]-dist[tt] respectively.[PAR]",
995 "The protonation state of N- and C-termini can be chosen interactively",
996 "with the [TT]-ter[tt] flag. Default termini are ionized (NH3+ and COO-),",
997 "respectively. Some force fields support zwitterionic forms of isolated",
998 "amino acids, but for polypeptides these options should NOT be selected.[PAR]",
1000 "The separation of chains is not entirely trivial since the markup",
1001 "in user-generated PDB files frequently varies and sometimes it",
1002 "is desirable to merge entries across a TER record, for instance",
1003 "if you want a disulfide bridge or distance restraints between",
1004 "two protein chains or if you have a HEME group bound to a protein.",
1005 "In such cases multiple chains should be contained in a single",
1006 "[TT]moleculetype[tt] definition.",
1007 "To handle this, [TT]pdb2gmx[tt] has an option [TT]-chainsep[tt] so you can",
1008 "choose whether a new chain should start when we find a TER record,",
1009 "when the chain id changes, combinations of either or both of these",
1010 "or fully interactively.[PAR]",
1012 "[TT]pdb2gmx[tt] will also check the occupancy field of the [TT].pdb[tt] file.",
1013 "If any of the occupancies are not one, indicating that the atom is",
1014 "not resolved well in the structure, a warning message is issued.",
1015 "When a [TT].pdb[tt] file does not originate from an X-ray structure determination",
1016 "all occupancy fields may be zero. Either way, it is up to the user",
1017 "to verify the correctness of the input data (read the article!).[PAR]",
1019 "During processing the atoms will be reordered according to GROMACS",
1020 "conventions. With [TT]-n[tt] an index file can be generated that",
1021 "contains one group reordered in the same way. This allows you to",
1022 "convert a GROMOS trajectory and coordinate file to GROMOS. There is",
1023 "one limitation: reordering is done after the hydrogens are stripped",
1024 "from the input and before new hydrogens are added. This means that",
1025 "you should not use [TT]-ignh[tt].[PAR]",
1027 "The [TT].gro[tt] and [TT].g96[tt] file formats do not support chain",
1028 "identifiers. Therefore it is useful to enter a [TT].pdb[tt] file name at",
1029 "the [TT]-o[tt] option when you want to convert a multi-chain [TT].pdb[tt] file.",
1030 "[PAR]",
1032 "The option [TT]-vsite[tt] removes hydrogen and fast improper dihedral",
1033 "motions. Angular and out-of-plane motions can be removed by changing",
1034 "hydrogens into virtual sites and fixing angles, which fixes their",
1035 "position relative to neighboring atoms. Additionally, all atoms in the",
1036 "aromatic rings of the standard amino acids (i.e. PHE, TRP, TYR and HIS)",
1037 "can be converted into virtual sites, eliminating the fast improper dihedral",
1038 "fluctuations in these rings. [BB]Note[bb] that in this case all other hydrogen",
1039 "atoms are also converted to virtual sites. The mass of all atoms that are",
1040 "converted into virtual sites, is added to the heavy atoms.[PAR]",
1041 "Also slowing down of dihedral motion can be done with [TT]-heavyh[tt]",
1042 "done by increasing the hydrogen-mass by a factor of 4. This is also",
1043 "done for water hydrogens to slow down the rotational motion of water.",
1044 "The increase in mass of the hydrogens is subtracted from the bonded",
1045 "(heavy) atom so that the total mass of the system remains the same."
1049 FILE *fp,*top_file,*top_file2,*itp_file=NULL;
1050 int natom,nres;
1051 t_atoms pdba_all,*pdba;
1052 t_atoms *atoms;
1053 t_resinfo *ri;
1054 t_blocka *block;
1055 int chain,nch,maxch,nwaterchain;
1056 t_pdbchain *pdb_ch;
1057 t_chain *chains,*cc;
1058 char select[STRLEN];
1059 int nincl,nmol;
1060 char **incls;
1061 t_mols *mols;
1062 char **gnames;
1063 int ePBC;
1064 matrix box;
1065 rvec box_space;
1066 int i,j,k,l,nrtp;
1067 int *swap_index,si;
1068 t_restp *restp;
1069 t_hackblock *ah;
1070 t_symtab symtab;
1071 gpp_atomtype_t atype;
1072 gmx_residuetype_t rt;
1073 const char *top_fn;
1074 char fn[256],itp_fn[STRLEN],posre_fn[STRLEN],buf_fn[STRLEN];
1075 char molname[STRLEN],title[STRLEN],quote[STRLEN],generator[STRLEN];
1076 char *c,forcefield[STRLEN],ffdir[STRLEN];
1077 char ffname[STRLEN],suffix[STRLEN],buf[STRLEN];
1078 char *watermodel;
1079 const char *watres;
1080 int nrtpf;
1081 char **rtpf;
1082 char rtp[STRLEN];
1083 int nrrn;
1084 char **rrn;
1085 int nrtprename,naa;
1086 rtprename_t *rtprename=NULL;
1087 int nah,nNtdb,nCtdb,ntdblist;
1088 t_hackblock *ntdb,*ctdb,**tdblist;
1089 int nssbonds;
1090 t_ssbond *ssbonds;
1091 rvec *pdbx,*x;
1092 gmx_bool bVsites=FALSE,bWat,bPrevWat=FALSE,bITP,bVsiteAromatics=FALSE,bMerge;
1093 real mHmult=0;
1094 t_hackblock *hb_chain;
1095 t_restp *restp_chain;
1096 output_env_t oenv;
1097 const char *p_restype;
1098 int rc;
1099 int this_atomnum;
1100 int prev_atomnum;
1101 const char * prev_atomname;
1102 const char * this_atomname;
1103 const char * prev_resname;
1104 const char * this_resname;
1105 int prev_resnum;
1106 int this_resnum;
1107 char prev_chainid;
1108 char this_chainid;
1109 int prev_chainnumber;
1110 int this_chainnumber;
1111 int nid_used;
1112 int this_chainstart;
1113 int prev_chainstart;
1114 gmx_bool bMerged;
1116 gmx_atomprop_t aps;
1118 t_filenm fnm[] = {
1119 { efSTX, "-f", "eiwit.pdb", ffREAD },
1120 { efSTO, "-o", "conf", ffWRITE },
1121 { efTOP, NULL, NULL, ffWRITE },
1122 { efITP, "-i", "posre", ffWRITE },
1123 { efNDX, "-n", "clean", ffOPTWR },
1124 { efSTO, "-q", "clean.pdb", ffOPTWR }
1126 #define NFILE asize(fnm)
1129 /* Command line arguments must be static */
1130 static gmx_bool bNewRTP=FALSE;
1131 static gmx_bool bInter=FALSE, bCysMan=FALSE;
1132 static gmx_bool bLysMan=FALSE, bAspMan=FALSE, bGluMan=FALSE, bHisMan=FALSE;
1133 static gmx_bool bGlnMan=FALSE, bArgMan=FALSE;
1134 static gmx_bool bTerMan=FALSE, bUnA=FALSE, bHeavyH;
1135 static gmx_bool bSort=TRUE, bAllowMissing=FALSE, bRemoveH=FALSE;
1136 static gmx_bool bDeuterate=FALSE,bVerbose=FALSE,bChargeGroups=TRUE,bCmap=TRUE;
1137 static gmx_bool bRenumRes=FALSE,bRTPresname=FALSE;
1138 static real angle=135.0, distance=0.3,posre_fc=1000;
1139 static real long_bond_dist=0.25, short_bond_dist=0.05;
1140 static const char *vsitestr[] = { NULL, "none", "hydrogens", "aromatics", NULL };
1141 static const char *watstr[] = { NULL, "select", "none", "spc", "spce", "tip3p", "tip4p", "tip5p", NULL };
1142 static const char *chainsep[] = { NULL, "id_or_ter", "id_and_ter", "ter", "id", "interactive", NULL };
1143 static const char *ff = "select";
1145 t_pargs pa[] = {
1146 { "-newrtp", FALSE, etBOOL, {&bNewRTP},
1147 "HIDDENWrite the residue database in new format to [TT]new.rtp[tt]"},
1148 { "-lb", FALSE, etREAL, {&long_bond_dist},
1149 "HIDDENLong bond warning distance" },
1150 { "-sb", FALSE, etREAL, {&short_bond_dist},
1151 "HIDDENShort bond warning distance" },
1152 { "-chainsep", FALSE, etENUM, {chainsep},
1153 "Condition in PDB files when a new chain and molecule_type should be started" },
1154 { "-ff", FALSE, etSTR, {&ff},
1155 "Force field, interactive by default. Use [TT]-h[tt] for information." },
1156 { "-water", FALSE, etENUM, {watstr},
1157 "Water model to use" },
1158 { "-inter", FALSE, etBOOL, {&bInter},
1159 "Set the next 8 options to interactive"},
1160 { "-ss", FALSE, etBOOL, {&bCysMan},
1161 "Interactive SS bridge selection" },
1162 { "-ter", FALSE, etBOOL, {&bTerMan},
1163 "Interactive termini selection, iso charged" },
1164 { "-lys", FALSE, etBOOL, {&bLysMan},
1165 "Interactive lysine selection, iso charged" },
1166 { "-arg", FALSE, etBOOL, {&bArgMan},
1167 "Interactive arginine selection, iso charged" },
1168 { "-asp", FALSE, etBOOL, {&bAspMan},
1169 "Interactive aspartic Acid selection, iso charged" },
1170 { "-glu", FALSE, etBOOL, {&bGluMan},
1171 "Interactive glutamic Acid selection, iso charged" },
1172 { "-gln", FALSE, etBOOL, {&bGlnMan},
1173 "Interactive glutamine selection, iso neutral" },
1174 { "-his", FALSE, etBOOL, {&bHisMan},
1175 "Interactive histidine selection, iso checking H-bonds" },
1176 { "-angle", FALSE, etREAL, {&angle},
1177 "Minimum hydrogen-donor-acceptor angle for a H-bond (degrees)" },
1178 { "-dist", FALSE, etREAL, {&distance},
1179 "Maximum donor-acceptor distance for a H-bond (nm)" },
1180 { "-una", FALSE, etBOOL, {&bUnA},
1181 "Select aromatic rings with united CH atoms on phenylalanine, "
1182 "tryptophane and tyrosine" },
1183 { "-sort", FALSE, etBOOL, {&bSort},
1184 "HIDDENSort the residues according to database, turning this off is dangerous as charge groups might be broken in parts" },
1185 { "-ignh", FALSE, etBOOL, {&bRemoveH},
1186 "Ignore hydrogen atoms that are in the coordinate file" },
1187 { "-missing",FALSE, etBOOL, {&bAllowMissing},
1188 "Continue when atoms are missing, dangerous" },
1189 { "-v", FALSE, etBOOL, {&bVerbose},
1190 "Be slightly more verbose in messages" },
1191 { "-posrefc",FALSE, etREAL, {&posre_fc},
1192 "Force constant for position restraints" },
1193 { "-vsite", FALSE, etENUM, {vsitestr},
1194 "Convert atoms to virtual sites" },
1195 { "-heavyh", FALSE, etBOOL, {&bHeavyH},
1196 "Make hydrogen atoms heavy" },
1197 { "-deuterate", FALSE, etBOOL, {&bDeuterate},
1198 "Change the mass of hydrogens to 2 amu" },
1199 { "-chargegrp", TRUE, etBOOL, {&bChargeGroups},
1200 "Use charge groups in the [TT].rtp[tt] file" },
1201 { "-cmap", TRUE, etBOOL, {&bCmap},
1202 "Use cmap torsions (if enabled in the [TT].rtp[tt] file)" },
1203 { "-renum", TRUE, etBOOL, {&bRenumRes},
1204 "Renumber the residues consecutively in the output" },
1205 { "-rtpres", TRUE, etBOOL, {&bRTPresname},
1206 "Use [TT].rtp[tt] entry names as residue names" }
1208 #define NPARGS asize(pa)
1210 CopyRight(stderr,argv[0]);
1211 parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,asize(desc),desc,
1212 0,NULL,&oenv);
1214 /* Force field selection, interactive or direct */
1215 choose_ff(strcmp(ff,"select") == 0 ? NULL : ff,
1216 forcefield,sizeof(forcefield),
1217 ffdir,sizeof(ffdir));
1219 if (strlen(forcefield) > 0) {
1220 strcpy(ffname,forcefield);
1221 ffname[0] = toupper(ffname[0]);
1222 } else {
1223 gmx_fatal(FARGS,"Empty forcefield string");
1226 printf("\nUsing the %s force field in directory %s\n\n",
1227 ffname,ffdir);
1229 choose_watermodel(watstr[0],ffdir,&watermodel);
1231 if (bInter) {
1232 /* if anything changes here, also change description of -inter */
1233 bCysMan = TRUE;
1234 bTerMan = TRUE;
1235 bLysMan = TRUE;
1236 bArgMan = TRUE;
1237 bAspMan = TRUE;
1238 bGluMan = TRUE;
1239 bGlnMan = TRUE;
1240 bHisMan = TRUE;
1243 if (bHeavyH)
1244 mHmult=4.0;
1245 else if (bDeuterate)
1246 mHmult=2.0;
1247 else
1248 mHmult=1.0;
1250 switch(vsitestr[0][0]) {
1251 case 'n': /* none */
1252 bVsites=FALSE;
1253 bVsiteAromatics=FALSE;
1254 break;
1255 case 'h': /* hydrogens */
1256 bVsites=TRUE;
1257 bVsiteAromatics=FALSE;
1258 break;
1259 case 'a': /* aromatics */
1260 bVsites=TRUE;
1261 bVsiteAromatics=TRUE;
1262 break;
1263 default:
1264 gmx_fatal(FARGS,"DEATH HORROR in $s (%d): vsitestr[0]='%s'",
1265 __FILE__,__LINE__,vsitestr[0]);
1266 }/* end switch */
1268 /* Open the symbol table */
1269 open_symtab(&symtab);
1271 /* Residue type database */
1272 gmx_residuetype_init(&rt);
1274 /* Read residue renaming database(s), if present */
1275 nrrn = fflib_search_file_end(ffdir,".r2b",FALSE,&rrn);
1277 nrtprename = 0;
1278 rtprename = NULL;
1279 for(i=0; i<nrrn; i++) {
1280 fp = fflib_open(rrn[i]);
1281 read_rtprename(rrn[i],fp,&nrtprename,&rtprename);
1282 fclose(fp);
1283 sfree(rrn[i]);
1285 sfree(rrn);
1287 /* Add all alternative names from the residue renaming database to the list of recognized amino/nucleic acids. */
1288 naa=0;
1289 for(i=0;i<nrtprename;i++)
1291 rc=gmx_residuetype_get_type(rt,rtprename[i].gmx,&p_restype);
1293 /* Only add names if the 'standard' gromacs/iupac base name was found */
1294 if(rc==0)
1296 gmx_residuetype_add(rt,rtprename[i].main,p_restype);
1297 gmx_residuetype_add(rt,rtprename[i].nter,p_restype);
1298 gmx_residuetype_add(rt,rtprename[i].cter,p_restype);
1299 gmx_residuetype_add(rt,rtprename[i].bter,p_restype);
1303 clear_mat(box);
1304 if (watermodel != NULL && (strstr(watermodel,"4p") ||
1305 strstr(watermodel,"4P"))) {
1306 watres = "HO4";
1307 } else if (watermodel != NULL && (strstr(watermodel,"5p") ||
1308 strstr(watermodel,"5P"))) {
1309 watres = "HO5";
1310 } else {
1311 watres = "HOH";
1314 aps = gmx_atomprop_init();
1315 natom = read_pdball(opt2fn("-f",NFILE,fnm),opt2fn_null("-q",NFILE,fnm),title,
1316 &pdba_all,&pdbx,&ePBC,box,bRemoveH,&symtab,rt,watres,
1317 aps,bVerbose);
1319 if (natom==0)
1320 gmx_fatal(FARGS,"No atoms found in pdb file %s\n",opt2fn("-f",NFILE,fnm));
1322 printf("Analyzing pdb file\n");
1323 nch=0;
1324 maxch=0;
1325 nwaterchain=0;
1327 modify_chain_numbers(&pdba_all,chainsep[0]);
1330 bMerge = !strncmp(chainsep[0],"int",3);
1332 this_atomname = NULL;
1333 this_atomnum = -1;
1334 this_resname = NULL;
1335 this_resnum = -1;
1336 this_chainid = '?';
1337 this_chainnumber = -1;
1338 this_chainstart = 0;
1339 /* Keep the compiler happy */
1340 prev_chainstart = 0;
1342 pdb_ch=NULL;
1343 bMerged = FALSE;
1344 for (i=0; (i<natom); i++)
1346 ri = &pdba_all.resinfo[pdba_all.atom[i].resind];
1348 prev_atomname = this_atomname;
1349 prev_atomnum = this_atomnum;
1350 prev_resname = this_resname;
1351 prev_resnum = this_resnum;
1352 prev_chainid = this_chainid;
1353 prev_chainnumber = this_chainnumber;
1354 if (!bMerged)
1356 prev_chainstart = this_chainstart;
1359 this_atomname = *pdba_all.atomname[i];
1360 this_atomnum = (pdba_all.pdbinfo != NULL) ? pdba_all.pdbinfo[i].atomnr : i+1;
1361 this_resname = *ri->name;
1362 this_resnum = ri->nr;
1363 this_chainid = ri->chainid;
1364 this_chainnumber = ri->chainnum;
1366 bWat = gmx_strcasecmp(*ri->name,watres) == 0;
1367 if ((i == 0) || (this_chainnumber != prev_chainnumber) || (bWat != bPrevWat))
1369 this_chainstart = pdba_all.atom[i].resind;
1370 if (bMerge && i>0 && !bWat)
1372 printf("Merge chain ending with residue %s%d (chain id '%c', atom %d %s) with\n"
1373 "chain starting with residue %s%d (chain id '%c', atom %d %s)? [n/y]\n",
1374 prev_resname,prev_resnum,prev_chainid,prev_atomnum,prev_atomname,
1375 this_resname,this_resnum,this_chainid,this_atomnum,this_atomname);
1377 if(NULL==fgets(select,STRLEN-1,stdin))
1379 gmx_fatal(FARGS,"Error reading from stdin");
1382 else
1384 select[0] = 'n';
1387 bMerged = (select[0] == 'y');
1388 if (bMerged)
1390 pdb_ch[nch-1].chainstart[pdb_ch[nch-1].nterpairs] =
1391 pdba_all.atom[i].resind - prev_chainstart;
1392 pdb_ch[nch-1].nterpairs++;
1393 srenew(pdb_ch[nch-1].chainstart,pdb_ch[nch-1].nterpairs+1);
1395 else
1397 /* set natom for previous chain */
1398 if (nch > 0)
1400 pdb_ch[nch-1].natom=i-pdb_ch[nch-1].start;
1402 if (bWat)
1404 nwaterchain++;
1405 ri->chainid = ' ';
1407 /* check if chain identifier was used before */
1408 for (j=0; (j<nch); j++)
1410 if (pdb_ch[j].chainid != ' ' && pdb_ch[j].chainid == ri->chainid)
1412 printf("WARNING: Chain identifier '%c' is used in two non-sequential blocks.\n"
1413 "They will be treated as separate chains unless you reorder your file.\n",
1414 ri->chainid);
1417 if (nch == maxch)
1419 maxch += 16;
1420 srenew(pdb_ch,maxch);
1422 pdb_ch[nch].chainid = ri->chainid;
1423 pdb_ch[nch].chainnum = ri->chainnum;
1424 pdb_ch[nch].start=i;
1425 pdb_ch[nch].bAllWat=bWat;
1426 if (bWat)
1427 pdb_ch[nch].nterpairs=0;
1428 else
1429 pdb_ch[nch].nterpairs=1;
1430 snew(pdb_ch[nch].chainstart,pdb_ch[nch].nterpairs+1);
1431 /* modified [nch] to [0] below */
1432 pdb_ch[nch].chainstart[0]=0;
1433 nch++;
1436 bPrevWat=bWat;
1438 pdb_ch[nch-1].natom=natom-pdb_ch[nch-1].start;
1440 /* set all the water blocks at the end of the chain */
1441 snew(swap_index,nch);
1442 j=0;
1443 for(i=0; i<nch; i++)
1444 if (!pdb_ch[i].bAllWat) {
1445 swap_index[j]=i;
1446 j++;
1448 for(i=0; i<nch; i++)
1449 if (pdb_ch[i].bAllWat) {
1450 swap_index[j]=i;
1451 j++;
1453 if (nwaterchain>1)
1454 printf("Moved all the water blocks to the end\n");
1456 snew(chains,nch);
1457 /* copy pdb data and x for all chains */
1458 for (i=0; (i<nch); i++) {
1459 si=swap_index[i];
1460 chains[i].chainid = pdb_ch[si].chainid;
1461 chains[i].chainnum = pdb_ch[si].chainnum;
1462 chains[i].bAllWat = pdb_ch[si].bAllWat;
1463 chains[i].nterpairs = pdb_ch[si].nterpairs;
1464 chains[i].chainstart = pdb_ch[si].chainstart;
1465 snew(chains[i].ntdb,pdb_ch[si].nterpairs);
1466 snew(chains[i].ctdb,pdb_ch[si].nterpairs);
1467 snew(chains[i].r_start,pdb_ch[si].nterpairs);
1468 snew(chains[i].r_end,pdb_ch[si].nterpairs);
1470 snew(chains[i].pdba,1);
1471 init_t_atoms(chains[i].pdba,pdb_ch[si].natom,TRUE);
1472 snew(chains[i].x,chains[i].pdba->nr);
1473 for (j=0; j<chains[i].pdba->nr; j++) {
1474 chains[i].pdba->atom[j] = pdba_all.atom[pdb_ch[si].start+j];
1475 snew(chains[i].pdba->atomname[j],1);
1476 *chains[i].pdba->atomname[j] =
1477 strdup(*pdba_all.atomname[pdb_ch[si].start+j]);
1478 chains[i].pdba->pdbinfo[j] = pdba_all.pdbinfo[pdb_ch[si].start+j];
1479 copy_rvec(pdbx[pdb_ch[si].start+j],chains[i].x[j]);
1481 /* Re-index the residues assuming that the indices are continuous */
1482 k = chains[i].pdba->atom[0].resind;
1483 nres = chains[i].pdba->atom[chains[i].pdba->nr-1].resind - k + 1;
1484 chains[i].pdba->nres = nres;
1485 for(j=0; j < chains[i].pdba->nr; j++) {
1486 chains[i].pdba->atom[j].resind -= k;
1488 srenew(chains[i].pdba->resinfo,nres);
1489 for(j=0; j<nres; j++) {
1490 chains[i].pdba->resinfo[j] = pdba_all.resinfo[k+j];
1491 snew(chains[i].pdba->resinfo[j].name,1);
1492 *chains[i].pdba->resinfo[j].name = strdup(*pdba_all.resinfo[k+j].name);
1493 /* make all chain identifiers equal to that of the chain */
1494 chains[i].pdba->resinfo[j].chainid = pdb_ch[si].chainid;
1498 if (bMerge)
1499 printf("\nMerged %d chains into one molecule definition\n\n",
1500 pdb_ch[0].nterpairs);
1502 printf("There are %d chains and %d blocks of water and "
1503 "%d residues with %d atoms\n",
1504 nch-nwaterchain,nwaterchain,
1505 pdba_all.resinfo[pdba_all.atom[natom-1].resind].nr,natom);
1507 printf("\n %5s %4s %6s\n","chain","#res","#atoms");
1508 for (i=0; (i<nch); i++)
1509 printf(" %d '%c' %5d %6d %s\n",
1510 i+1, chains[i].chainid ? chains[i].chainid:'-',
1511 chains[i].pdba->nres, chains[i].pdba->nr,
1512 chains[i].bAllWat ? "(only water)":"");
1513 printf("\n");
1515 check_occupancy(&pdba_all,opt2fn("-f",NFILE,fnm),bVerbose);
1517 /* Read atomtypes... */
1518 atype = read_atype(ffdir,&symtab);
1520 /* read residue database */
1521 printf("Reading residue database... (%s)\n",forcefield);
1522 nrtpf = fflib_search_file_end(ffdir,".rtp",TRUE,&rtpf);
1523 nrtp = 0;
1524 restp = NULL;
1525 for(i=0; i<nrtpf; i++) {
1526 read_resall(rtpf[i],&nrtp,&restp,atype,&symtab,FALSE);
1527 sfree(rtpf[i]);
1529 sfree(rtpf);
1530 if (bNewRTP) {
1531 /* Not correct with multiple rtp input files with different bonded types */
1532 fp=gmx_fio_fopen("new.rtp","w");
1533 print_resall(fp,nrtp,restp,atype);
1534 gmx_fio_fclose(fp);
1537 /* read hydrogen database */
1538 nah = read_h_db(ffdir,&ah);
1540 /* Read Termini database... */
1541 nNtdb=read_ter_db(ffdir,'n',&ntdb,atype);
1542 nCtdb=read_ter_db(ffdir,'c',&ctdb,atype);
1544 top_fn=ftp2fn(efTOP,NFILE,fnm);
1545 top_file=gmx_fio_fopen(top_fn,"w");
1547 sprintf(generator,"%s - %s",ShortProgram(), GromacsVersion() );
1549 print_top_header(top_file,top_fn,generator,FALSE,ffdir,mHmult);
1551 nincl=0;
1552 nmol=0;
1553 incls=NULL;
1554 mols=NULL;
1555 nres=0;
1556 for(chain=0; (chain<nch); chain++) {
1557 cc = &(chains[chain]);
1559 /* set pdba, natom and nres to the current chain */
1560 pdba =cc->pdba;
1561 x =cc->x;
1562 natom=cc->pdba->nr;
1563 nres =cc->pdba->nres;
1565 if (cc->chainid && ( cc->chainid != ' ' ) )
1566 printf("Processing chain %d '%c' (%d atoms, %d residues)\n",
1567 chain+1,cc->chainid,natom,nres);
1568 else
1569 printf("Processing chain %d (%d atoms, %d residues)\n",
1570 chain+1,natom,nres);
1572 process_chain(pdba,x,bUnA,bUnA,bUnA,bLysMan,bAspMan,bGluMan,
1573 bHisMan,bArgMan,bGlnMan,angle,distance,&symtab,
1574 nrtprename,rtprename);
1576 cc->chainstart[cc->nterpairs] = pdba->nres;
1577 j = 0;
1578 for(i=0; i<cc->nterpairs; i++)
1580 find_nc_ter(pdba,cc->chainstart[i],cc->chainstart[i+1],
1581 &(cc->r_start[j]),&(cc->r_end[j]),rt);
1583 if (cc->r_start[j] >= 0 && cc->r_end[j] >= 0)
1585 j++;
1588 cc->nterpairs = j;
1589 if (cc->nterpairs == 0)
1591 printf("Problem with chain definition, or missing terminal residues.\n"
1592 "This chain does not appear to contain a recognized chain molecule.\n"
1593 "If this is incorrect, you can edit residuetypes.dat to modify the behavior.\n");
1596 /* Check for disulfides and other special bonds */
1597 nssbonds = mk_specbonds(pdba,x,bCysMan,&ssbonds,bVerbose);
1599 if (nrtprename > 0) {
1600 rename_resrtp(pdba,cc->nterpairs,cc->r_start,cc->r_end,nrtprename,rtprename,
1601 &symtab,bVerbose);
1604 if (debug) {
1605 if (nch==1) {
1606 sprintf(fn,"chain.pdb");
1607 } else {
1608 sprintf(fn,"chain_%c%d.pdb",cc->chainid,cc->chainnum);
1610 write_sto_conf(fn,title,pdba,x,NULL,ePBC,box);
1614 for(i=0; i<cc->nterpairs; i++)
1617 /* Set termini.
1618 * We first apply a filter so we only have the
1619 * termini that can be applied to the residue in question
1620 * (or a generic terminus if no-residue specific is available).
1622 /* First the N terminus */
1623 if (nNtdb > 0)
1625 tdblist = filter_ter(nrtp,restp,nNtdb,ntdb,
1626 *pdba->resinfo[cc->r_start[i]].name,
1627 *pdba->resinfo[cc->r_start[i]].rtp,
1628 &ntdblist);
1629 if(ntdblist==0)
1631 printf("No suitable end (N or 5') terminus found in database - assuming this residue\n"
1632 "is already in a terminus-specific form and skipping terminus selection.\n");
1633 cc->ntdb[i]=NULL;
1635 else
1637 if(bTerMan && ntdblist>1)
1639 sprintf(select,"Select start terminus type for %s-%d",
1640 *pdba->resinfo[cc->r_start[i]].name,
1641 pdba->resinfo[cc->r_start[i]].nr);
1642 cc->ntdb[i] = choose_ter(ntdblist,tdblist,select);
1644 else
1646 cc->ntdb[i] = tdblist[0];
1649 printf("Start terminus %s-%d: %s\n",
1650 *pdba->resinfo[cc->r_start[i]].name,
1651 pdba->resinfo[cc->r_start[i]].nr,
1652 (cc->ntdb[i])->name);
1653 sfree(tdblist);
1656 else
1658 cc->ntdb[i] = NULL;
1661 /* And the C terminus */
1662 if (nCtdb > 0)
1664 tdblist = filter_ter(nrtp,restp,nCtdb,ctdb,
1665 *pdba->resinfo[cc->r_end[i]].name,
1666 *pdba->resinfo[cc->r_end[i]].rtp,
1667 &ntdblist);
1668 if(ntdblist==0)
1670 printf("No suitable end (C or 3') terminus found in database - assuming this residue\n"
1671 "is already in a terminus-specific form and skipping terminus selection.\n");
1672 cc->ctdb[i] = NULL;
1674 else
1676 if(bTerMan && ntdblist>1)
1678 sprintf(select,"Select end terminus type for %s-%d",
1679 *pdba->resinfo[cc->r_end[i]].name,
1680 pdba->resinfo[cc->r_end[i]].nr);
1681 cc->ctdb[i] = choose_ter(ntdblist,tdblist,select);
1683 else
1685 cc->ctdb[i] = tdblist[0];
1687 printf("End terminus %s-%d: %s\n",
1688 *pdba->resinfo[cc->r_end[i]].name,
1689 pdba->resinfo[cc->r_end[i]].nr,
1690 (cc->ctdb[i])->name);
1691 sfree(tdblist);
1694 else
1696 cc->ctdb[i] = NULL;
1699 /* lookup hackblocks and rtp for all residues */
1700 get_hackblocks_rtp(&hb_chain, &restp_chain,
1701 nrtp, restp, pdba->nres, pdba->resinfo,
1702 cc->nterpairs, cc->ntdb, cc->ctdb, cc->r_start, cc->r_end);
1703 /* ideally, now we would not need the rtp itself anymore, but do
1704 everything using the hb and restp arrays. Unfortunately, that
1705 requires some re-thinking of code in gen_vsite.c, which I won't
1706 do now :( AF 26-7-99 */
1708 rename_atoms(NULL,ffdir,
1709 pdba,&symtab,restp_chain,FALSE,rt,FALSE,bVerbose);
1711 match_atomnames_with_rtp(restp_chain,hb_chain,pdba,x,bVerbose);
1713 if (bSort) {
1714 block = new_blocka();
1715 snew(gnames,1);
1716 sort_pdbatoms(pdba->nres,restp_chain,hb_chain,
1717 natom,&pdba,&x,block,&gnames);
1718 natom = remove_duplicate_atoms(pdba,x,bVerbose);
1719 if (ftp2bSet(efNDX,NFILE,fnm)) {
1720 if (bRemoveH) {
1721 fprintf(stderr,"WARNING: with the -remh option the generated "
1722 "index file (%s) might be useless\n"
1723 "(the index file is generated before hydrogens are added)",
1724 ftp2fn(efNDX,NFILE,fnm));
1726 write_index(ftp2fn(efNDX,NFILE,fnm),block,gnames);
1728 for(i=0; i < block->nr; i++)
1729 sfree(gnames[i]);
1730 sfree(gnames);
1731 done_blocka(block);
1732 } else {
1733 fprintf(stderr,"WARNING: "
1734 "without sorting no check for duplicate atoms can be done\n");
1737 /* Generate Hydrogen atoms (and termini) in the sequence */
1738 natom=add_h(&pdba,&x,nah,ah,
1739 cc->nterpairs,cc->ntdb,cc->ctdb,cc->r_start,cc->r_end,bAllowMissing,
1740 NULL,NULL,TRUE,FALSE);
1741 printf("Now there are %d residues with %d atoms\n",
1742 pdba->nres,pdba->nr);
1743 if (debug) write_pdbfile(debug,title,pdba,x,ePBC,box,' ',0,NULL,TRUE);
1745 if (debug)
1746 for(i=0; (i<natom); i++)
1747 fprintf(debug,"Res %s%d atom %d %s\n",
1748 *(pdba->resinfo[pdba->atom[i].resind].name),
1749 pdba->resinfo[pdba->atom[i].resind].nr,i+1,*pdba->atomname[i]);
1751 strcpy(posre_fn,ftp2fn(efITP,NFILE,fnm));
1753 /* make up molecule name(s) */
1755 k = (cc->nterpairs>0 && cc->r_start[0]>=0) ? cc->r_start[0] : 0;
1757 gmx_residuetype_get_type(rt,*pdba->resinfo[k].name,&p_restype);
1759 suffix[0]='\0';
1761 if (cc->bAllWat)
1763 sprintf(molname,"Water");
1765 else
1767 this_chainid = cc->chainid;
1769 /* Add the chain id if we have one */
1770 if(this_chainid != ' ')
1772 sprintf(buf,"_chain_%c",this_chainid);
1773 strcat(suffix,buf);
1776 /* Check if there have been previous chains with the same id */
1777 nid_used = 0;
1778 for(k=0;k<chain;k++)
1780 if(cc->chainid == chains[k].chainid)
1782 nid_used++;
1785 /* Add the number for this chain identifier if there are multiple copies */
1786 if(nid_used>0)
1789 sprintf(buf,"%d",nid_used+1);
1790 strcat(suffix,buf);
1793 if(strlen(suffix)>0)
1795 sprintf(molname,"%s%s",p_restype,suffix);
1797 else
1799 strcpy(molname,p_restype);
1803 if ((nch-nwaterchain>1) && !cc->bAllWat) {
1804 bITP=TRUE;
1805 strcpy(itp_fn,top_fn);
1806 printf("Chain time...\n");
1807 c=strrchr(itp_fn,'.');
1808 sprintf(c,"_%s.itp",molname);
1809 c=strrchr(posre_fn,'.');
1810 sprintf(c,"_%s.itp",molname);
1811 if (strcmp(itp_fn,posre_fn) == 0) {
1812 strcpy(buf_fn,posre_fn);
1813 c = strrchr(buf_fn,'.');
1814 *c = '\0';
1815 sprintf(posre_fn,"%s_pr.itp",buf_fn);
1818 nincl++;
1819 srenew(incls,nincl);
1820 incls[nincl-1]=strdup(itp_fn);
1821 itp_file=gmx_fio_fopen(itp_fn,"w");
1822 } else
1823 bITP=FALSE;
1825 srenew(mols,nmol+1);
1826 if (cc->bAllWat) {
1827 mols[nmol].name = strdup("SOL");
1828 mols[nmol].nr = pdba->nres;
1829 } else {
1830 mols[nmol].name = strdup(molname);
1831 mols[nmol].nr = 1;
1833 nmol++;
1835 if (bITP)
1836 print_top_comment(itp_file,itp_fn,generator,ffdir,TRUE);
1838 if (cc->bAllWat)
1839 top_file2=NULL;
1840 else
1841 if (bITP)
1842 top_file2=itp_file;
1843 else
1844 top_file2=top_file;
1846 pdb2top(top_file2,posre_fn,molname,pdba,&x,atype,&symtab,
1847 nrtp,restp,
1848 restp_chain,hb_chain,
1849 cc->nterpairs,cc->ntdb,cc->ctdb,bAllowMissing,
1850 bVsites,bVsiteAromatics,forcefield,ffdir,
1851 mHmult,nssbonds,ssbonds,
1852 long_bond_dist,short_bond_dist,bDeuterate,bChargeGroups,bCmap,
1853 bRenumRes,bRTPresname);
1855 if (!cc->bAllWat)
1856 write_posres(posre_fn,pdba,posre_fc);
1858 if (bITP)
1859 gmx_fio_fclose(itp_file);
1861 /* pdba and natom have been reassigned somewhere so: */
1862 cc->pdba = pdba;
1863 cc->x = x;
1865 if (debug) {
1866 if (cc->chainid == ' ')
1867 sprintf(fn,"chain.pdb");
1868 else
1869 sprintf(fn,"chain_%c.pdb",cc->chainid);
1870 cool_quote(quote,255,NULL);
1871 write_sto_conf(fn,quote,pdba,x,NULL,ePBC,box);
1875 if (watermodel == NULL) {
1876 for(chain=0; chain<nch; chain++) {
1877 if (chains[chain].bAllWat) {
1878 gmx_fatal(FARGS,"You have chosen not to include a water model, but there is water in the input file. Select a water model or remove the water from your input file.");
1881 } else {
1882 sprintf(buf_fn,"%s%c%s.itp",ffdir,DIR_SEPARATOR,watermodel);
1883 if (!fflib_fexist(buf_fn)) {
1884 gmx_fatal(FARGS,"The topology file '%s' for the selected water model '%s' can not be found in the force field directory. Select a different water model.",
1885 buf_fn,watermodel);
1889 print_top_mols(top_file,title,ffdir,watermodel,nincl,incls,nmol,mols);
1890 gmx_fio_fclose(top_file);
1892 gmx_residuetype_destroy(rt);
1894 /* now merge all chains back together */
1895 natom=0;
1896 nres=0;
1897 for (i=0; (i<nch); i++) {
1898 natom+=chains[i].pdba->nr;
1899 nres+=chains[i].pdba->nres;
1901 snew(atoms,1);
1902 init_t_atoms(atoms,natom,FALSE);
1903 for(i=0; i < atoms->nres; i++)
1904 sfree(atoms->resinfo[i].name);
1905 sfree(atoms->resinfo);
1906 atoms->nres=nres;
1907 snew(atoms->resinfo,nres);
1908 snew(x,natom);
1909 k=0;
1910 l=0;
1911 for (i=0; (i<nch); i++) {
1912 if (nch>1)
1913 printf("Including chain %d in system: %d atoms %d residues\n",
1914 i+1,chains[i].pdba->nr,chains[i].pdba->nres);
1915 for (j=0; (j<chains[i].pdba->nr); j++) {
1916 atoms->atom[k]=chains[i].pdba->atom[j];
1917 atoms->atom[k].resind += l; /* l is processed nr of residues */
1918 atoms->atomname[k]=chains[i].pdba->atomname[j];
1919 atoms->resinfo[atoms->atom[k].resind].chainid = chains[i].chainid;
1920 copy_rvec(chains[i].x[j],x[k]);
1921 k++;
1923 for (j=0; (j<chains[i].pdba->nres); j++) {
1924 atoms->resinfo[l] = chains[i].pdba->resinfo[j];
1925 if (bRTPresname) {
1926 atoms->resinfo[l].name = atoms->resinfo[l].rtp;
1928 l++;
1932 if (nch>1) {
1933 fprintf(stderr,"Now there are %d atoms and %d residues\n",k,l);
1934 print_sums(atoms, TRUE);
1937 fprintf(stderr,"\nWriting coordinate file...\n");
1938 clear_rvec(box_space);
1939 if (box[0][0] == 0)
1940 gen_box(0,atoms->nr,x,box,box_space,FALSE);
1941 write_sto_conf(ftp2fn(efSTO,NFILE,fnm),title,atoms,x,NULL,ePBC,box);
1943 printf("\t\t--------- PLEASE NOTE ------------\n");
1944 printf("You have successfully generated a topology from: %s.\n",
1945 opt2fn("-f",NFILE,fnm));
1946 if (watermodel != NULL) {
1947 printf("The %s force field and the %s water model are used.\n",
1948 ffname,watermodel);
1949 } else {
1950 printf("The %s force field is used.\n",
1951 ffname);
1953 printf("\t\t--------- ETON ESAELP ------------\n");
1956 thanx(stdout);
1958 return 0;