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
44 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
57 #include "gmx_fatal.h"
59 #include "gpp_nextnb.h"
72 #include "gen_vsite.h"
75 #include "fflibutil.h"
78 /* this must correspond to enum in pdb2top.h */
79 const char *hh
[ehisNR
] = { "HISD", "HISE", "HISH", "HIS1" };
81 static int missing_atoms(t_restp
*rp
, int resind
,t_atoms
*at
, int i0
, int i
)
85 gmx_bool bFound
, bRet
;
88 for (j
=0; j
<rp
->natom
; j
++)
90 name
=*(rp
->atomname
[j
]);
94 bFound
= (bFound
|| !gmx_strcasecmp(*(at
->atomname
[k
]),name
));
99 fprintf(stderr
,"\nWARNING: "
100 "atom %s is missing in residue %s %d in the pdb file\n",
101 name
,*(at
->resinfo
[resind
].name
),at
->resinfo
[resind
].nr
);
102 if (name
[0]=='H' || name
[0]=='h')
104 fprintf(stderr
," You might need to add atom %s to the hydrogen database of building block %s\n"
105 " in the file %s.hdb (see the manual)\n",
106 name
,*(at
->resinfo
[resind
].rtp
),rp
->filebase
);
108 fprintf(stderr
,"\n");
115 gmx_bool
is_int(double x
)
117 const double tol
= 1e-4;
124 return (fabs(x
-ix
) < tol
);
127 static void swap_strings(char **s
,int i
,int j
)
137 choose_ff(const char *ffsel
,
138 char *forcefield
, int ff_maxlen
,
139 char *ffdir
, int ffdir_maxlen
)
142 char **ffdirs
,**ffs
,**ffs_dir
,*ptr
;
143 int i
,j
,sel
,cwdsel
,nfound
;
144 char buf
[STRLEN
],**desc
;
148 nff
= fflib_search_file_in_dirend(fflib_forcefield_itp(),
149 fflib_forcefield_dir_ext(),
154 gmx_fatal(FARGS
,"No force fields found (files with name '%s' in subdirectories ending on '%s')",
155 fflib_forcefield_itp(),fflib_forcefield_dir_ext());
158 /* Replace with unix path separators */
159 if(DIR_SEPARATOR
!='/')
163 while( (ptr
=strchr(ffdirs
[i
],DIR_SEPARATOR
))!=NULL
)
170 /* Store the force field names in ffs */
175 /* Remove the path from the ffdir name - use our unix standard here! */
176 ptr
= strrchr(ffdirs
[i
],'/');
179 ffs
[i
] = strdup(ffdirs
[i
]);
180 ffs_dir
[i
] = low_gmxlibfn(ffdirs
[i
],FALSE
,FALSE
);
181 if (ffs_dir
[i
] == NULL
)
183 gmx_fatal(FARGS
,"Can no longer find file '%s'",ffdirs
[i
]);
188 ffs
[i
] = strdup(ptr
+1);
189 ffs_dir
[i
] = strdup(ffdirs
[i
]);
191 ffs_dir
[i
][strlen(ffs_dir
[i
])-strlen(ffs
[i
])-1] = '\0';
192 /* Remove the extension from the ffdir name */
193 ffs
[i
][strlen(ffs
[i
])-strlen(fflib_forcefield_dir_ext())] = '\0';
203 if ( strcmp(ffs
[i
],ffsel
)==0 )
205 /* Matching ff name */
209 if( strncmp(ffs_dir
[i
],".",1)==0 )
226 "Force field '%s' occurs in %d places. pdb2gmx is using the one in the\n"
227 "current directory. Use interactive selection (not the -ff option) if\n"
228 "you would prefer a different one.\n",ffsel
,nfound
);
233 "Force field '%s' occurs in %d places, but not in the current directory.\n"
234 "Run without the -ff switch and select the force field interactively.",ffsel
,nfound
);
239 gmx_fatal(FARGS
,"Could not find force field '%s' in current directory, install tree or GMXDATA path.",ffsel
);
245 for(i
=0; (i
<nff
); i
++)
247 sprintf(buf
,"%s%c%s%s%c%s",
248 ffs_dir
[i
],DIR_SEPARATOR
,
249 ffs
[i
],fflib_forcefield_dir_ext(),DIR_SEPARATOR
,
250 fflib_forcefield_doc());
253 /* We don't use fflib_open, because we don't want printf's */
254 fp
= ffopen(buf
,"r");
255 snew(desc
[i
],STRLEN
);
256 get_a_line(fp
,desc
[i
],STRLEN
);
261 desc
[i
] = strdup(ffs
[i
]);
264 /* Order force fields from the same dir alphabetically
265 * and put deprecated force fields at the end.
267 for(i
=0; (i
<nff
); i
++)
269 for(j
=i
+1; (j
<nff
); j
++)
271 if (strcmp(ffs_dir
[i
],ffs_dir
[j
]) == 0 &&
272 ((desc
[i
][0] == '[' && desc
[j
][0] != '[') ||
273 ((desc
[i
][0] == '[' || desc
[j
][0] != '[') &&
274 gmx_strcasecmp(desc
[i
],desc
[j
]) > 0)))
276 swap_strings(ffdirs
,i
,j
);
277 swap_strings(ffs
,i
,j
);
278 swap_strings(desc
,i
,j
);
283 printf("\nSelect the Force Field:\n");
284 for(i
=0; (i
<nff
); i
++)
286 if (i
== 0 || strcmp(ffs_dir
[i
-1],ffs_dir
[i
]) != 0)
288 if( strcmp(ffs_dir
[i
],".")==0 )
290 printf("From current directory:\n");
294 printf("From '%s':\n",ffs_dir
[i
]);
297 printf("%2d: %s\n",i
+1,desc
[i
]);
304 pret
= fgets(buf
,STRLEN
,stdin
);
308 sscanf(buf
,"%d",&sel
);
312 while ( pret
==NULL
|| (sel
< 0) || (sel
>= nff
));
314 /* Check for a current limitation of the fflib code.
315 * It will always read from the first ff directory in the list.
316 * This check assumes that the order of ffs matches the order
317 * in which fflib_open searches ff library files.
321 if (strcmp(ffs
[i
],ffs
[sel
]) == 0)
323 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.",
324 ffs
[sel
],fflib_forcefield_dir_ext());
333 if (strlen(ffs
[sel
]) >= (size_t)ff_maxlen
)
335 gmx_fatal(FARGS
,"Length of force field name (%d) >= maxlen (%d)",
336 strlen(ffs
[sel
]),ff_maxlen
);
338 strcpy(forcefield
,ffs
[sel
]);
340 if (strlen(ffdirs
[sel
]) >= (size_t)ffdir_maxlen
)
342 gmx_fatal(FARGS
,"Length of force field dir (%d) >= maxlen (%d)",
343 strlen(ffdirs
[sel
]),ffdir_maxlen
);
345 strcpy(ffdir
,ffdirs
[sel
]);
347 for(i
=0; (i
<nff
); i
++)
358 void choose_watermodel(const char *wmsel
,const char *ffdir
,
361 const char *fn_watermodels
="watermodels.dat";
362 char fn_list
[STRLEN
];
369 if (strcmp(wmsel
,"none") == 0)
375 else if (strcmp(wmsel
,"select") != 0)
377 *watermodel
= strdup(wmsel
);
382 sprintf(fn_list
,"%s%c%s",ffdir
,DIR_SEPARATOR
,fn_watermodels
);
384 if (!fflib_fexist(fn_list
))
386 fprintf(stderr
,"No file '%s' found, will not include a water model\n",
393 fp
= fflib_open(fn_list
);
394 printf("\nSelect the Water Model:\n");
397 while (get_a_line(fp
,buf
,STRLEN
))
400 snew(model
[nwm
],STRLEN
);
401 sscanf(buf
,"%s%n",model
[nwm
],&i
);
405 fprintf(stderr
,"%2d: %s\n",nwm
+1,buf
+i
);
414 fprintf(stderr
,"%2d: %s\n",nwm
+1,"None");
418 pret
= fgets(buf
,STRLEN
,stdin
);
422 sscanf(buf
,"%d",&sel
);
426 while (pret
== NULL
|| sel
< 0 || sel
> nwm
);
434 *watermodel
= strdup(model
[sel
]);
444 static int name2type(t_atoms
*at
, int **cgnr
, gpp_atomtype_t atype
,
445 t_restp restp
[], gmx_residuetype_t rt
)
447 int i
,j
,prevresind
,resind
,i0
,prevcg
,cg
,curcg
;
449 gmx_bool bProt
, bNterm
;
466 for(i
=0; (i
<at
->nr
); i
++) {
468 if (at
->atom
[i
].resind
!= resind
) {
469 resind
= at
->atom
[i
].resind
;
470 bProt
= gmx_residuetype_is_protein(rt
,*(at
->resinfo
[resind
].name
));
471 bNterm
=bProt
&& (resind
== 0);
473 nmissat
+= missing_atoms(&restp
[prevresind
],prevresind
,at
,i0
,i
);
477 if (at
->atom
[i
].m
== 0) {
479 fprintf(debug
,"atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
480 i
+1,*(at
->atomname
[i
]),curcg
,prevcg
,
481 j
==NOTSET
? NOTSET
: restp
[resind
].cgnr
[j
]);
484 name
=*(at
->atomname
[i
]);
485 j
=search_jtype(&restp
[resind
],name
,bNterm
);
486 at
->atom
[i
].type
= restp
[resind
].atom
[j
].type
;
487 at
->atom
[i
].q
= restp
[resind
].atom
[j
].q
;
488 at
->atom
[i
].m
= get_atomtype_massA(restp
[resind
].atom
[j
].type
,
490 cg
= restp
[resind
].cgnr
[j
];
491 /* A charge group number -1 signals a separate charge group
494 if ( (cg
== -1) || (cg
!= prevcg
) || (resind
!= prevresind
) ) {
499 fprintf(debug
,"atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
500 i
+1,*(at
->atomname
[i
]),curcg
,qt
,is_int(qt
));
509 at
->atom
[i
].typeB
= at
->atom
[i
].type
;
510 at
->atom
[i
].qB
= at
->atom
[i
].q
;
511 at
->atom
[i
].mB
= at
->atom
[i
].m
;
513 nmissat
+= missing_atoms(&restp
[resind
],resind
,at
,i0
,i
);
518 static void print_top_heavy_H(FILE *out
, real mHmult
)
521 fprintf(out
,"; Using deuterium instead of hydrogen\n\n");
522 else if (mHmult
== 4.0)
523 fprintf(out
,"#define HEAVY_H\n\n");
524 else if (mHmult
!= 1.0)
525 fprintf(stderr
,"WARNING: unsupported proton mass multiplier (%g) "
526 "in pdb2top\n",mHmult
);
529 void print_top_comment(FILE *out
,
530 const char *filename
,
531 const char *generator
,
536 char ffdir_parent
[STRLEN
];
539 nice_header(out
,filename
);
540 fprintf(out
,";\tThis is a %s topology file\n;\n",bITP
? "include" : "standalone");
541 fprintf(out
,";\tIt was generated using program:\n;\t%s\n;\n",
542 (NULL
== generator
) ? "unknown" : generator
);
543 fprintf(out
,";\tCommand line was:\n;\t%s\n;\n",command_line());
545 if(strchr(ffdir
,'/')==NULL
)
547 fprintf(out
,";\tForce field was read from the standard Gromacs share directory.\n;\n\n");
549 else if(ffdir
[0]=='.')
551 fprintf(out
,";\tForce field was read from current directory or a relative path - path added.\n;\n\n");
555 strncpy(ffdir_parent
,ffdir
,STRLEN
-1);
556 p
=strrchr(ffdir_parent
,'/');
561 ";\tForce field data was read from:\n"
565 ";\tThis might be a non-standard force field location. When you use this topology, the\n"
566 ";\tforce field must either be present in the current directory, or the location\n"
567 ";\tspecified in the GMXLIB path variable or with the 'include' mdp file option.\n;\n\n",
572 void print_top_header(FILE *out
,const char *filename
,
573 const char *title
,gmx_bool bITP
,const char *ffdir
,real mHmult
)
577 print_top_comment(out
,filename
,title
,ffdir
,bITP
);
579 print_top_heavy_H(out
, mHmult
);
580 fprintf(out
,"; Include forcefield parameters\n");
582 p
=strrchr(ffdir
,'/');
583 p
= (ffdir
[0]=='.' || p
==NULL
) ? ffdir
: p
+1;
585 fprintf(out
,"#include \"%s/%s\"\n\n",p
,fflib_forcefield_itp());
588 static void print_top_posre(FILE *out
,const char *pr
)
590 fprintf(out
,"; Include Position restraint file\n");
591 fprintf(out
,"#ifdef POSRES\n");
592 fprintf(out
,"#include \"%s\"\n",pr
);
593 fprintf(out
,"#endif\n\n");
596 static void print_top_water(FILE *out
,const char *ffdir
,const char *water
)
601 fprintf(out
,"; Include water topology\n");
603 p
=strrchr(ffdir
,'/');
604 p
= (ffdir
[0]=='.' || p
==NULL
) ? ffdir
: p
+1;
605 fprintf(out
,"#include \"%s/%s.itp\"\n",p
,water
);
608 fprintf(out
,"#ifdef POSRES_WATER\n");
609 fprintf(out
,"; Position restraint for each water oxygen\n");
610 fprintf(out
,"[ position_restraints ]\n");
611 fprintf(out
,";%3s %5s %9s %10s %10s\n","i","funct","fcx","fcy","fcz");
612 fprintf(out
,"%4d %4d %10g %10g %10g\n",1,1,1000.0,1000.0,1000.0);
613 fprintf(out
,"#endif\n");
616 sprintf(buf
,"%s/ions.itp",p
);
618 if (fflib_fexist(buf
))
620 fprintf(out
,"; Include topology for ions\n");
621 fprintf(out
,"#include \"%s\"\n",buf
);
626 static void print_top_system(FILE *out
, const char *title
)
628 fprintf(out
,"[ %s ]\n",dir2str(d_system
));
629 fprintf(out
,"; Name\n");
630 fprintf(out
,"%s\n\n",title
[0]?title
:"Protein");
633 void print_top_mols(FILE *out
,
634 const char *title
, const char *ffdir
, const char *water
,
635 int nincl
, char **incls
, int nmol
, t_mols
*mols
)
641 fprintf(out
,"; Include chain topologies\n");
642 for (i
=0; (i
<nincl
); i
++) {
643 incl
= strrchr(incls
[i
],DIR_SEPARATOR
);
647 /* Remove the path from the include name */
650 fprintf(out
,"#include \"%s\"\n",incl
);
657 print_top_water(out
,ffdir
,water
);
659 print_top_system(out
, title
);
662 fprintf(out
,"[ %s ]\n",dir2str(d_molecules
));
663 fprintf(out
,"; %-15s %5s\n","Compound","#mols");
664 for (i
=0; (i
<nmol
); i
++)
665 fprintf(out
,"%-15s %5d\n",mols
[i
].name
,mols
[i
].nr
);
669 void write_top(FILE *out
, char *pr
,char *molname
,
670 t_atoms
*at
,gmx_bool bRTPresname
,
671 int bts
[],t_params plist
[],t_excls excls
[],
672 gpp_atomtype_t atype
,int *cgnr
, int nrexcl
)
673 /* NOTE: nrexcl is not the size of *excl! */
675 if (at
&& atype
&& cgnr
) {
676 fprintf(out
,"[ %s ]\n",dir2str(d_moleculetype
));
677 fprintf(out
,"; %-15s %5s\n","Name","nrexcl");
678 fprintf(out
,"%-15s %5d\n\n",molname
?molname
:"Protein",nrexcl
);
680 print_atoms(out
, atype
, at
, cgnr
, bRTPresname
);
681 print_bondeds(out
,at
->nr
,d_bonds
, F_BONDS
, bts
[ebtsBONDS
], plist
);
682 print_bondeds(out
,at
->nr
,d_constraints
,F_CONSTR
, 0, plist
);
683 print_bondeds(out
,at
->nr
,d_constraints
,F_CONSTRNC
, 0, plist
);
684 print_bondeds(out
,at
->nr
,d_pairs
, F_LJ14
, 0, plist
);
685 print_excl(out
,at
->nr
,excls
);
686 print_bondeds(out
,at
->nr
,d_angles
, F_ANGLES
, bts
[ebtsANGLES
],plist
);
687 print_bondeds(out
,at
->nr
,d_dihedrals
, F_PDIHS
, bts
[ebtsPDIHS
], plist
);
688 print_bondeds(out
,at
->nr
,d_dihedrals
, F_IDIHS
, bts
[ebtsIDIHS
], plist
);
689 print_bondeds(out
,at
->nr
,d_cmap
, F_CMAP
, bts
[ebtsCMAP
], plist
);
690 print_bondeds(out
,at
->nr
,d_polarization
,F_POLARIZATION
, 0, plist
);
691 print_bondeds(out
,at
->nr
,d_thole_polarization
,F_THOLE_POL
,0, plist
);
692 print_bondeds(out
,at
->nr
,d_vsites2
, F_VSITE2
, 0, plist
);
693 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3
, 0, plist
);
694 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3FD
, 0, plist
);
695 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3FAD
,0, plist
);
696 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3OUT
,0, plist
);
697 print_bondeds(out
,at
->nr
,d_vsites4
, F_VSITE4FD
, 0, plist
);
698 print_bondeds(out
,at
->nr
,d_vsites4
, F_VSITE4FDN
, 0, plist
);
701 print_top_posre(out
,pr
);
705 static atom_id
search_res_atom(const char *type
,int resind
,
706 int natom
,t_atom at
[],
707 char ** const *aname
,
708 const char *bondtype
,gmx_bool bAllowMissing
)
712 for(i
=0; (i
<natom
); i
++)
713 if (at
[i
].resind
== resind
)
714 return search_atom(type
,i
,natom
,at
,aname
,bondtype
,bAllowMissing
);
719 static void do_ssbonds(t_params
*ps
,int natoms
,t_atom atom
[],char **aname
[],
720 int nssbonds
,t_ssbond
*ssbonds
,gmx_bool bAllowMissing
)
725 for(i
=0; (i
<nssbonds
); i
++) {
726 ri
= ssbonds
[i
].res1
;
727 rj
= ssbonds
[i
].res2
;
728 ai
= search_res_atom(ssbonds
[i
].a1
,ri
,natoms
,atom
,aname
,
729 "special bond",bAllowMissing
);
730 aj
= search_res_atom(ssbonds
[i
].a2
,rj
,natoms
,atom
,aname
,
731 "special bond",bAllowMissing
);
732 if ((ai
== NO_ATID
) || (aj
== NO_ATID
))
733 gmx_fatal(FARGS
,"Trying to make impossible special bond (%s-%s)!",
734 ssbonds
[i
].a1
,ssbonds
[i
].a2
);
735 add_param(ps
,ai
,aj
,NULL
,NULL
);
739 static gmx_bool
inter_res_bond(const t_rbonded
*b
)
741 return (b
->AI
[0] == '-' || b
->AI
[0] == '+' ||
742 b
->AJ
[0] == '-' || b
->AJ
[0] == '+');
745 static void at2bonds(t_params
*psb
, t_hackblock
*hb
,
746 int natoms
, t_atom atom
[], char **aname
[],
748 real long_bond_dist
, real short_bond_dist
,
749 gmx_bool bAllowMissing
)
753 real dist2
, long_bond_dist2
, short_bond_dist2
;
756 long_bond_dist2
= sqr(long_bond_dist
);
757 short_bond_dist2
= sqr(short_bond_dist
);
764 fprintf(stderr
,"Making bonds...\n");
766 for(resind
=0; (resind
< nres
) && (i
<natoms
); resind
++) {
767 /* add bonds from list of bonded interactions */
768 for(j
=0; j
< hb
[resind
].rb
[ebtsBONDS
].nb
; j
++) {
769 /* Unfortunately we can not issue errors or warnings
770 * for missing atoms in bonds, as the hydrogens and terminal atoms
771 * have not been added yet.
773 ai
=search_atom(hb
[resind
].rb
[ebtsBONDS
].b
[j
].AI
,i
,natoms
,atom
,aname
,
775 aj
=search_atom(hb
[resind
].rb
[ebtsBONDS
].b
[j
].AJ
,i
,natoms
,atom
,aname
,
777 if (ai
!= NO_ATID
&& aj
!= NO_ATID
) {
778 dist2
= distance2(x
[ai
],x
[aj
]);
779 if (dist2
> long_bond_dist2
)
781 fprintf(stderr
,"Warning: Long Bond (%d-%d = %g nm)\n",
782 ai
+1,aj
+1,sqrt(dist2
));
784 else if (dist2
< short_bond_dist2
)
786 fprintf(stderr
,"Warning: Short Bond (%d-%d = %g nm)\n",
787 ai
+1,aj
+1,sqrt(dist2
));
789 add_param(psb
,ai
,aj
,NULL
,hb
[resind
].rb
[ebtsBONDS
].b
[j
].s
);
792 /* add bonds from list of hacks (each added atom gets a bond) */
793 while( (i
<natoms
) && (atom
[i
].resind
== resind
) ) {
794 for(j
=0; j
< hb
[resind
].nhack
; j
++)
795 if ( ( hb
[resind
].hack
[j
].tp
> 0 ||
796 hb
[resind
].hack
[j
].oname
==NULL
) &&
797 strcmp(hb
[resind
].hack
[j
].AI
,*(aname
[i
])) == 0 ) {
798 switch(hb
[resind
].hack
[j
].tp
) {
799 case 9: /* COOH terminus */
800 add_param(psb
,i
,i
+1,NULL
,NULL
); /* C-O */
801 add_param(psb
,i
,i
+2,NULL
,NULL
); /* C-OA */
802 add_param(psb
,i
+2,i
+3,NULL
,NULL
); /* OA-H */
805 for(k
=0; (k
<hb
[resind
].hack
[j
].nr
); k
++)
806 add_param(psb
,i
,i
+k
+1,NULL
,NULL
);
811 /* we're now at the start of the next residue */
815 static int pcompar(const void *a
, const void *b
)
826 return strlen(pb
->s
) - strlen(pa
->s
);
831 static void clean_bonds(t_params
*ps
)
837 /* swap atomnumbers in bond if first larger than second: */
838 for(i
=0; (i
<ps
->nr
); i
++)
839 if ( ps
->param
[i
].AJ
< ps
->param
[i
].AI
) {
841 ps
->param
[i
].AI
= ps
->param
[i
].AJ
;
846 qsort(ps
->param
,ps
->nr
,(size_t)sizeof(ps
->param
[0]),pcompar
);
848 /* remove doubles, keep the first one always. */
850 for(i
=1; (i
<ps
->nr
); i
++) {
851 if ((ps
->param
[i
].AI
!= ps
->param
[j
-1].AI
) ||
852 (ps
->param
[i
].AJ
!= ps
->param
[j
-1].AJ
) ) {
854 cp_param(&(ps
->param
[j
]),&(ps
->param
[i
]));
859 fprintf(stderr
,"Number of bonds was %d, now %d\n",ps
->nr
,j
);
863 fprintf(stderr
,"No bonds\n");
866 void print_sums(t_atoms
*atoms
, gmx_bool bSystem
)
879 for(i
=0; (i
<atoms
->nr
); i
++) {
881 qtot
+=atoms
->atom
[i
].q
;
884 fprintf(stderr
,"Total mass%s %.3f a.m.u.\n",where
,m
);
885 fprintf(stderr
,"Total charge%s %.3f e\n",where
,qtot
);
888 static void check_restp_type(const char *name
,int t1
,int t2
)
892 gmx_fatal(FARGS
,"Residues in one molecule have a different '%s' type: %d and %d",name
,t1
,t2
);
896 static void check_restp_types(t_restp
*r0
,t_restp
*r1
)
900 check_restp_type("all dihedrals",r0
->bAlldih
,r1
->bAlldih
);
901 check_restp_type("nrexcl",r0
->nrexcl
,r1
->nrexcl
);
902 check_restp_type("HH14",r0
->HH14
,r1
->HH14
);
903 check_restp_type("remove dihedrals",r0
->bRemoveDih
,r1
->bRemoveDih
);
905 for(i
=0; i
<ebtsNR
; i
++)
907 check_restp_type(btsNames
[i
],r0
->rb
[i
].type
,r1
->rb
[i
].type
);
911 void add_atom_to_restp(t_restp
*restp
,int resnr
,int at_start
,const t_hack
*hack
)
915 const char *Hnum
="123456";
919 fprintf(debug,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
921 *restp->atomname[at_start], resnr, restp->resname);
923 strcpy(buf
, hack
->nname
);
924 buf
[strlen(buf
)+1]='\0';
927 buf
[strlen(buf
)]='-';
930 restp
->natom
+= hack
->nr
;
931 srenew(restp
->atom
, restp
->natom
);
932 srenew(restp
->atomname
, restp
->natom
);
933 srenew(restp
->cgnr
, restp
->natom
);
935 for(k
=restp
->natom
-1; k
> at_start
+hack
->nr
; k
--)
938 restp
->atom
[k
- hack
->nr
];
940 restp
->atomname
[k
- hack
->nr
];
942 restp
->cgnr
[k
- hack
->nr
];
945 for(k
=0; k
< hack
->nr
; k
++)
947 /* set counter in atomname */
950 buf
[strlen(buf
)-1] = Hnum
[k
];
952 snew( restp
->atomname
[at_start
+1+k
], 1);
953 restp
->atom
[at_start
+1+k
] = *hack
->atom
;
954 *restp
->atomname
[at_start
+1+k
] = strdup(buf
);
955 if ( hack
->cgnr
!= NOTSET
)
957 restp
->cgnr
[at_start
+1+k
] = hack
->cgnr
;
961 restp
->cgnr
[at_start
+1+k
] = restp
->cgnr
[at_start
];
966 void get_hackblocks_rtp(t_hackblock
**hb
, t_restp
**restp
,
967 int nrtp
, t_restp rtp
[],
968 int nres
, t_resinfo
*resinfo
,
970 t_hackblock
**ntdb
, t_hackblock
**ctdb
,
977 const char *Hnum
="123456";
983 /* first the termini */
984 for(i
=0; i
<nterpairs
; i
++) {
985 if (rn
[i
] >= 0 && ntdb
[i
] != NULL
) {
986 copy_t_hackblock(ntdb
[i
], &(*hb
)[rn
[i
]]);
988 if (rc
[i
] >= 0 && ctdb
[i
] != NULL
) {
989 merge_t_hackblock(ctdb
[i
], &(*hb
)[rc
[i
]]);
993 /* then the whole rtp */
994 for(i
=0; i
< nres
; i
++) {
995 /* Here we allow a mismatch of one character when looking for the rtp entry.
996 * For such a mismatch there should be only one mismatching name.
997 * This is mainly useful for small molecules such as ions.
998 * Note that this will usually not work for protein, DNA and RNA,
999 * since there the residue names should be listed in residuetypes.dat
1000 * and an error will have been generated earlier in the process.
1002 key
= *resinfo
[i
].rtp
;
1003 snew(resinfo
[i
].rtp
,1);
1004 *resinfo
[i
].rtp
= search_rtp(key
,nrtp
,rtp
);
1005 res
= get_restp(*resinfo
[i
].rtp
,nrtp
,rtp
);
1006 copy_t_restp(res
, &(*restp
)[i
]);
1008 /* Check that we do not have different bonded types in one molecule */
1009 check_restp_types(&(*restp
)[0],&(*restp
)[i
]);
1012 for(j
=0; j
<nterpairs
&& tern
==-1; j
++) {
1018 for(j
=0; j
<nterpairs
&& terc
== -1; j
++) {
1023 bRM
= merge_t_bondeds(res
->rb
, (*hb
)[i
].rb
,tern
>=0,terc
>=0);
1025 if (bRM
&& ((tern
>= 0 && ntdb
[tern
] == NULL
) ||
1026 (terc
>= 0 && ctdb
[terc
] == NULL
))) {
1027 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. Edit a .n.tdb and/or .c.tdb file.");
1029 if (bRM
&& ((tern
>= 0 && ntdb
[tern
]->nhack
== 0) ||
1030 (terc
>= 0 && ctdb
[terc
]->nhack
== 0))) {
1031 gmx_fatal(FARGS
,"There is a dangling bond at at least one of the terminal ends. Select a proper terminal entry.");
1035 /* now perform t_hack's on t_restp's,
1036 i.e. add's and deletes from termini database will be
1037 added to/removed from residue topology
1038 we'll do this on one big dirty loop, so it won't make easy reading! */
1039 for(i
=0; i
< nres
; i
++)
1041 for(j
=0; j
< (*hb
)[i
].nhack
; j
++)
1043 if ( (*hb
)[i
].hack
[j
].nr
)
1045 /* find atom in restp */
1046 for(l
=0; l
< (*restp
)[i
].natom
; l
++)
1047 if ( ( (*hb
)[i
].hack
[j
].oname
==NULL
&&
1048 strcmp((*hb
)[i
].hack
[j
].AI
, *(*restp
)[i
].atomname
[l
])==0 ) ||
1049 ( (*hb
)[i
].hack
[j
].oname
!=NULL
&&
1050 strcmp((*hb
)[i
].hack
[j
].oname
,*(*restp
)[i
].atomname
[l
])==0 ) )
1052 if (l
== (*restp
)[i
].natom
)
1054 /* If we are doing an atom rename only, we don't need
1055 * to generate a fatal error if the old name is not found
1058 /* Deleting can happen also only on the input atoms,
1059 * not necessarily always on the rtp entry.
1061 if (!((*hb
)[i
].hack
[j
].oname
!= NULL
&&
1062 (*hb
)[i
].hack
[j
].nname
!= NULL
) &&
1063 !((*hb
)[i
].hack
[j
].oname
!= NULL
&&
1064 (*hb
)[i
].hack
[j
].nname
== NULL
))
1067 "atom %s not found in buiding block %d%s "
1068 "while combining tdb and rtp",
1069 (*hb
)[i
].hack
[j
].oname
!=NULL
?
1070 (*hb
)[i
].hack
[j
].oname
: (*hb
)[i
].hack
[j
].AI
,
1071 i
+1,*resinfo
[i
].rtp
);
1076 if ( (*hb
)[i
].hack
[j
].oname
==NULL
) {
1078 add_atom_to_restp(&(*restp
)[i
],resinfo
[i
].nr
,l
,
1084 if ( (*hb
)[i
].hack
[j
].nname
==NULL
) {
1085 /* we're deleting */
1087 fprintf(debug
, "deleting atom %s from res %d%s in rtp\n",
1088 *(*restp
)[i
].atomname
[l
],
1089 i
+1,(*restp
)[i
].resname
);
1090 /* shift the rest */
1091 (*restp
)[i
].natom
--;
1092 for(k
=l
; k
< (*restp
)[i
].natom
; k
++) {
1093 (*restp
)[i
].atom
[k
] = (*restp
)[i
].atom
[k
+1];
1094 (*restp
)[i
].atomname
[k
] = (*restp
)[i
].atomname
[k
+1];
1095 (*restp
)[i
].cgnr
[k
] = (*restp
)[i
].cgnr
[k
+1];
1097 /* give back space */
1098 srenew((*restp
)[i
].atom
, (*restp
)[i
].natom
);
1099 srenew((*restp
)[i
].atomname
, (*restp
)[i
].natom
);
1100 srenew((*restp
)[i
].cgnr
, (*restp
)[i
].natom
);
1101 } else { /* nname != NULL */
1102 /* we're replacing */
1104 fprintf(debug
, "replacing atom %s by %s in res %d%s in rtp\n",
1105 *(*restp
)[i
].atomname
[l
], (*hb
)[i
].hack
[j
].nname
,
1106 i
+1,(*restp
)[i
].resname
);
1107 snew( (*restp
)[i
].atomname
[l
], 1);
1108 (*restp
)[i
].atom
[l
] = *(*hb
)[i
].hack
[j
].atom
;
1109 *(*restp
)[i
].atomname
[l
] = strdup((*hb
)[i
].hack
[j
].nname
);
1110 if ( (*hb
)[i
].hack
[j
].cgnr
!= NOTSET
)
1111 (*restp
)[i
].cgnr
[l
] = (*hb
)[i
].hack
[j
].cgnr
;
1120 static gmx_bool
atomname_cmp_nr(const char *anm
,t_hack
*hack
,int *nr
)
1127 return (gmx_strcasecmp(anm
,hack
->nname
) == 0);
1131 if (isdigit(anm
[strlen(anm
)-1]))
1133 *nr
= anm
[strlen(anm
)-1] - '0';
1139 if (*nr
<= 0 || *nr
> hack
->nr
)
1145 return (strlen(anm
) == strlen(hack
->nname
) + 1 &&
1146 gmx_strncasecmp(anm
,hack
->nname
,strlen(hack
->nname
)) == 0);
1151 static gmx_bool
match_atomnames_with_rtp_atom(t_atoms
*pdba
,rvec
*x
,int atind
,
1152 t_restp
*rptr
,t_hackblock
*hbr
,
1159 char *start_at
,buf
[STRLEN
];
1161 gmx_bool bReplaceReplace
,bFoundInAdd
;
1164 oldnm
= *pdba
->atomname
[atind
];
1165 resnr
= pdba
->resinfo
[pdba
->atom
[atind
].resind
].nr
;
1168 for(j
=0; j
<hbr
->nhack
; j
++)
1170 if (hbr
->hack
[j
].oname
!= NULL
&& hbr
->hack
[j
].nname
!= NULL
&&
1171 gmx_strcasecmp(oldnm
,hbr
->hack
[j
].oname
) == 0)
1173 /* This is a replace entry. */
1174 /* Check if we are not replacing a replaced atom. */
1175 bReplaceReplace
= FALSE
;
1176 for(k
=0; k
<hbr
->nhack
; k
++) {
1178 hbr
->hack
[k
].oname
!= NULL
&& hbr
->hack
[k
].nname
!= NULL
&&
1179 gmx_strcasecmp(hbr
->hack
[k
].nname
,hbr
->hack
[j
].oname
) == 0)
1181 /* The replace in hack[j] replaces an atom that
1182 * was already replaced in hack[k], we do not want
1183 * second or higher level replaces at this stage.
1185 bReplaceReplace
= TRUE
;
1188 if (bReplaceReplace
)
1190 /* Skip this replace. */
1194 /* This atom still has the old name, rename it */
1195 newnm
= hbr
->hack
[j
].nname
;
1196 for(k
=0; k
<rptr
->natom
; k
++)
1198 if (gmx_strcasecmp(newnm
,*rptr
->atomname
[k
]) == 0)
1203 if (k
== rptr
->natom
)
1205 /* The new name is not present in the rtp.
1206 * We need to apply the replace also to the rtp entry.
1209 /* We need to find the add hack that can add this atom
1210 * to find out after which atom it should be added.
1212 bFoundInAdd
= FALSE
;
1213 for(k
=0; k
<hbr
->nhack
; k
++)
1215 if (hbr
->hack
[k
].oname
== NULL
&&
1216 hbr
->hack
[k
].nname
!= NULL
&&
1217 atomname_cmp_nr(newnm
,&hbr
->hack
[k
],&anmnr
))
1221 start_at
= hbr
->hack
[k
].a
[0];
1225 sprintf(buf
,"%s%d",hbr
->hack
[k
].nname
,anmnr
-1);
1228 for(start_nr
=0; start_nr
<rptr
->natom
; start_nr
++)
1230 if (gmx_strcasecmp(start_at
,(*rptr
->atomname
[start_nr
])) == 0)
1235 if (start_nr
== rptr
->natom
)
1237 gmx_fatal(FARGS
,"Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1238 start_at
,rptr
->resname
,newnm
);
1240 /* We can add the atom after atom start_nr */
1241 add_atom_to_restp(rptr
,resnr
,start_nr
,
1250 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'",
1252 hbr
->hack
[j
].oname
,hbr
->hack
[j
].nname
,
1259 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1260 oldnm
,rptr
->resname
,resnr
,newnm
);
1262 /* Rename the atom in pdba */
1263 snew(pdba
->atomname
[atind
],1);
1264 *pdba
->atomname
[atind
] = strdup(newnm
);
1266 else if (hbr
->hack
[j
].oname
!= NULL
&& hbr
->hack
[j
].nname
== NULL
&&
1267 gmx_strcasecmp(oldnm
,hbr
->hack
[j
].oname
) == 0)
1269 /* This is a delete entry, check if this atom is present
1270 * in the rtp entry of this residue.
1272 for(k
=0; k
<rptr
->natom
; k
++)
1274 if (gmx_strcasecmp(oldnm
,*rptr
->atomname
[k
]) == 0)
1279 if (k
== rptr
->natom
)
1281 /* This atom is not present in the rtp entry,
1282 * delete is now from the input pdba.
1286 printf("Deleting atom '%s' in residue '%s' %d\n",
1287 oldnm
,rptr
->resname
,resnr
);
1289 /* We should free the atom name,
1290 * but it might be used multiple times in the symtab.
1291 * sfree(pdba->atomname[atind]);
1293 for(k
=atind
+1; k
<pdba
->nr
; k
++)
1295 pdba
->atom
[k
-1] = pdba
->atom
[k
];
1296 pdba
->atomname
[k
-1] = pdba
->atomname
[k
];
1297 copy_rvec(x
[k
],x
[k
-1]);
1308 void match_atomnames_with_rtp(t_restp restp
[],t_hackblock hb
[],
1309 t_atoms
*pdba
,rvec
*x
,
1318 char *start_at
,buf
[STRLEN
];
1320 gmx_bool bFoundInAdd
;
1322 for(i
=0; i
<pdba
->nr
; i
++)
1324 oldnm
= *pdba
->atomname
[i
];
1325 resnr
= pdba
->resinfo
[pdba
->atom
[i
].resind
].nr
;
1326 rptr
= &restp
[pdba
->atom
[i
].resind
];
1327 for(j
=0; (j
<rptr
->natom
); j
++)
1329 if (gmx_strcasecmp(oldnm
,*(rptr
->atomname
[j
])) == 0)
1334 if (j
== rptr
->natom
)
1336 /* Not found yet, check if we have to rename this atom */
1337 if (match_atomnames_with_rtp_atom(pdba
,x
,i
,
1338 rptr
,&(hb
[pdba
->atom
[i
].resind
]),
1341 /* We deleted this atom, decrease the atom counter by 1. */
1348 #define NUM_CMAP_ATOMS 5
1349 static void gen_cmap(t_params
*psb
, t_restp
*restp
, t_atoms
*atoms
, gmx_residuetype_t rt
)
1353 int natoms
= atoms
->nr
;
1354 t_atom
*atom
= atoms
->atom
;
1355 char ***aname
= atoms
->atomname
;
1356 t_resinfo
*resinfo
= atoms
->resinfo
;
1357 int nres
= atoms
->nres
;
1359 atom_id cmap_atomid
[NUM_CMAP_ATOMS
];
1360 int cmap_chainnum
=-1, this_residue_index
;
1367 fprintf(stderr
,"Making cmap torsions...");
1369 /* End loop at nres-1, since the very last residue does not have a +N atom, and
1370 * therefore we get a valgrind invalid 4 byte read error with atom am */
1371 for(residx
=0; residx
<nres
-1; residx
++)
1373 /* Add CMAP terms from the list of CMAP interactions */
1374 for(j
=0;j
<restp
[residx
].rb
[ebtsCMAP
].nb
; j
++)
1377 /* Loop over atoms in a candidate CMAP interaction and
1378 * check that they exist, are from the same chain and are
1379 * from residues labelled as protein. */
1380 for(k
= 0; k
< NUM_CMAP_ATOMS
&& bAddCMAP
; k
++)
1382 cmap_atomid
[k
] = search_atom(restp
[residx
].rb
[ebtsCMAP
].b
[j
].a
[k
],
1383 i
,natoms
,atom
,aname
,ptr
,TRUE
);
1384 bAddCMAP
= bAddCMAP
&& (cmap_atomid
[k
] != NO_ATID
);
1387 /* This break is necessary, because cmap_atomid[k]
1388 * == NO_ATID cannot be safely used as an index
1389 * into the atom array. */
1392 this_residue_index
= atom
[cmap_atomid
[k
]].resind
;
1395 cmap_chainnum
= resinfo
[this_residue_index
].chainnum
;
1399 /* Does the residue for this atom have the same
1400 * chain number as the residues for previous
1402 bAddCMAP
= bAddCMAP
&&
1403 cmap_chainnum
== resinfo
[this_residue_index
].chainnum
;
1405 bAddCMAP
= bAddCMAP
&& gmx_residuetype_is_protein(rt
,*(resinfo
[this_residue_index
].name
));
1410 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
);
1416 while(atom
[i
].resind
<residx
+1)
1423 /* Start the next residue */
1427 scrub_charge_groups(int *cgnr
, int natoms
)
1431 for(i
=0;i
<natoms
;i
++)
1438 void pdb2top(FILE *top_file
, char *posre_fn
, char *molname
,
1439 t_atoms
*atoms
, rvec
**x
, gpp_atomtype_t atype
, t_symtab
*tab
,
1440 int nrtp
, t_restp rtp
[],
1441 t_restp
*restp
, t_hackblock
*hb
,
1442 int nterpairs
,t_hackblock
**ntdb
, t_hackblock
**ctdb
,
1443 gmx_bool bAllowMissing
,
1444 gmx_bool bVsites
, gmx_bool bVsiteAromatics
,
1445 const char *ff
, const char *ffdir
,
1447 int nssbonds
, t_ssbond
*ssbonds
,
1448 real long_bond_dist
, real short_bond_dist
,
1449 gmx_bool bDeuterate
, gmx_bool bChargeGroups
, gmx_bool bCmap
,
1450 gmx_bool bRenumRes
,gmx_bool bRTPresname
)
1456 t_params plist
[F_NRE
];
1463 gmx_residuetype_t rt
;
1466 gmx_residuetype_init(&rt
);
1469 print_resall(debug
, atoms
->nres
, restp
, atype
);
1470 dump_hb(debug
, atoms
->nres
, hb
);
1474 at2bonds(&(plist
[F_BONDS
]), hb
,
1475 atoms
->nr
, atoms
->atom
, atoms
->atomname
, atoms
->nres
, *x
,
1476 long_bond_dist
, short_bond_dist
, bAllowMissing
);
1478 /* specbonds: disulphide bonds & heme-his */
1479 do_ssbonds(&(plist
[F_BONDS
]),
1480 atoms
->nr
, atoms
->atom
, atoms
->atomname
, nssbonds
, ssbonds
,
1483 nmissat
= name2type(atoms
, &cgnr
, atype
, restp
, rt
);
1486 fprintf(stderr
,"There were %d missing atoms in molecule %s\n",
1489 gmx_fatal(FARGS
,"There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1493 /* Cleanup bonds (sort and rm doubles) */
1494 clean_bonds(&(plist
[F_BONDS
]));
1496 snew(vsite_type
,atoms
->nr
);
1497 for(i
=0; i
<atoms
->nr
; i
++)
1498 vsite_type
[i
]=NOTSET
;
1500 /* determine which atoms will be vsites and add dummy masses
1501 also renumber atom numbers in plist[0..F_NRE]! */
1502 do_vsites(nrtp
, rtp
, atype
, atoms
, tab
, x
, plist
,
1503 &vsite_type
, &cgnr
, mHmult
, bVsiteAromatics
, ffdir
);
1506 /* Make Angles and Dihedrals */
1507 fprintf(stderr
,"Generating angles, dihedrals and pairs...\n");
1508 snew(excls
,atoms
->nr
);
1509 init_nnb(&nnb
,atoms
->nr
,4);
1510 gen_nnb(&nnb
,plist
);
1511 print_nnb(&nnb
,"NNB");
1512 gen_pad(&nnb
,atoms
,restp
[0].nrexcl
,restp
[0].HH14
,
1513 plist
,excls
,hb
,restp
[0].bAlldih
,restp
[0].bRemoveDih
,
1520 gen_cmap(&(plist
[F_CMAP
]), restp
, atoms
, rt
);
1521 if (plist
[F_CMAP
].nr
> 0)
1523 fprintf(stderr
, "There are %4d cmap torsion pairs\n",
1528 /* set mass of all remaining hydrogen atoms */
1530 do_h_mass(&(plist
[F_BONDS
]),vsite_type
,atoms
,mHmult
,bDeuterate
);
1533 /* Cleanup bonds (sort and rm doubles) */
1534 /* clean_bonds(&(plist[F_BONDS]));*/
1537 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1538 " %4d pairs, %4d bonds and %4d virtual sites\n",
1539 plist
[F_PDIHS
].nr
, plist
[F_IDIHS
].nr
, plist
[F_ANGLES
].nr
,
1540 plist
[F_LJ14
].nr
, plist
[F_BONDS
].nr
,
1541 plist
[F_VSITE2
].nr
+
1542 plist
[F_VSITE3
].nr
+
1543 plist
[F_VSITE3FD
].nr
+
1544 plist
[F_VSITE3FAD
].nr
+
1545 plist
[F_VSITE3OUT
].nr
+
1546 plist
[F_VSITE4FD
].nr
+
1547 plist
[F_VSITE4FDN
].nr
);
1549 print_sums(atoms
, FALSE
);
1551 if (FALSE
== bChargeGroups
)
1553 scrub_charge_groups(cgnr
, atoms
->nr
);
1558 for(i
=0; i
<atoms
->nres
; i
++)
1560 atoms
->resinfo
[i
].nr
= i
+ 1;
1561 atoms
->resinfo
[i
].ic
= ' ';
1566 fprintf(stderr
,"Writing topology\n");
1567 /* We can copy the bonded types from the first restp,
1568 * since the types have to be identical for all residues in one molecule.
1570 for(i
=0; i
<ebtsNR
; i
++) {
1571 bts
[i
] = restp
[0].rb
[i
].type
;
1573 write_top(top_file
, posre_fn
, molname
,
1575 bts
, plist
, excls
, atype
, cgnr
, restp
[0].nrexcl
);
1579 free_t_hackblock(atoms
->nres
, &hb
);
1580 free_t_restp(atoms
->nres
, &restp
);
1581 gmx_residuetype_destroy(rt
);
1583 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1585 for (i
=0; i
<F_NRE
; i
++)
1586 sfree(plist
[i
].param
);
1587 for (i
=0; i
<atoms
->nr
; i
++)