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
8 * GROningen MAchine for Chemical Simulations
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
34 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
39 #include "gmx_header_config.h"
45 #ifdef GMX_NATIVE_WINDOWS
58 #include "gmx_fatal.h"
60 #include "gpp_nextnb.h"
73 #include "gen_vsite.h"
76 #include "fflibutil.h"
79 /* this must correspond to enum in pdb2top.h */
80 const char *hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
82 static int missing_atoms(t_restp *rp, int resind,t_atoms *at, int i0, int i)
86 gmx_bool bFound, bRet;
89 for (j=0; j<rp->natom; j++)
91 name=*(rp->atomname[j]);
95 bFound = (bFound || !gmx_strcasecmp(*(at->atomname[k]),name));
100 fprintf(stderr,"\nWARNING: "
101 "atom %s is missing in residue %s %d in the pdb file\n",
102 name,*(at->resinfo[resind].name),at->resinfo[resind].nr);
103 if (name[0]=='H' || name[0]=='h')
105 fprintf(stderr," You might need to add atom %s to the hydrogen database of building block %s\n"
106 " in the file %s.hdb (see the manual)\n",
107 name,*(at->resinfo[resind].rtp),rp->filebase);
109 fprintf(stderr,"\n");
116 gmx_bool is_int(double x)
118 const double tol = 1e-4;
125 return (fabs(x-ix) < tol);
128 static void swap_strings(char **s,int i,int j)
138 choose_ff(const char *ffsel,
139 char *forcefield, int ff_maxlen,
140 char *ffdir, int ffdir_maxlen)
143 char **ffdirs,**ffs,**ffs_dir,*ptr;
144 int i,j,sel,cwdsel,nfound;
145 char buf[STRLEN],**desc;
149 nff = fflib_search_file_in_dirend(fflib_forcefield_itp(),
150 fflib_forcefield_dir_ext(),
155 gmx_fatal(FARGS,"No force fields found (files with name '%s' in subdirectories ending on '%s')",
156 fflib_forcefield_itp(),fflib_forcefield_dir_ext());
159 /* Replace with unix path separators */
160 if(DIR_SEPARATOR!='/')
164 while( (ptr=strchr(ffdirs[i],DIR_SEPARATOR))!=NULL )
171 /* Store the force field names in ffs */
176 /* Remove the path from the ffdir name - use our unix standard here! */
177 ptr = strrchr(ffdirs[i],'/');
180 ffs[i] = strdup(ffdirs[i]);
181 ffs_dir[i] = low_gmxlibfn(ffdirs[i],FALSE,FALSE);
182 if (ffs_dir[i] == NULL)
184 gmx_fatal(FARGS,"Can no longer find file '%s'",ffdirs[i]);
189 ffs[i] = strdup(ptr+1);
190 ffs_dir[i] = strdup(ffdirs[i]);
192 ffs_dir[i][strlen(ffs_dir[i])-strlen(ffs[i])-1] = '\0';
193 /* Remove the extension from the ffdir name */
194 ffs[i][strlen(ffs[i])-strlen(fflib_forcefield_dir_ext())] = '\0';
204 if ( strcmp(ffs[i],ffsel)==0 )
206 /* Matching ff name */
210 if( strncmp(ffs_dir[i],".",1)==0 )
227 "Force field '%s' occurs in %d places. pdb2gmx is using the one in the\n"
228 "current directory. Use interactive selection (not the -ff option) if\n"
229 "you would prefer a different one.\n",ffsel,nfound);
234 "Force field '%s' occurs in %d places, but not in the current directory.\n"
235 "Run without the -ff switch and select the force field interactively.",ffsel,nfound);
240 gmx_fatal(FARGS,"Could not find force field '%s' in current directory, install tree or GMXDATA path.",ffsel);
246 for(i=0; (i<nff); i++)
248 sprintf(buf,"%s%c%s%s%c%s",
249 ffs_dir[i],DIR_SEPARATOR,
250 ffs[i],fflib_forcefield_dir_ext(),DIR_SEPARATOR,
251 fflib_forcefield_doc());
254 /* We don't use fflib_open, because we don't want printf's */
255 fp = ffopen(buf,"r");
256 snew(desc[i],STRLEN);
257 get_a_line(fp,desc[i],STRLEN);
262 desc[i] = strdup(ffs[i]);
265 /* Order force fields from the same dir alphabetically
266 * and put deprecated force fields at the end.
268 for(i=0; (i<nff); i++)
270 for(j=i+1; (j<nff); j++)
272 if (strcmp(ffs_dir[i],ffs_dir[j]) == 0 &&
273 ((desc[i][0] == '[' && desc[j][0] != '[') ||
274 ((desc[i][0] == '[' || desc[j][0] != '[') &&
275 gmx_strcasecmp(desc[i],desc[j]) > 0)))
277 swap_strings(ffdirs,i,j);
278 swap_strings(ffs ,i,j);
279 swap_strings(desc ,i,j);
284 printf("\nSelect the Force Field:\n");
285 for(i=0; (i<nff); i++)
287 if (i == 0 || strcmp(ffs_dir[i-1],ffs_dir[i]) != 0)
289 if( strcmp(ffs_dir[i],".")==0 )
291 printf("From current directory:\n");
295 printf("From '%s':\n",ffs_dir[i]);
298 printf("%2d: %s\n",i+1,desc[i]);
305 pret = fgets(buf,STRLEN,stdin);
309 sscanf(buf,"%d",&sel);
313 while ( pret==NULL || (sel < 0) || (sel >= nff));
315 /* Check for a current limitation of the fflib code.
316 * It will always read from the first ff directory in the list.
317 * This check assumes that the order of ffs matches the order
318 * in which fflib_open searches ff library files.
322 if (strcmp(ffs[i],ffs[sel]) == 0)
324 gmx_fatal(FARGS,"Can only select the first of multiple force field entries with directory name '%s%s' in the list. If you want to use the next entry, run pdb2gmx in a different directory or rename or move the force field directory present in the current working directory.",
325 ffs[sel],fflib_forcefield_dir_ext());
334 if (strlen(ffs[sel]) >= (size_t)ff_maxlen)
336 gmx_fatal(FARGS,"Length of force field name (%d) >= maxlen (%d)",
337 strlen(ffs[sel]),ff_maxlen);
339 strcpy(forcefield,ffs[sel]);
341 if (strlen(ffdirs[sel]) >= (size_t)ffdir_maxlen)
343 gmx_fatal(FARGS,"Length of force field dir (%d) >= maxlen (%d)",
344 strlen(ffdirs[sel]),ffdir_maxlen);
346 strcpy(ffdir,ffdirs[sel]);
348 for(i=0; (i<nff); i++)
359 void choose_watermodel(const char *wmsel,const char *ffdir,
362 const char *fn_watermodels="watermodels.dat";
363 char fn_list[STRLEN];
370 if (strcmp(wmsel,"none") == 0)
376 else if (strcmp(wmsel,"select") != 0)
378 *watermodel = strdup(wmsel);
383 sprintf(fn_list,"%s%c%s",ffdir,DIR_SEPARATOR,fn_watermodels);
385 if (!fflib_fexist(fn_list))
387 fprintf(stderr,"No file '%s' found, will not include a water model\n",
394 fp = fflib_open(fn_list);
395 printf("\nSelect the Water Model:\n");
398 while (get_a_line(fp,buf,STRLEN))
401 snew(model[nwm],STRLEN);
402 sscanf(buf,"%s%n",model[nwm],&i);
406 fprintf(stderr,"%2d: %s\n",nwm+1,buf+i);
415 fprintf(stderr,"%2d: %s\n",nwm+1,"None");
419 pret = fgets(buf,STRLEN,stdin);
423 sscanf(buf,"%d",&sel);
427 while (pret == NULL || sel < 0 || sel > nwm);
435 *watermodel = strdup(model[sel]);
445 static int name2type(t_atoms *at, int **cgnr, gpp_atomtype_t atype,
446 t_restp restp[], gmx_residuetype_t rt)
448 int i,j,prevresind,resind,i0,prevcg,cg,curcg;
450 gmx_bool bProt, bNterm;
467 for(i=0; (i<at->nr); i++) {
469 if (at->atom[i].resind != resind) {
470 resind = at->atom[i].resind;
471 bProt = gmx_residuetype_is_protein(rt,*(at->resinfo[resind].name));
472 bNterm=bProt && (resind == 0);
474 nmissat += missing_atoms(&restp[prevresind],prevresind,at,i0,i);
478 if (at->atom[i].m == 0) {
480 fprintf(debug,"atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
481 i+1,*(at->atomname[i]),curcg,prevcg,
482 j==NOTSET ? NOTSET : restp[resind].cgnr[j]);
485 name=*(at->atomname[i]);
486 j=search_jtype(&restp[resind],name,bNterm);
487 at->atom[i].type = restp[resind].atom[j].type;
488 at->atom[i].q = restp[resind].atom[j].q;
489 at->atom[i].m = get_atomtype_massA(restp[resind].atom[j].type,
491 cg = restp[resind].cgnr[j];
492 /* A charge group number -1 signals a separate charge group
495 if ( (cg == -1) || (cg != prevcg) || (resind != prevresind) ) {
500 fprintf(debug,"atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
501 i+1,*(at->atomname[i]),curcg,qt,is_int(qt));
510 at->atom[i].typeB = at->atom[i].type;
511 at->atom[i].qB = at->atom[i].q;
512 at->atom[i].mB = at->atom[i].m;
514 nmissat += missing_atoms(&restp[resind],resind,at,i0,i);
519 static void print_top_heavy_H(FILE *out, real mHmult)
522 fprintf(out,"; Using deuterium instead of hydrogen\n\n");
523 else if (mHmult == 4.0)
524 fprintf(out,"#define HEAVY_H\n\n");
525 else if (mHmult != 1.0)
526 fprintf(stderr,"WARNING: unsupported proton mass multiplier (%g) "
527 "in pdb2top\n",mHmult);
530 void print_top_comment(FILE *out,
531 const char *filename,
532 const char *generator,
537 char ffdir_parent[STRLEN];
540 nice_header(out,filename);
541 fprintf(out,";\tThis is a %s topology file\n;\n",bITP ? "include" : "standalone");
542 fprintf(out,";\tIt was generated using program:\n;\t%s\n;\n",
543 (NULL == generator) ? "unknown" : generator);
544 fprintf(out,";\tCommand line was:\n;\t%s\n;\n",command_line());
546 if(strchr(ffdir,'/')==NULL)
548 fprintf(out,";\tForce field was read from the standard Gromacs share directory.\n;\n\n");
550 else if(ffdir[0]=='.')
552 fprintf(out,";\tForce field was read from current directory or a relative path - path added.\n;\n\n");
556 strncpy(ffdir_parent,ffdir,STRLEN-1);
557 ffdir_parent[STRLEN-1]='\0'; /*make sure it is 0-terminated even for long string*/
558 p=strrchr(ffdir_parent,'/');
563 ";\tForce field data was read from:\n"
567 ";\tThis might be a non-standard force field location. When you use this topology, the\n"
568 ";\tforce field must either be present in the current directory, or the location\n"
569 ";\tspecified in the GMXLIB path variable or with the 'include' mdp file option.\n;\n\n",
574 void print_top_header(FILE *out,const char *filename,
575 const char *title,gmx_bool bITP,const char *ffdir,real mHmult)
579 print_top_comment(out,filename,title,ffdir,bITP);
581 print_top_heavy_H(out, mHmult);
582 fprintf(out,"; Include forcefield parameters\n");
584 p=strrchr(ffdir,'/');
585 p = (ffdir[0]=='.' || p==NULL) ? ffdir : p+1;
587 fprintf(out,"#include \"%s/%s\"\n\n",p,fflib_forcefield_itp());
590 static void print_top_posre(FILE *out,const char *pr)
592 fprintf(out,"; Include Position restraint file\n");
593 fprintf(out,"#ifdef POSRES\n");
594 fprintf(out,"#include \"%s\"\n",pr);
595 fprintf(out,"#endif\n\n");
598 static void print_top_water(FILE *out,const char *ffdir,const char *water)
603 fprintf(out,"; Include water topology\n");
605 p=strrchr(ffdir,'/');
606 p = (ffdir[0]=='.' || p==NULL) ? ffdir : p+1;
607 fprintf(out,"#include \"%s/%s.itp\"\n",p,water);
610 fprintf(out,"#ifdef POSRES_WATER\n");
611 fprintf(out,"; Position restraint for each water oxygen\n");
612 fprintf(out,"[ position_restraints ]\n");
613 fprintf(out,";%3s %5s %9s %10s %10s\n","i","funct","fcx","fcy","fcz");
614 fprintf(out,"%4d %4d %10g %10g %10g\n",1,1,1000.0,1000.0,1000.0);
615 fprintf(out,"#endif\n");
618 sprintf(buf,"%s/ions.itp",p);
620 if (fflib_fexist(buf))
622 fprintf(out,"; Include topology for ions\n");
623 fprintf(out,"#include \"%s\"\n",buf);
628 static void print_top_system(FILE *out, const char *title)
630 fprintf(out,"[ %s ]\n",dir2str(d_system));
631 fprintf(out,"; Name\n");
632 fprintf(out,"%s\n\n",title[0]?title:"Protein");
635 void print_top_mols(FILE *out,
636 const char *title, const char *ffdir, const char *water,
637 int nincl, char **incls, int nmol, t_mols *mols)
643 fprintf(out,"; Include chain topologies\n");
644 for (i=0; (i<nincl); i++) {
645 incl = strrchr(incls[i],DIR_SEPARATOR);
649 /* Remove the path from the include name */
652 fprintf(out,"#include \"%s\"\n",incl);
659 print_top_water(out,ffdir,water);
661 print_top_system(out, title);
664 fprintf(out,"[ %s ]\n",dir2str(d_molecules));
665 fprintf(out,"; %-15s %5s\n","Compound","#mols");
666 for (i=0; (i<nmol); i++)
667 fprintf(out,"%-15s %5d\n",mols[i].name,mols[i].nr);
671 void write_top(FILE *out, char *pr,char *molname,
672 t_atoms *at,gmx_bool bRTPresname,
673 int bts[],t_params plist[],t_excls excls[],
674 gpp_atomtype_t atype,int *cgnr, int nrexcl)
675 /* NOTE: nrexcl is not the size of *excl! */
677 if (at && atype && cgnr) {
678 fprintf(out,"[ %s ]\n",dir2str(d_moleculetype));
679 fprintf(out,"; %-15s %5s\n","Name","nrexcl");
680 fprintf(out,"%-15s %5d\n\n",molname?molname:"Protein",nrexcl);
682 print_atoms(out, atype, at, cgnr, bRTPresname);
683 print_bondeds(out,at->nr,d_bonds, F_BONDS, bts[ebtsBONDS], plist);
684 print_bondeds(out,at->nr,d_constraints,F_CONSTR, 0, plist);
685 print_bondeds(out,at->nr,d_constraints,F_CONSTRNC, 0, plist);
686 print_bondeds(out,at->nr,d_pairs, F_LJ14, 0, plist);
687 print_excl(out,at->nr,excls);
688 print_bondeds(out,at->nr,d_angles, F_ANGLES, bts[ebtsANGLES],plist);
689 print_bondeds(out,at->nr,d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist);
690 print_bondeds(out,at->nr,d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist);
691 print_bondeds(out,at->nr,d_cmap, F_CMAP, bts[ebtsCMAP], plist);
692 print_bondeds(out,at->nr,d_polarization,F_POLARIZATION, 0, plist);
693 print_bondeds(out,at->nr,d_thole_polarization,F_THOLE_POL,0, plist);
694 print_bondeds(out,at->nr,d_vsites2, F_VSITE2, 0, plist);
695 print_bondeds(out,at->nr,d_vsites3, F_VSITE3, 0, plist);
696 print_bondeds(out,at->nr,d_vsites3, F_VSITE3FD, 0, plist);
697 print_bondeds(out,at->nr,d_vsites3, F_VSITE3FAD,0, plist);
698 print_bondeds(out,at->nr,d_vsites3, F_VSITE3OUT,0, plist);
699 print_bondeds(out,at->nr,d_vsites4, F_VSITE4FD, 0, plist);
700 print_bondeds(out,at->nr,d_vsites4, F_VSITE4FDN, 0, plist);
703 print_top_posre(out,pr);
707 static atom_id search_res_atom(const char *type,int resind,
709 const char *bondtype,gmx_bool bAllowMissing)
713 for(i=0; (i<atoms->nr); i++)
715 if (atoms->atom[i].resind == resind)
717 return search_atom(type,i,atoms,bondtype,bAllowMissing);
724 static void do_ssbonds(t_params *ps,t_atoms *atoms,
725 int nssbonds,t_ssbond *ssbonds,gmx_bool bAllowMissing)
730 for(i=0; (i<nssbonds); i++) {
731 ri = ssbonds[i].res1;
732 rj = ssbonds[i].res2;
733 ai = search_res_atom(ssbonds[i].a1,ri,atoms,
734 "special bond",bAllowMissing);
735 aj = search_res_atom(ssbonds[i].a2,rj,atoms,
736 "special bond",bAllowMissing);
737 if ((ai == NO_ATID) || (aj == NO_ATID))
738 gmx_fatal(FARGS,"Trying to make impossible special bond (%s-%s)!",
739 ssbonds[i].a1,ssbonds[i].a2);
740 add_param(ps,ai,aj,NULL,NULL);
744 static void at2bonds(t_params *psb, t_hackblock *hb,
747 real long_bond_dist, real short_bond_dist,
748 gmx_bool bAllowMissing)
752 real dist2, long_bond_dist2, short_bond_dist2;
755 long_bond_dist2 = sqr(long_bond_dist);
756 short_bond_dist2 = sqr(short_bond_dist);
763 fprintf(stderr,"Making bonds...\n");
765 for(resind=0; (resind < atoms->nres) && (i<atoms->nr); resind++) {
766 /* add bonds from list of bonded interactions */
767 for(j=0; j < hb[resind].rb[ebtsBONDS].nb; j++) {
768 /* Unfortunately we can not issue errors or warnings
769 * for missing atoms in bonds, as the hydrogens and terminal atoms
770 * have not been added yet.
772 ai=search_atom(hb[resind].rb[ebtsBONDS].b[j].AI,i,atoms,
774 aj=search_atom(hb[resind].rb[ebtsBONDS].b[j].AJ,i,atoms,
776 if (ai != NO_ATID && aj != NO_ATID) {
777 dist2 = distance2(x[ai],x[aj]);
778 if (dist2 > long_bond_dist2 )
780 fprintf(stderr,"Warning: Long Bond (%d-%d = %g nm)\n",
781 ai+1,aj+1,sqrt(dist2));
783 else if (dist2 < short_bond_dist2 )
785 fprintf(stderr,"Warning: Short Bond (%d-%d = %g nm)\n",
786 ai+1,aj+1,sqrt(dist2));
788 add_param(psb,ai,aj,NULL,hb[resind].rb[ebtsBONDS].b[j].s);
791 /* add bonds from list of hacks (each added atom gets a bond) */
792 while( (i<atoms->nr) && (atoms->atom[i].resind == resind) ) {
793 for(j=0; j < hb[resind].nhack; j++)
794 if ( ( hb[resind].hack[j].tp > 0 ||
795 hb[resind].hack[j].oname==NULL ) &&
796 strcmp(hb[resind].hack[j].AI,*(atoms->atomname[i])) == 0 ) {
797 switch(hb[resind].hack[j].tp) {
798 case 9: /* COOH terminus */
799 add_param(psb,i,i+1,NULL,NULL); /* C-O */
800 add_param(psb,i,i+2,NULL,NULL); /* C-OA */
801 add_param(psb,i+2,i+3,NULL,NULL); /* OA-H */
804 for(k=0; (k<hb[resind].hack[j].nr); k++)
805 add_param(psb,i,i+k+1,NULL,NULL);
810 /* we're now at the start of the next residue */
814 static int pcompar(const void *a, const void *b)
825 return strlen(pb->s) - strlen(pa->s);
830 static void clean_bonds(t_params *ps)
836 /* swap atomnumbers in bond if first larger than second: */
837 for(i=0; (i<ps->nr); i++)
838 if ( ps->param[i].AJ < ps->param[i].AI ) {
840 ps->param[i].AI = ps->param[i].AJ;
845 qsort(ps->param,ps->nr,(size_t)sizeof(ps->param[0]),pcompar);
847 /* remove doubles, keep the first one always. */
849 for(i=1; (i<ps->nr); i++) {
850 if ((ps->param[i].AI != ps->param[j-1].AI) ||
851 (ps->param[i].AJ != ps->param[j-1].AJ) ) {
853 cp_param(&(ps->param[j]),&(ps->param[i]));
858 fprintf(stderr,"Number of bonds was %d, now %d\n",ps->nr,j);
862 fprintf(stderr,"No bonds\n");
865 void print_sums(t_atoms *atoms, gmx_bool bSystem)
878 for(i=0; (i<atoms->nr); i++) {
880 qtot+=atoms->atom[i].q;
883 fprintf(stderr,"Total mass%s %.3f a.m.u.\n",where,m);
884 fprintf(stderr,"Total charge%s %.3f e\n",where,qtot);
887 static void check_restp_type(const char *name,int t1,int t2)
891 gmx_fatal(FARGS,"Residues in one molecule have a different '%s' type: %d and %d",name,t1,t2);
895 static void check_restp_types(t_restp *r0,t_restp *r1)
899 check_restp_type("all dihedrals",r0->bKeepAllGeneratedDihedrals,r1->bKeepAllGeneratedDihedrals);
900 check_restp_type("nrexcl",r0->nrexcl,r1->nrexcl);
901 check_restp_type("HH14",r0->bGenerateHH14Interactions,r1->bGenerateHH14Interactions);
902 check_restp_type("remove dihedrals",r0->bRemoveDihedralIfWithImproper,r1->bRemoveDihedralIfWithImproper);
904 for(i=0; i<ebtsNR; i++)
906 check_restp_type(btsNames[i],r0->rb[i].type,r1->rb[i].type);
910 void add_atom_to_restp(t_restp *restp,int resnr,int at_start,const t_hack *hack)
914 const char *Hnum="123456";
918 fprintf(debug,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
920 *restp->atomname[at_start], resnr, restp->resname);
922 strcpy(buf, hack->nname);
923 buf[strlen(buf)+1]='\0';
926 buf[strlen(buf)]='-';
929 restp->natom += hack->nr;
930 srenew(restp->atom, restp->natom);
931 srenew(restp->atomname, restp->natom);
932 srenew(restp->cgnr, restp->natom);
934 for(k=restp->natom-1; k > at_start+hack->nr; k--)
937 restp->atom [k - hack->nr];
939 restp->atomname[k - hack->nr];
941 restp->cgnr [k - hack->nr];
944 for(k=0; k < hack->nr; k++)
946 /* set counter in atomname */
949 buf[strlen(buf)-1] = Hnum[k];
951 snew( restp->atomname[at_start+1+k], 1);
952 restp->atom [at_start+1+k] = *hack->atom;
953 *restp->atomname[at_start+1+k] = strdup(buf);
954 if ( hack->cgnr != NOTSET )
956 restp->cgnr [at_start+1+k] = hack->cgnr;
960 restp->cgnr [at_start+1+k] = restp->cgnr[at_start];
965 void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
966 int nrtp, t_restp rtp[],
967 int nres, t_resinfo *resinfo,
969 t_hackblock **ntdb, t_hackblock **ctdb,
976 const char *Hnum="123456";
982 /* first the termini */
983 for(i=0; i<nterpairs; i++) {
984 if (rn[i] >= 0 && ntdb[i] != NULL) {
985 copy_t_hackblock(ntdb[i], &(*hb)[rn[i]]);
987 if (rc[i] >= 0 && ctdb[i] != NULL) {
988 merge_t_hackblock(ctdb[i], &(*hb)[rc[i]]);
992 /* then the whole rtp */
993 for(i=0; i < nres; i++) {
994 /* Here we allow a mismatch of one character when looking for the rtp entry.
995 * For such a mismatch there should be only one mismatching name.
996 * This is mainly useful for small molecules such as ions.
997 * Note that this will usually not work for protein, DNA and RNA,
998 * since there the residue names should be listed in residuetypes.dat
999 * and an error will have been generated earlier in the process.
1001 key = *resinfo[i].rtp;
1002 snew(resinfo[i].rtp,1);
1003 *resinfo[i].rtp = search_rtp(key,nrtp,rtp);
1004 res = get_restp(*resinfo[i].rtp,nrtp,rtp);
1005 copy_t_restp(res, &(*restp)[i]);
1007 /* Check that we do not have different bonded types in one molecule */
1008 check_restp_types(&(*restp)[0],&(*restp)[i]);
1011 for(j=0; j<nterpairs && tern==-1; j++) {
1017 for(j=0; j<nterpairs && terc == -1; j++) {
1022 bRM = merge_t_bondeds(res->rb, (*hb)[i].rb,tern>=0,terc>=0);
1024 if (bRM && ((tern >= 0 && ntdb[tern] == NULL) ||
1025 (terc >= 0 && ctdb[terc] == NULL))) {
1026 gmx_fatal(FARGS,"There is a dangling bond at at least one of the terminal ends and the force field does not provide terminal entries or files. Fix your terminal residues so that they match the residue database (.rtp) entries, or provide terminal database entries (.tdb).");
1028 if (bRM && ((tern >= 0 && ntdb[tern]->nhack == 0) ||
1029 (terc >= 0 && ctdb[terc]->nhack == 0))) {
1030 gmx_fatal(FARGS,"There is a dangling bond at at least one of the terminal ends. Fix your coordinate file, add a new terminal database entry (.tdb), or select the proper existing terminal entry.");
1034 /* now perform t_hack's on t_restp's,
1035 i.e. add's and deletes from termini database will be
1036 added to/removed from residue topology
1037 we'll do this on one big dirty loop, so it won't make easy reading! */
1038 for(i=0; i < nres; i++)
1040 for(j=0; j < (*hb)[i].nhack; j++)
1042 if ( (*hb)[i].hack[j].nr )
1044 /* find atom in restp */
1045 for(l=0; l < (*restp)[i].natom; l++)
1046 if ( ( (*hb)[i].hack[j].oname==NULL &&
1047 strcmp((*hb)[i].hack[j].AI, *(*restp)[i].atomname[l])==0 ) ||
1048 ( (*hb)[i].hack[j].oname!=NULL &&
1049 strcmp((*hb)[i].hack[j].oname,*(*restp)[i].atomname[l])==0 ) )
1051 if (l == (*restp)[i].natom)
1053 /* If we are doing an atom rename only, we don't need
1054 * to generate a fatal error if the old name is not found
1057 /* Deleting can happen also only on the input atoms,
1058 * not necessarily always on the rtp entry.
1060 if (!((*hb)[i].hack[j].oname != NULL &&
1061 (*hb)[i].hack[j].nname != NULL) &&
1062 !((*hb)[i].hack[j].oname != NULL &&
1063 (*hb)[i].hack[j].nname == NULL))
1066 "atom %s not found in buiding block %d%s "
1067 "while combining tdb and rtp",
1068 (*hb)[i].hack[j].oname!=NULL ?
1069 (*hb)[i].hack[j].oname : (*hb)[i].hack[j].AI,
1070 i+1,*resinfo[i].rtp);
1075 if ( (*hb)[i].hack[j].oname==NULL ) {
1077 add_atom_to_restp(&(*restp)[i],resinfo[i].nr,l,
1083 if ( (*hb)[i].hack[j].nname==NULL ) {
1084 /* we're deleting */
1086 fprintf(debug, "deleting atom %s from res %d%s in rtp\n",
1087 *(*restp)[i].atomname[l],
1088 i+1,(*restp)[i].resname);
1089 /* shift the rest */
1090 (*restp)[i].natom--;
1091 for(k=l; k < (*restp)[i].natom; k++) {
1092 (*restp)[i].atom [k] = (*restp)[i].atom [k+1];
1093 (*restp)[i].atomname[k] = (*restp)[i].atomname[k+1];
1094 (*restp)[i].cgnr [k] = (*restp)[i].cgnr [k+1];
1096 /* give back space */
1097 srenew((*restp)[i].atom, (*restp)[i].natom);
1098 srenew((*restp)[i].atomname, (*restp)[i].natom);
1099 srenew((*restp)[i].cgnr, (*restp)[i].natom);
1100 } else { /* nname != NULL */
1101 /* we're replacing */
1103 fprintf(debug, "replacing atom %s by %s in res %d%s in rtp\n",
1104 *(*restp)[i].atomname[l], (*hb)[i].hack[j].nname,
1105 i+1,(*restp)[i].resname);
1106 snew( (*restp)[i].atomname[l], 1);
1107 (*restp)[i].atom[l] = *(*hb)[i].hack[j].atom;
1108 *(*restp)[i].atomname[l] = strdup((*hb)[i].hack[j].nname);
1109 if ( (*hb)[i].hack[j].cgnr != NOTSET )
1110 (*restp)[i].cgnr [l] = (*hb)[i].hack[j].cgnr;
1119 static gmx_bool atomname_cmp_nr(const char *anm,t_hack *hack,int *nr)
1126 return (gmx_strcasecmp(anm,hack->nname) == 0);
1130 if (isdigit(anm[strlen(anm)-1]))
1132 *nr = anm[strlen(anm)-1] - '0';
1138 if (*nr <= 0 || *nr > hack->nr)
1144 return (strlen(anm) == strlen(hack->nname) + 1 &&
1145 gmx_strncasecmp(anm,hack->nname,strlen(hack->nname)) == 0);
1150 static gmx_bool match_atomnames_with_rtp_atom(t_atoms *pdba,rvec *x,int atind,
1151 t_restp *rptr,t_hackblock *hbr,
1158 char *start_at,buf[STRLEN];
1160 gmx_bool bReplaceReplace,bFoundInAdd;
1163 oldnm = *pdba->atomname[atind];
1164 resnr = pdba->resinfo[pdba->atom[atind].resind].nr;
1167 for(j=0; j<hbr->nhack; j++)
1169 if (hbr->hack[j].oname != NULL && hbr->hack[j].nname != NULL &&
1170 gmx_strcasecmp(oldnm,hbr->hack[j].oname) == 0)
1172 /* This is a replace entry. */
1173 /* Check if we are not replacing a replaced atom. */
1174 bReplaceReplace = FALSE;
1175 for(k=0; k<hbr->nhack; k++) {
1177 hbr->hack[k].oname != NULL && hbr->hack[k].nname != NULL &&
1178 gmx_strcasecmp(hbr->hack[k].nname,hbr->hack[j].oname) == 0)
1180 /* The replace in hack[j] replaces an atom that
1181 * was already replaced in hack[k], we do not want
1182 * second or higher level replaces at this stage.
1184 bReplaceReplace = TRUE;
1187 if (bReplaceReplace)
1189 /* Skip this replace. */
1193 /* This atom still has the old name, rename it */
1194 newnm = hbr->hack[j].nname;
1195 for(k=0; k<rptr->natom; k++)
1197 if (gmx_strcasecmp(newnm,*rptr->atomname[k]) == 0)
1202 if (k == rptr->natom)
1204 /* The new name is not present in the rtp.
1205 * We need to apply the replace also to the rtp entry.
1208 /* We need to find the add hack that can add this atom
1209 * to find out after which atom it should be added.
1211 bFoundInAdd = FALSE;
1212 for(k=0; k<hbr->nhack; k++)
1214 if (hbr->hack[k].oname == NULL &&
1215 hbr->hack[k].nname != NULL &&
1216 atomname_cmp_nr(newnm,&hbr->hack[k],&anmnr))
1220 start_at = hbr->hack[k].a[0];
1224 sprintf(buf,"%s%d",hbr->hack[k].nname,anmnr-1);
1227 for(start_nr=0; start_nr<rptr->natom; start_nr++)
1229 if (gmx_strcasecmp(start_at,(*rptr->atomname[start_nr])) == 0)
1234 if (start_nr == rptr->natom)
1236 gmx_fatal(FARGS,"Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1237 start_at,rptr->resname,newnm);
1239 /* We can add the atom after atom start_nr */
1240 add_atom_to_restp(rptr,resnr,start_nr,
1249 gmx_fatal(FARGS,"Could not find an 'add' entry for atom named '%s' corresponding to the 'replace' entry from atom name '%s' to '%s' for tdb or hdb database of residue type '%s'",
1251 hbr->hack[j].oname,hbr->hack[j].nname,
1258 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1259 oldnm,rptr->resname,resnr,newnm);
1261 /* Rename the atom in pdba */
1262 snew(pdba->atomname[atind],1);
1263 *pdba->atomname[atind] = strdup(newnm);
1265 else if (hbr->hack[j].oname != NULL && hbr->hack[j].nname == NULL &&
1266 gmx_strcasecmp(oldnm,hbr->hack[j].oname) == 0)
1268 /* This is a delete entry, check if this atom is present
1269 * in the rtp entry of this residue.
1271 for(k=0; k<rptr->natom; k++)
1273 if (gmx_strcasecmp(oldnm,*rptr->atomname[k]) == 0)
1278 if (k == rptr->natom)
1280 /* This atom is not present in the rtp entry,
1281 * delete is now from the input pdba.
1285 printf("Deleting atom '%s' in residue '%s' %d\n",
1286 oldnm,rptr->resname,resnr);
1288 /* We should free the atom name,
1289 * but it might be used multiple times in the symtab.
1290 * sfree(pdba->atomname[atind]);
1292 for(k=atind+1; k<pdba->nr; k++)
1294 pdba->atom[k-1] = pdba->atom[k];
1295 pdba->atomname[k-1] = pdba->atomname[k];
1296 copy_rvec(x[k],x[k-1]);
1307 void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
1308 t_atoms *pdba,rvec *x,
1317 char *start_at,buf[STRLEN];
1319 gmx_bool bFoundInAdd;
1321 for(i=0; i<pdba->nr; i++)
1323 oldnm = *pdba->atomname[i];
1324 resnr = pdba->resinfo[pdba->atom[i].resind].nr;
1325 rptr = &restp[pdba->atom[i].resind];
1326 for(j=0; (j<rptr->natom); j++)
1328 if (gmx_strcasecmp(oldnm,*(rptr->atomname[j])) == 0)
1333 if (j == rptr->natom)
1335 /* Not found yet, check if we have to rename this atom */
1336 if (match_atomnames_with_rtp_atom(pdba,x,i,
1337 rptr,&(hb[pdba->atom[i].resind]),
1340 /* We deleted this atom, decrease the atom counter by 1. */
1347 #define NUM_CMAP_ATOMS 5
1348 static void gen_cmap(t_params *psb, t_restp *restp, t_atoms *atoms, gmx_residuetype_t rt)
1352 t_resinfo *resinfo = atoms->resinfo;
1353 int nres = atoms->nres;
1355 atom_id cmap_atomid[NUM_CMAP_ATOMS];
1356 int cmap_chainnum=-1, this_residue_index;
1363 fprintf(stderr,"Making cmap torsions...");
1365 /* End loop at nres-1, since the very last residue does not have a +N atom, and
1366 * therefore we get a valgrind invalid 4 byte read error with atom am */
1367 for(residx=0; residx<nres-1; residx++)
1369 /* Add CMAP terms from the list of CMAP interactions */
1370 for(j=0;j<restp[residx].rb[ebtsCMAP].nb; j++)
1373 /* Loop over atoms in a candidate CMAP interaction and
1374 * check that they exist, are from the same chain and are
1375 * from residues labelled as protein. */
1376 for(k = 0; k < NUM_CMAP_ATOMS && bAddCMAP; k++)
1378 cmap_atomid[k] = search_atom(restp[residx].rb[ebtsCMAP].b[j].a[k],
1380 bAddCMAP = bAddCMAP && (cmap_atomid[k] != NO_ATID);
1383 /* This break is necessary, because cmap_atomid[k]
1384 * == NO_ATID cannot be safely used as an index
1385 * into the atom array. */
1388 this_residue_index = atoms->atom[cmap_atomid[k]].resind;
1391 cmap_chainnum = resinfo[this_residue_index].chainnum;
1395 /* Does the residue for this atom have the same
1396 * chain number as the residues for previous
1398 bAddCMAP = bAddCMAP &&
1399 cmap_chainnum == resinfo[this_residue_index].chainnum;
1401 bAddCMAP = bAddCMAP && gmx_residuetype_is_protein(rt,*(resinfo[this_residue_index].name));
1406 add_cmap_param(psb,cmap_atomid[0],cmap_atomid[1],cmap_atomid[2],cmap_atomid[3],cmap_atomid[4],restp[residx].rb[ebtsCMAP].b[j].s);
1412 while(atoms->atom[i].resind<residx+1)
1419 /* Start the next residue */
1423 scrub_charge_groups(int *cgnr, int natoms)
1427 for(i=0;i<natoms;i++)
1434 void pdb2top(FILE *top_file, char *posre_fn, char *molname,
1435 t_atoms *atoms, rvec **x, gpp_atomtype_t atype, t_symtab *tab,
1436 int nrtp, t_restp rtp[],
1437 t_restp *restp, t_hackblock *hb,
1438 int nterpairs,t_hackblock **ntdb, t_hackblock **ctdb,
1439 gmx_bool bAllowMissing,
1440 gmx_bool bVsites, gmx_bool bVsiteAromatics,
1441 const char *ff, const char *ffdir,
1443 int nssbonds, t_ssbond *ssbonds,
1444 real long_bond_dist, real short_bond_dist,
1445 gmx_bool bDeuterate, gmx_bool bChargeGroups, gmx_bool bCmap,
1446 gmx_bool bRenumRes,gmx_bool bRTPresname)
1452 t_params plist[F_NRE];
1459 gmx_residuetype_t rt;
1462 gmx_residuetype_init(&rt);
1465 print_resall(debug, atoms->nres, restp, atype);
1466 dump_hb(debug, atoms->nres, hb);
1470 at2bonds(&(plist[F_BONDS]), hb,
1472 long_bond_dist, short_bond_dist, bAllowMissing);
1474 /* specbonds: disulphide bonds & heme-his */
1475 do_ssbonds(&(plist[F_BONDS]),
1476 atoms, nssbonds, ssbonds,
1479 nmissat = name2type(atoms, &cgnr, atype, restp, rt);
1482 fprintf(stderr,"There were %d missing atoms in molecule %s\n",
1485 gmx_fatal(FARGS,"There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1489 /* Cleanup bonds (sort and rm doubles) */
1490 clean_bonds(&(plist[F_BONDS]));
1492 snew(vsite_type,atoms->nr);
1493 for(i=0; i<atoms->nr; i++)
1494 vsite_type[i]=NOTSET;
1496 /* determine which atoms will be vsites and add dummy masses
1497 also renumber atom numbers in plist[0..F_NRE]! */
1498 do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
1499 &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
1502 /* Make Angles and Dihedrals */
1503 fprintf(stderr,"Generating angles, dihedrals and pairs...\n");
1504 snew(excls,atoms->nr);
1505 init_nnb(&nnb,atoms->nr,4);
1506 gen_nnb(&nnb,plist);
1507 print_nnb(&nnb,"NNB");
1508 gen_pad(&nnb,atoms,restp,plist,excls,hb,bAllowMissing);
1514 gen_cmap(&(plist[F_CMAP]), restp, atoms, rt);
1515 if (plist[F_CMAP].nr > 0)
1517 fprintf(stderr, "There are %4d cmap torsion pairs\n",
1522 /* set mass of all remaining hydrogen atoms */
1524 do_h_mass(&(plist[F_BONDS]),vsite_type,atoms,mHmult,bDeuterate);
1527 /* Cleanup bonds (sort and rm doubles) */
1528 /* clean_bonds(&(plist[F_BONDS]));*/
1531 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1532 " %4d pairs, %4d bonds and %4d virtual sites\n",
1533 plist[F_PDIHS].nr, plist[F_IDIHS].nr, plist[F_ANGLES].nr,
1534 plist[F_LJ14].nr, plist[F_BONDS].nr,
1535 plist[F_VSITE2].nr +
1536 plist[F_VSITE3].nr +
1537 plist[F_VSITE3FD].nr +
1538 plist[F_VSITE3FAD].nr +
1539 plist[F_VSITE3OUT].nr +
1540 plist[F_VSITE4FD].nr +
1541 plist[F_VSITE4FDN].nr );
1543 print_sums(atoms, FALSE);
1545 if (FALSE == bChargeGroups)
1547 scrub_charge_groups(cgnr, atoms->nr);
1552 for(i=0; i<atoms->nres; i++)
1554 atoms->resinfo[i].nr = i + 1;
1555 atoms->resinfo[i].ic = ' ';
1560 fprintf(stderr,"Writing topology\n");
1561 /* We can copy the bonded types from the first restp,
1562 * since the types have to be identical for all residues in one molecule.
1564 for(i=0; i<ebtsNR; i++) {
1565 bts[i] = restp[0].rb[i].type;
1567 write_top(top_file, posre_fn, molname,
1569 bts, plist, excls, atype, cgnr, restp[0].nrexcl);
1573 free_t_hackblock(atoms->nres, &hb);
1574 free_t_restp(atoms->nres, &restp);
1575 gmx_residuetype_destroy(rt);
1577 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1579 for (i=0; i<F_NRE; i++)
1580 sfree(plist[i].param);
1581 for (i=0; i<atoms->nr; i++)