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
50 #include "gmx_fatal.h"
52 #include "gpp_nextnb.h"
65 #include "gen_vsite.h"
68 #include "fflibutil.h"
71 /* this must correspond to enum in pdb2top.h */
72 const char *hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
74 static int missing_atoms(t_restp *rp, int resind,t_atoms *at, int i0, int i)
78 gmx_bool bFound, bRet;
81 for (j=0; j<rp->natom; j++)
83 name=*(rp->atomname[j]);
87 bFound = (bFound || !gmx_strcasecmp(*(at->atomname[k]),name));
92 fprintf(stderr,"\nWARNING: "
93 "atom %s is missing in residue %s %d in the pdb file\n",
94 name,*(at->resinfo[resind].name),at->resinfo[resind].nr);
95 if (name[0]=='H' || name[0]=='h')
97 fprintf(stderr," You might need to add atom %s to the hydrogen database of building block %s\n"
98 " in the file %s.hdb (see the manual)\n",
99 name,*(at->resinfo[resind].rtp),rp->filebase);
101 fprintf(stderr,"\n");
108 gmx_bool is_int(double x)
110 const double tol = 1e-4;
117 return (fabs(x-ix) < tol);
120 static void swap_strings(char **s,int i,int j)
130 choose_ff(const char *ffsel,
131 char *forcefield, int ff_maxlen,
132 char *ffdir, int ffdir_maxlen)
135 char **ffdirs,**ffs,**ffs_dir,*ptr;
137 char buf[STRLEN],**desc;
141 nff = fflib_search_file_in_dirend(fflib_forcefield_itp(),
142 fflib_forcefield_dir_ext(),
147 gmx_fatal(FARGS,"No force fields found (files with name '%s' in subdirectories ending on '%s')",
148 fflib_forcefield_itp(),fflib_forcefield_dir_ext());
151 /* Store the force field names in ffs */
156 /* Remove the path from the ffdir name */
157 ptr = strrchr(ffdirs[i],DIR_SEPARATOR);
160 ffs[i] = strdup(ffdirs[i]);
161 ffs_dir[i] = low_gmxlibfn(ffdirs[i],FALSE,FALSE);
162 if (ffs_dir[i] == NULL)
164 gmx_fatal(FARGS,"Can no longer find file '%s'",ffdirs[i]);
169 ffs[i] = strdup(ptr+1);
170 ffs_dir[i] = strdup(ffdirs[i]);
172 ffs_dir[i][strlen(ffs_dir[i])-strlen(ffs[i])-1] = '\0';
173 /* Remove the extension from the ffdir name */
174 ffs[i][strlen(ffs[i])-strlen(fflib_forcefield_dir_ext())] = '\0';
182 if (strcmp(ffs[i],ffsel) == 0)
186 gmx_fatal(FARGS,"There are multiple force field directories in your path with the name '%s'. Run without the -ff switch and select the force field interactively.",ffsel);
193 gmx_fatal(FARGS,"Could not find force field '%s'",ffsel);
199 for(i=0; (i<nff); i++)
201 sprintf(buf,"%s%c%s%s%c%s",
202 ffs_dir[i],DIR_SEPARATOR,
203 ffs[i],fflib_forcefield_dir_ext(),DIR_SEPARATOR,
204 fflib_forcefield_doc());
207 /* We don't use fflib_open, because we don't want printf's */
208 fp = ffopen(buf,"r");
209 snew(desc[i],STRLEN);
210 get_a_line(fp,desc[i],STRLEN);
215 desc[i] = strdup(ffs[i]);
218 /* Order force fields from the same dir alphabetically
219 * and put deprecated force fields at the end.
221 for(i=0; (i<nff); i++)
223 for(j=i+1; (j<nff); j++)
225 if (strcmp(ffs_dir[i],ffs_dir[j]) == 0 &&
226 ((desc[i][0] == '[' && desc[j][0] != '[') ||
227 ((desc[i][0] == '[' || desc[j][0] != '[') &&
228 gmx_strcasecmp(desc[i],desc[j]) > 0)))
230 swap_strings(ffdirs,i,j);
231 swap_strings(ffs ,i,j);
232 swap_strings(desc ,i,j);
237 printf("\nSelect the Force Field:\n");
238 for(i=0; (i<nff); i++)
240 if (i == 0 || strcmp(ffs_dir[i-1],ffs_dir[i]) != 0)
242 printf("From '%s':\n",ffs_dir[i]);
244 printf("%2d: %s\n",i+1,desc[i]);
251 pret = fgets(buf,STRLEN,stdin);
255 sscanf(buf,"%d",&sel);
259 while ( pret==NULL || (sel < 0) || (sel >= nff));
266 if (strlen(ffs[sel]) >= (size_t)ff_maxlen)
268 gmx_fatal(FARGS,"Length of force field name (%d) >= maxlen (%d)",
269 strlen(ffs[sel]),ff_maxlen);
271 strcpy(forcefield,ffs[sel]);
273 if (strlen(ffdirs[sel]) >= (size_t)ffdir_maxlen)
275 gmx_fatal(FARGS,"Length of force field dir (%d) >= maxlen (%d)",
276 strlen(ffdirs[sel]),ffdir_maxlen);
278 strcpy(ffdir,ffdirs[sel]);
280 for(i=0; (i<nff); i++)
291 void choose_watermodel(const char *wmsel,const char *ffdir,
294 const char *fn_watermodels="watermodels.dat";
295 char fn_list[STRLEN];
302 if (strcmp(wmsel,"none") == 0)
308 else if (strcmp(wmsel,"select") != 0)
310 *watermodel = strdup(wmsel);
315 sprintf(fn_list,"%s%c%s",ffdir,DIR_SEPARATOR,fn_watermodels);
317 if (!fflib_fexist(fn_list))
319 fprintf(stderr,"No file '%s' found, will not include a water model\n",
326 fp = fflib_open(fn_list);
327 printf("\nSelect the Water Model:\n");
330 while (get_a_line(fp,buf,STRLEN))
333 snew(model[nwm],STRLEN);
334 sscanf(buf,"%s%n",model[nwm],&i);
338 fprintf(stderr,"%2d: %s\n",nwm+1,buf+i);
347 fprintf(stderr,"%2d: %s\n",nwm+1,"None");
351 pret = fgets(buf,STRLEN,stdin);
355 sscanf(buf,"%d",&sel);
359 while (pret == NULL || sel < 0 || sel > nwm);
367 *watermodel = strdup(model[sel]);
377 static int name2type(t_atoms *at, int **cgnr, gpp_atomtype_t atype,
380 int i,j,prevresind,resind,i0,prevcg,cg,curcg;
382 gmx_bool bProt, bNterm;
385 gmx_residuetype_t rt;
399 gmx_residuetype_init(&rt);
401 for(i=0; (i<at->nr); i++) {
403 if (at->atom[i].resind != resind) {
404 resind = at->atom[i].resind;
405 bProt = gmx_residuetype_is_protein(rt,*(at->resinfo[resind].name));
406 bNterm=bProt && (resind == 0);
408 nmissat += missing_atoms(&restp[prevresind],prevresind,at,i0,i);
412 if (at->atom[i].m == 0) {
414 fprintf(debug,"atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
415 i+1,*(at->atomname[i]),curcg,prevcg,
416 j==NOTSET ? NOTSET : restp[resind].cgnr[j]);
419 name=*(at->atomname[i]);
420 j=search_jtype(&restp[resind],name,bNterm);
421 at->atom[i].type = restp[resind].atom[j].type;
422 at->atom[i].q = restp[resind].atom[j].q;
423 at->atom[i].m = get_atomtype_massA(restp[resind].atom[j].type,
425 cg = restp[resind].cgnr[j];
426 if ( (cg != prevcg) || (resind != prevresind) )
430 fprintf(debug,"atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
431 i+1,*(at->atomname[i]),curcg,qt,is_int(qt));
440 at->atom[i].typeB = at->atom[i].type;
441 at->atom[i].qB = at->atom[i].q;
442 at->atom[i].mB = at->atom[i].m;
444 nmissat += missing_atoms(&restp[resind],resind,at,i0,i);
446 gmx_residuetype_destroy(rt);
451 static void print_top_heavy_H(FILE *out, real mHmult)
454 fprintf(out,"; Using deuterium instead of hydrogen\n\n");
455 else if (mHmult == 4.0)
456 fprintf(out,"#define HEAVY_H\n\n");
457 else if (mHmult != 1.0)
458 fprintf(stderr,"WARNING: unsupported proton mass multiplier (%g) "
459 "in pdb2top\n",mHmult);
462 void print_top_comment(FILE *out,const char *filename,
463 const char *generator,gmx_bool bITP)
467 nice_header(out,filename);
468 fprintf(out,";\tThis is your %stopology file\n",bITP ? "include " : "");
469 fprintf(out,";\tit was generated using program:\n;\t%s\n",
470 (NULL == generator) ? "unknown" : generator);
471 fprintf(out,";\twith command line:\n;\t%s\n;\n\n",command_line());
474 void print_top_header(FILE *out,const char *filename,
475 const char *title,gmx_bool bITP,const char *ffdir,real mHmult)
477 print_top_comment(out,filename,title,bITP);
479 print_top_heavy_H(out, mHmult);
480 fprintf(out,"; Include forcefield parameters\n");
481 fprintf(out,"#include \"%s%c%s\"\n\n",
482 ffdir,DIR_SEPARATOR,fflib_forcefield_itp());
485 static void print_top_posre(FILE *out,const char *pr)
487 fprintf(out,"; Include Position restraint file\n");
488 fprintf(out,"#ifdef POSRES\n");
489 fprintf(out,"#include \"%s\"\n",pr);
490 fprintf(out,"#endif\n\n");
493 static void print_top_water(FILE *out,const char *ffdir,const char *water)
497 fprintf(out,"; Include water topology\n");
498 fprintf(out,"#include \"%s%c%s.itp\"\n",ffdir,DIR_SEPARATOR,water);
500 fprintf(out,"#ifdef POSRES_WATER\n");
501 fprintf(out,"; Position restraint for each water oxygen\n");
502 fprintf(out,"[ position_restraints ]\n");
503 fprintf(out,";%3s %5s %9s %10s %10s\n","i","funct","fcx","fcy","fcz");
504 fprintf(out,"%4d %4d %10g %10g %10g\n",1,1,1000.0,1000.0,1000.0);
505 fprintf(out,"#endif\n");
508 sprintf(buf,"%s%c%s",ffdir,DIR_SEPARATOR,"ions.itp");
509 if (fflib_fexist(buf))
511 fprintf(out,"; Include topology for ions\n");
512 fprintf(out,"#include \"%s%cions.itp\"\n",ffdir,DIR_SEPARATOR);
517 static void print_top_system(FILE *out, const char *title)
519 fprintf(out,"[ %s ]\n",dir2str(d_system));
520 fprintf(out,"; Name\n");
521 fprintf(out,"%s\n\n",title[0]?title:"Protein");
524 void print_top_mols(FILE *out,
525 const char *title, const char *ffdir, const char *water,
526 int nincl, char **incls, int nmol, t_mols *mols)
532 fprintf(out,"; Include chain topologies\n");
533 for (i=0; (i<nincl); i++) {
534 incl = strrchr(incls[i],DIR_SEPARATOR);
538 /* Remove the path from the include name */
541 fprintf(out,"#include \"%s\"\n",incl);
548 print_top_water(out,ffdir,water);
550 print_top_system(out, title);
553 fprintf(out,"[ %s ]\n",dir2str(d_molecules));
554 fprintf(out,"; %-15s %5s\n","Compound","#mols");
555 for (i=0; (i<nmol); i++)
556 fprintf(out,"%-15s %5d\n",mols[i].name,mols[i].nr);
560 void write_top(FILE *out, char *pr,char *molname,
561 t_atoms *at,gmx_bool bRTPresname,
562 int bts[],t_params plist[],t_excls excls[],
563 gpp_atomtype_t atype,int *cgnr, int nrexcl)
564 /* NOTE: nrexcl is not the size of *excl! */
566 if (at && atype && cgnr) {
567 fprintf(out,"[ %s ]\n",dir2str(d_moleculetype));
568 fprintf(out,"; %-15s %5s\n","Name","nrexcl");
569 fprintf(out,"%-15s %5d\n\n",molname?molname:"Protein",nrexcl);
571 print_atoms(out, atype, at, cgnr, bRTPresname);
572 print_bondeds(out,at->nr,d_bonds, F_BONDS, bts[ebtsBONDS], plist);
573 print_bondeds(out,at->nr,d_constraints,F_CONSTR, 0, plist);
574 print_bondeds(out,at->nr,d_constraints,F_CONSTRNC, 0, plist);
575 print_bondeds(out,at->nr,d_pairs, F_LJ14, 0, plist);
576 print_excl(out,at->nr,excls);
577 print_bondeds(out,at->nr,d_angles, F_ANGLES, bts[ebtsANGLES],plist);
578 print_bondeds(out,at->nr,d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist);
579 print_bondeds(out,at->nr,d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist);
580 print_bondeds(out,at->nr,d_cmap, F_CMAP, bts[ebtsCMAP], plist);
581 print_bondeds(out,at->nr,d_polarization,F_POLARIZATION, 0, plist);
582 print_bondeds(out,at->nr,d_thole_polarization,F_THOLE_POL,0, plist);
583 print_bondeds(out,at->nr,d_vsites2, F_VSITE2, 0, plist);
584 print_bondeds(out,at->nr,d_vsites3, F_VSITE3, 0, plist);
585 print_bondeds(out,at->nr,d_vsites3, F_VSITE3FD, 0, plist);
586 print_bondeds(out,at->nr,d_vsites3, F_VSITE3FAD,0, plist);
587 print_bondeds(out,at->nr,d_vsites3, F_VSITE3OUT,0, plist);
588 print_bondeds(out,at->nr,d_vsites4, F_VSITE4FD, 0, plist);
589 print_bondeds(out,at->nr,d_vsites4, F_VSITE4FDN, 0, plist);
592 print_top_posre(out,pr);
596 static atom_id search_res_atom(const char *type,int resind,
597 int natom,t_atom at[],
598 char ** const *aname,
599 const char *bondtype,gmx_bool bAllowMissing)
603 for(i=0; (i<natom); i++)
604 if (at[i].resind == resind)
605 return search_atom(type,i,natom,at,aname,bondtype,bAllowMissing);
610 static void do_ssbonds(t_params *ps,int natoms,t_atom atom[],char **aname[],
611 int nssbonds,t_ssbond *ssbonds,gmx_bool bAllowMissing)
616 for(i=0; (i<nssbonds); i++) {
617 ri = ssbonds[i].res1;
618 rj = ssbonds[i].res2;
619 ai = search_res_atom(ssbonds[i].a1,ri,natoms,atom,aname,
620 "special bond",bAllowMissing);
621 aj = search_res_atom(ssbonds[i].a2,rj,natoms,atom,aname,
622 "special bond",bAllowMissing);
623 if ((ai == NO_ATID) || (aj == NO_ATID))
624 gmx_fatal(FARGS,"Trying to make impossible special bond (%s-%s)!",
625 ssbonds[i].a1,ssbonds[i].a2);
626 add_param(ps,ai,aj,NULL,NULL);
630 static gmx_bool inter_res_bond(const t_rbonded *b)
632 return (b->AI[0] == '-' || b->AI[0] == '+' ||
633 b->AJ[0] == '-' || b->AJ[0] == '+');
636 static void at2bonds(t_params *psb, t_hackblock *hb,
637 int natoms, t_atom atom[], char **aname[],
639 real long_bond_dist, real short_bond_dist,
640 gmx_bool bAllowMissing)
644 real dist2, long_bond_dist2, short_bond_dist2;
647 long_bond_dist2 = sqr(long_bond_dist);
648 short_bond_dist2 = sqr(short_bond_dist);
655 fprintf(stderr,"Making bonds...\n");
657 for(resind=0; (resind < nres) && (i<natoms); resind++) {
658 /* add bonds from list of bonded interactions */
659 for(j=0; j < hb[resind].rb[ebtsBONDS].nb; j++) {
660 /* Unfortunately we can not issue errors or warnings
661 * for missing atoms in bonds, as the hydrogens and terminal atoms
662 * have not been added yet.
664 ai=search_atom(hb[resind].rb[ebtsBONDS].b[j].AI,i,natoms,atom,aname,
666 aj=search_atom(hb[resind].rb[ebtsBONDS].b[j].AJ,i,natoms,atom,aname,
668 if (ai != NO_ATID && aj != NO_ATID) {
669 dist2 = distance2(x[ai],x[aj]);
670 if (dist2 > long_bond_dist2 )
672 fprintf(stderr,"Warning: Long Bond (%d-%d = %g nm)\n",
673 ai+1,aj+1,sqrt(dist2));
675 else if (dist2 < short_bond_dist2 )
677 fprintf(stderr,"Warning: Short Bond (%d-%d = %g nm)\n",
678 ai+1,aj+1,sqrt(dist2));
680 add_param(psb,ai,aj,NULL,hb[resind].rb[ebtsBONDS].b[j].s);
683 /* add bonds from list of hacks (each added atom gets a bond) */
684 while( (i<natoms) && (atom[i].resind == resind) ) {
685 for(j=0; j < hb[resind].nhack; j++)
686 if ( ( hb[resind].hack[j].tp > 0 ||
687 hb[resind].hack[j].oname==NULL ) &&
688 strcmp(hb[resind].hack[j].AI,*(aname[i])) == 0 ) {
689 switch(hb[resind].hack[j].tp) {
690 case 9: /* COOH terminus */
691 add_param(psb,i,i+1,NULL,NULL); /* C-O */
692 add_param(psb,i,i+2,NULL,NULL); /* C-OA */
693 add_param(psb,i+2,i+3,NULL,NULL); /* OA-H */
696 for(k=0; (k<hb[resind].hack[j].nr); k++)
697 add_param(psb,i,i+k+1,NULL,NULL);
702 /* we're now at the start of the next residue */
706 static int pcompar(const void *a, const void *b)
717 return strlen(pb->s) - strlen(pa->s);
722 static void clean_bonds(t_params *ps)
728 /* swap atomnumbers in bond if first larger than second: */
729 for(i=0; (i<ps->nr); i++)
730 if ( ps->param[i].AJ < ps->param[i].AI ) {
732 ps->param[i].AI = ps->param[i].AJ;
737 qsort(ps->param,ps->nr,(size_t)sizeof(ps->param[0]),pcompar);
739 /* remove doubles, keep the first one always. */
741 for(i=1; (i<ps->nr); i++) {
742 if ((ps->param[i].AI != ps->param[j-1].AI) ||
743 (ps->param[i].AJ != ps->param[j-1].AJ) ) {
744 cp_param(&(ps->param[j]),&(ps->param[i]));
748 fprintf(stderr,"Number of bonds was %d, now %d\n",ps->nr,j);
752 fprintf(stderr,"No bonds\n");
755 void print_sums(t_atoms *atoms, gmx_bool bSystem)
768 for(i=0; (i<atoms->nr); i++) {
770 qtot+=atoms->atom[i].q;
773 fprintf(stderr,"Total mass%s %.3f a.m.u.\n",where,m);
774 fprintf(stderr,"Total charge%s %.3f e\n",where,qtot);
777 static void check_restp_type(const char *name,int t1,int t2)
781 gmx_fatal(FARGS,"Residues in one molecule have a different '%s' type: %d and %d",name,t1,t2);
785 static void check_restp_types(t_restp *r0,t_restp *r1)
789 check_restp_type("all dihedrals",r0->bAlldih,r1->bAlldih);
790 check_restp_type("nrexcl",r0->nrexcl,r1->nrexcl);
791 check_restp_type("HH14",r0->HH14,r1->HH14);
792 check_restp_type("remove dihedrals",r0->bRemoveDih,r1->bRemoveDih);
794 for(i=0; i<ebtsNR; i++)
796 check_restp_type(btsNames[i],r0->rb[i].type,r1->rb[i].type);
800 void add_atom_to_restp(t_restp *restp,int resnr,int at_start,const t_hack *hack)
804 const char *Hnum="123456";
808 fprintf(debug,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
810 *restp->atomname[at_start], resnr, restp->resname);
812 strcpy(buf, hack->nname);
813 buf[strlen(buf)+1]='\0';
816 buf[strlen(buf)]='-';
819 restp->natom += hack->nr;
820 srenew(restp->atom, restp->natom);
821 srenew(restp->atomname, restp->natom);
822 srenew(restp->cgnr, restp->natom);
824 for(k=restp->natom-1; k > at_start+hack->nr; k--)
827 restp->atom [k - hack->nr];
829 restp->atomname[k - hack->nr];
831 restp->cgnr [k - hack->nr];
834 for(k=0; k < hack->nr; k++)
836 /* set counter in atomname */
839 buf[strlen(buf)-1] = Hnum[k];
841 snew( restp->atomname[at_start+1+k], 1);
842 restp->atom [at_start+1+k] = *hack->atom;
843 *restp->atomname[at_start+1+k] = strdup(buf);
844 if ( hack->cgnr != NOTSET )
846 restp->cgnr [at_start+1+k] = hack->cgnr;
850 restp->cgnr [at_start+1+k] = restp->cgnr[at_start];
855 void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
856 int nrtp, t_restp rtp[],
857 int nres, t_resinfo *resinfo,
859 t_hackblock **ntdb, t_hackblock **ctdb,
860 int *rn, int *rc, char *ffname)
866 const char *Hnum="123456";
872 /* first the termini */
873 for(i=0; i<nterpairs; i++) {
874 if (rn[i] >= 0 && ntdb[i] != NULL) {
875 copy_t_hackblock(ntdb[i], &(*hb)[rn[i]]);
877 if (rc[i] >= 0 && ctdb[i] != NULL) {
878 merge_t_hackblock(ctdb[i], &(*hb)[rc[i]]);
882 /* then the whole rtp */
883 for(i=0; i < nres; i++) {
884 /* Here we allow a mismatch of one character when looking for the rtp entry.
885 * For such a mismatch there should be only one mismatching name.
886 * This is mainly useful for small molecules such as ions.
887 * Note that this will usually not work for protein, DNA and RNA,
888 * since there the residue names should be listed in residuetypes.dat
889 * and an error will have been generated earlier in the process.
891 key = *resinfo[i].rtp;
892 snew(resinfo[i].rtp,1);
893 *resinfo[i].rtp = search_rtp(key,nrtp,rtp);
894 res = get_restp(*resinfo[i].rtp,nrtp,rtp);
895 copy_t_restp(res, &(*restp)[i]);
897 /* Check that we do not have different bonded types in one molecule */
898 check_restp_types(&(*restp)[0],&(*restp)[i]);
901 for(j=0; j<nterpairs && tern==-1; j++) {
907 for(j=0; j<nterpairs && terc == -1; j++) {
912 bRM = merge_t_bondeds(res->rb, (*hb)[i].rb,tern>=0,terc>=0);
914 if (bRM && ((tern >= 0 && ntdb[tern] == NULL) ||
915 (terc >= 0 && ctdb[terc] == NULL))) {
916 gmx_fatal(FARGS,"At least one terminus has a dangling bond, and the force field does\nnot provide suitable terminal entries or files. %s",
917 0 == gmx_strncasecmp("AMBER", ffname, 5) ? "With AMBER force fields,\nuse the terminus-specific residue names, eg. NALA, CVAL."
918 : "Edit a .n.tdb and/or .c.tdb file.");
920 if (bRM && ((tern >= 0 && ntdb[tern]->nhack == 0) ||
921 (terc >= 0 && ctdb[terc]->nhack == 0))) {
922 gmx_fatal(FARGS,"At least one terminus has a dangling bond. Select a proper terminal entry.");
926 /* now perform t_hack's on t_restp's,
927 i.e. add's and deletes from termini database will be
928 added to/removed from residue topology
929 we'll do this on one big dirty loop, so it won't make easy reading! */
930 for(i=0; i < nres; i++)
932 for(j=0; j < (*hb)[i].nhack; j++)
934 if ( (*hb)[i].hack[j].nr )
936 /* find atom in restp */
937 for(l=0; l < (*restp)[i].natom; l++)
938 if ( ( (*hb)[i].hack[j].oname==NULL &&
939 strcmp((*hb)[i].hack[j].AI, *(*restp)[i].atomname[l])==0 ) ||
940 ( (*hb)[i].hack[j].oname!=NULL &&
941 strcmp((*hb)[i].hack[j].oname,*(*restp)[i].atomname[l])==0 ) )
943 if (l == (*restp)[i].natom)
945 /* If we are doing an atom rename only, we don't need
946 * to generate a fatal error if the old name is not found
949 /* Deleting can happen also only on the input atoms,
950 * not necessarily always on the rtp entry.
952 if (!((*hb)[i].hack[j].oname != NULL &&
953 (*hb)[i].hack[j].nname != NULL) &&
954 !((*hb)[i].hack[j].oname != NULL &&
955 (*hb)[i].hack[j].nname == NULL))
958 "atom %s not found in buiding block %d%s "
959 "while combining tdb and rtp",
960 (*hb)[i].hack[j].oname!=NULL ?
961 (*hb)[i].hack[j].oname : (*hb)[i].hack[j].AI,
962 i+1,*resinfo[i].rtp);
967 if ( (*hb)[i].hack[j].oname==NULL ) {
969 add_atom_to_restp(&(*restp)[i],resinfo[i].nr,l,
975 if ( (*hb)[i].hack[j].nname==NULL ) {
978 fprintf(debug, "deleting atom %s from res %d%s in rtp\n",
979 *(*restp)[i].atomname[l],
980 i+1,(*restp)[i].resname);
983 for(k=l; k < (*restp)[i].natom; k++) {
984 (*restp)[i].atom [k] = (*restp)[i].atom [k+1];
985 (*restp)[i].atomname[k] = (*restp)[i].atomname[k+1];
986 (*restp)[i].cgnr [k] = (*restp)[i].cgnr [k+1];
988 /* give back space */
989 srenew((*restp)[i].atom, (*restp)[i].natom);
990 srenew((*restp)[i].atomname, (*restp)[i].natom);
991 srenew((*restp)[i].cgnr, (*restp)[i].natom);
992 } else { /* nname != NULL */
993 /* we're replacing */
995 fprintf(debug, "replacing atom %s by %s in res %d%s in rtp\n",
996 *(*restp)[i].atomname[l], (*hb)[i].hack[j].nname,
997 i+1,(*restp)[i].resname);
998 snew( (*restp)[i].atomname[l], 1);
999 (*restp)[i].atom[l] = *(*hb)[i].hack[j].atom;
1000 *(*restp)[i].atomname[l] = strdup((*hb)[i].hack[j].nname);
1001 if ( (*hb)[i].hack[j].cgnr != NOTSET )
1002 (*restp)[i].cgnr [l] = (*hb)[i].hack[j].cgnr;
1011 static gmx_bool atomname_cmp_nr(const char *anm,t_hack *hack,int *nr)
1018 return (gmx_strcasecmp(anm,hack->nname) == 0);
1022 if (isdigit(anm[strlen(anm)-1]))
1024 *nr = anm[strlen(anm)-1] - '0';
1030 if (*nr <= 0 || *nr > hack->nr)
1036 return (strlen(anm) == strlen(hack->nname) + 1 &&
1037 gmx_strncasecmp(anm,hack->nname,strlen(hack->nname)) == 0);
1042 static gmx_bool match_atomnames_with_rtp_atom(t_atoms *pdba,rvec *x,int atind,
1043 t_restp *rptr,t_hackblock *hbr,
1050 char *start_at,buf[STRLEN];
1052 gmx_bool bReplaceReplace,bFoundInAdd;
1055 oldnm = *pdba->atomname[atind];
1056 resnr = pdba->resinfo[pdba->atom[atind].resind].nr;
1059 for(j=0; j<hbr->nhack; j++)
1061 if (hbr->hack[j].oname != NULL && hbr->hack[j].nname != NULL &&
1062 gmx_strcasecmp(oldnm,hbr->hack[j].oname) == 0)
1064 /* This is a replace entry. */
1065 /* Check if we are not replacing a replaced atom. */
1066 bReplaceReplace = FALSE;
1067 for(k=0; k<hbr->nhack; k++) {
1069 hbr->hack[k].oname != NULL && hbr->hack[k].nname != NULL &&
1070 gmx_strcasecmp(hbr->hack[k].nname,hbr->hack[j].oname) == 0)
1072 /* The replace in hack[j] replaces an atom that
1073 * was already replaced in hack[k], we do not want
1074 * second or higher level replaces at this stage.
1076 bReplaceReplace = TRUE;
1079 if (bReplaceReplace)
1081 /* Skip this replace. */
1085 /* This atom still has the old name, rename it */
1086 newnm = hbr->hack[j].nname;
1087 for(k=0; k<rptr->natom; k++)
1089 if (gmx_strcasecmp(newnm,*rptr->atomname[k]) == 0)
1094 if (k == rptr->natom)
1096 /* The new name is not present in the rtp.
1097 * We need to apply the replace also to the rtp entry.
1100 /* We need to find the add hack that can add this atom
1101 * to find out after which atom it should be added.
1103 bFoundInAdd = FALSE;
1104 for(k=0; k<hbr->nhack; k++)
1106 if (hbr->hack[k].oname == NULL &&
1107 hbr->hack[k].nname != NULL &&
1108 atomname_cmp_nr(newnm,&hbr->hack[k],&anmnr))
1112 start_at = hbr->hack[k].a[0];
1116 sprintf(buf,"%s%d",hbr->hack[k].nname,anmnr-1);
1119 for(start_nr=0; start_nr<rptr->natom; start_nr++)
1121 if (gmx_strcasecmp(start_at,(*rptr->atomname[start_nr])) == 0)
1126 if (start_nr == rptr->natom)
1128 gmx_fatal(FARGS,"Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1129 start_at,rptr->resname,newnm);
1131 /* We can add the atom after atom start_nr */
1132 add_atom_to_restp(rptr,resnr,start_nr,
1141 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'",
1143 hbr->hack[j].oname,hbr->hack[j].nname,
1150 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1151 oldnm,rptr->resname,resnr,newnm);
1153 /* Rename the atom in pdba */
1154 snew(pdba->atomname[atind],1);
1155 *pdba->atomname[atind] = strdup(newnm);
1157 else if (hbr->hack[j].oname != NULL && hbr->hack[j].nname == NULL &&
1158 gmx_strcasecmp(oldnm,hbr->hack[j].oname) == 0)
1160 /* This is a delete entry, check if this atom is present
1161 * in the rtp entry of this residue.
1163 for(k=0; k<rptr->natom; k++)
1165 if (gmx_strcasecmp(oldnm,*rptr->atomname[k]) == 0)
1170 if (k == rptr->natom)
1172 /* This atom is not present in the rtp entry,
1173 * delete is now from the input pdba.
1177 printf("Deleting atom '%s' in residue '%s' %d\n",
1178 oldnm,rptr->resname,resnr);
1180 /* We should free the atom name,
1181 * but it might be used multiple times in the symtab.
1182 * sfree(pdba->atomname[atind]);
1184 for(k=atind+1; k<pdba->nr; k++)
1186 pdba->atom[k-1] = pdba->atom[k];
1187 pdba->atomname[k-1] = pdba->atomname[k];
1188 copy_rvec(x[k],x[k-1]);
1199 void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
1200 t_atoms *pdba,rvec *x,
1209 char *start_at,buf[STRLEN];
1211 gmx_bool bFoundInAdd;
1213 for(i=0; i<pdba->nr; i++)
1215 oldnm = *pdba->atomname[i];
1216 resnr = pdba->resinfo[pdba->atom[i].resind].nr;
1217 rptr = &restp[pdba->atom[i].resind];
1218 for(j=0; (j<rptr->natom); j++)
1220 if (gmx_strcasecmp(oldnm,*(rptr->atomname[j])) == 0)
1225 if (j == rptr->natom)
1227 /* Not found yet, check if we have to rename this atom */
1228 if (match_atomnames_with_rtp_atom(pdba,x,i,
1229 rptr,&(hb[pdba->atom[i].resind]),
1232 /* We deleted this atom, decrease the atom counter by 1. */
1239 void gen_cmap(t_params *psb, t_restp *restp, int natoms, t_atom atom[], char **aname[], int nres)
1241 int residx,i,ii,j,k;
1242 atom_id ai,aj,ak,al,am;
1250 fprintf(stderr,"Making cmap torsions...");
1252 /* End loop at nres-1, since the very last residue does not have a +N atom, and
1253 * therefore we get a valgrind invalid 4 byte read error with atom am */
1254 for(residx=0; residx<nres-1; residx++)
1256 /* Add CMAP terms from the list of CMAP interactions */
1257 for(j=0;j<restp[residx].rb[ebtsCMAP].nb; j++)
1259 ai=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[0],i,natoms,atom,aname,
1261 aj=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[1],i,natoms,atom,aname,
1263 ak=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[2],i,natoms,atom,aname,
1265 al=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[3],i,natoms,atom,aname,
1267 am=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[4],i,natoms,atom,aname,
1270 /* The first and last residues no not have cmap torsions */
1271 if(ai!=NO_ATID && aj!=NO_ATID && ak!=NO_ATID && al!=NO_ATID && am!=NO_ATID)
1273 add_cmap_param(psb,ai,aj,ak,al,am,restp[residx].rb[ebtsCMAP].b[j].s);
1279 while(atom[i].resind<residx+1)
1286 /* Start the next residue */
1290 scrub_charge_groups(int *cgnr, int natoms)
1294 for(i=0;i<natoms;i++)
1301 void pdb2top(FILE *top_file, char *posre_fn, char *molname,
1302 t_atoms *atoms, rvec **x, gpp_atomtype_t atype, t_symtab *tab,
1303 int nrtp, t_restp rtp[],
1304 t_restp *restp, t_hackblock *hb,
1305 int nterpairs,t_hackblock **ntdb, t_hackblock **ctdb,
1306 int *rn, int *rc, gmx_bool bAllowMissing,
1307 gmx_bool bVsites, gmx_bool bVsiteAromatics,
1308 const char *ff, const char *ffdir,
1310 int nssbonds, t_ssbond *ssbonds,
1311 real long_bond_dist, real short_bond_dist,
1312 gmx_bool bDeuterate, gmx_bool bChargeGroups, gmx_bool bCmap,
1313 gmx_bool bRenumRes,gmx_bool bRTPresname)
1319 t_params plist[F_NRE];
1330 print_resall(debug, atoms->nres, restp, atype);
1331 dump_hb(debug, atoms->nres, hb);
1335 at2bonds(&(plist[F_BONDS]), hb,
1336 atoms->nr, atoms->atom, atoms->atomname, atoms->nres, *x,
1337 long_bond_dist, short_bond_dist, bAllowMissing);
1339 /* specbonds: disulphide bonds & heme-his */
1340 do_ssbonds(&(plist[F_BONDS]),
1341 atoms->nr, atoms->atom, atoms->atomname, nssbonds, ssbonds,
1344 nmissat = name2type(atoms, &cgnr, atype, restp);
1347 fprintf(stderr,"There were %d missing atoms in molecule %s\n",
1350 gmx_fatal(FARGS,"There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1354 /* Cleanup bonds (sort and rm doubles) */
1355 clean_bonds(&(plist[F_BONDS]));
1357 snew(vsite_type,atoms->nr);
1358 for(i=0; i<atoms->nr; i++)
1359 vsite_type[i]=NOTSET;
1361 /* determine which atoms will be vsites and add dummy masses
1362 also renumber atom numbers in plist[0..F_NRE]! */
1363 do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
1364 &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
1367 /* Make Angles and Dihedrals */
1368 fprintf(stderr,"Generating angles, dihedrals and pairs...\n");
1369 snew(excls,atoms->nr);
1370 init_nnb(&nnb,atoms->nr,4);
1371 gen_nnb(&nnb,plist);
1372 print_nnb(&nnb,"NNB");
1373 gen_pad(&nnb,atoms,restp[0].nrexcl,restp[0].HH14,
1374 plist,excls,hb,restp[0].bAlldih,restp[0].bRemoveDih,
1381 gen_cmap(&(plist[F_CMAP]), restp, atoms->nr, atoms->atom, atoms->atomname, atoms->nres);
1382 if (plist[F_CMAP].nr > 0)
1384 fprintf(stderr, "There are %4d cmap torsion pairs\n",
1389 /* set mass of all remaining hydrogen atoms */
1391 do_h_mass(&(plist[F_BONDS]),vsite_type,atoms,mHmult,bDeuterate);
1394 /* Cleanup bonds (sort and rm doubles) */
1395 /* clean_bonds(&(plist[F_BONDS]));*/
1398 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1399 " %4d pairs, %4d bonds and %4d virtual sites\n",
1400 plist[F_PDIHS].nr, plist[F_IDIHS].nr, plist[F_ANGLES].nr,
1401 plist[F_LJ14].nr, plist[F_BONDS].nr,
1402 plist[F_VSITE2].nr +
1403 plist[F_VSITE3].nr +
1404 plist[F_VSITE3FD].nr +
1405 plist[F_VSITE3FAD].nr +
1406 plist[F_VSITE3OUT].nr +
1407 plist[F_VSITE4FD].nr +
1408 plist[F_VSITE4FDN].nr );
1410 print_sums(atoms, FALSE);
1412 if (FALSE == bChargeGroups)
1414 scrub_charge_groups(cgnr, atoms->nr);
1419 for(i=0; i<atoms->nres; i++)
1421 atoms->resinfo[i].nr = i + 1;
1422 atoms->resinfo[i].ic = ' ';
1427 fprintf(stderr,"Writing topology\n");
1428 /* We can copy the bonded types from the first restp,
1429 * since the types have to be identical for all residues in one molecule.
1431 for(i=0; i<ebtsNR; i++) {
1432 bts[i] = restp[0].rb[i].type;
1434 write_top(top_file, posre_fn, molname,
1436 bts, plist, excls, atype, cgnr, restp[0].nrexcl);
1440 free_t_hackblock(atoms->nres, &hb);
1441 free_t_restp(atoms->nres, &restp);
1443 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1445 for (i=0; i<F_NRE; i++)
1446 sfree(plist[i].param);
1447 for (i=0; i<atoms->nr; i++)