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
)
81 for (j
=0; j
<rp
->natom
; j
++)
83 name
=*(rp
->atomname
[j
]);
87 bFound
= (bFound
|| !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 buidling 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 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
,*ptr
;
137 char buf
[STRLEN
],**desc
,*doc_dir
;
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 */
155 /* Remove the path from the ffdir name */
156 ptr
= strrchr(ffdirs
[i
],DIR_SEPARATOR
);
159 ffs
[i
] = strdup(ffdirs
[i
]);
163 ffs
[i
] = strdup(ptr
+1);
165 /* Remove the extension from the ffdir name */
166 ffs
[i
][strlen(ffs
[i
])-strlen(fflib_forcefield_dir_ext())] = '\0';
174 if (strcmp(ffs
[i
],ffsel
) == 0)
181 gmx_fatal(FARGS
,"Could not find force field '%s'",ffsel
);
187 for(i
=0; (i
<nff
); i
++)
189 sprintf(buf
,"%s%c%s",
190 ffdirs
[i
],DIR_SEPARATOR
,fflib_forcefield_doc());
191 doc_dir
= low_gmxlibfn(buf
,FALSE
);
194 /* We don't use fflib_open, because we don't want printf's */
195 fp
= ffopen(doc_dir
,"r");
196 snew(desc
[i
],STRLEN
);
197 get_a_line(fp
,desc
[i
],STRLEN
);
203 desc
[i
] = strdup(ffs
[i
]);
204 printf("%2d: %s\n",i
,ffs
[i
]);
207 for(i
=0; (i
<nff
); i
++)
209 for(j
=i
+1; (j
<nff
); j
++)
211 if ((desc
[i
][0] == '[' && desc
[j
][0] != '[') ||
212 ((desc
[i
][0] == '[' || desc
[j
][0] != '[') &&
213 strcasecmp(desc
[i
],desc
[j
]) > 0))
215 swap_strings(ffdirs
,i
,j
);
216 swap_strings(ffs
,i
,j
);
217 swap_strings(desc
,i
,j
);
222 printf("\nSelect the Force Field:\n");
223 for(i
=0; (i
<nff
); i
++)
225 printf("%2d: %s\n",i
,desc
[i
]);
232 pret
= fgets(buf
,STRLEN
,stdin
);
236 sscanf(buf
,"%d",&sel
);
239 while ( pret
==NULL
|| (sel
< 0) || (sel
>= nff
));
246 if (strlen(ffs
[sel
]) >= ff_maxlen
)
248 gmx_fatal(FARGS
,"Length of force field name (%d) >= maxlen (%d)",
249 strlen(ffs
[sel
]),ff_maxlen
);
251 strcpy(forcefield
,ffs
[sel
]);
253 if (strlen(ffdirs
[sel
]) >= ffdir_maxlen
)
255 gmx_fatal(FARGS
,"Length of force field dir (%d) >= maxlen (%d)",
256 strlen(ffdirs
[sel
]),ffdir_maxlen
);
258 strcpy(ffdir
,ffdirs
[sel
]);
260 for(i
=0; (i
<nff
); i
++)
269 static int name2type(t_atoms
*at
, int **cgnr
, gpp_atomtype_t atype
,
272 int i
,j
,prevresind
,resind
,i0
,prevcg
,cg
,curcg
;
291 aan
= get_aa_names();
293 for(i
=0; (i
<at
->nr
); i
++) {
295 if (at
->atom
[i
].resind
!= resind
) {
296 resind
= at
->atom
[i
].resind
;
297 bProt
= is_protein(aan
,*(at
->resinfo
[resind
].name
));
298 bNterm
=bProt
&& (resind
== 0);
300 nmissat
+= missing_atoms(&restp
[prevresind
],prevresind
,at
,i0
,i
);
304 if (at
->atom
[i
].m
== 0) {
306 fprintf(debug
,"atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
307 i
+1,*(at
->atomname
[i
]),curcg
,prevcg
,
308 j
==NOTSET
? NOTSET
: restp
[resind
].cgnr
[j
]);
311 name
=*(at
->atomname
[i
]);
312 j
=search_jtype(&restp
[resind
],name
,bNterm
);
313 at
->atom
[i
].type
= restp
[resind
].atom
[j
].type
;
314 at
->atom
[i
].q
= restp
[resind
].atom
[j
].q
;
315 at
->atom
[i
].m
= get_atomtype_massA(restp
[resind
].atom
[j
].type
,
317 cg
= restp
[resind
].cgnr
[j
];
318 if ( (cg
!= prevcg
) || (resind
!= prevresind
) )
322 fprintf(debug
,"atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
323 i
+1,*(at
->atomname
[i
]),curcg
,qt
,is_int(qt
));
332 at
->atom
[i
].typeB
= at
->atom
[i
].type
;
333 at
->atom
[i
].qB
= at
->atom
[i
].q
;
334 at
->atom
[i
].mB
= at
->atom
[i
].m
;
336 nmissat
+= missing_atoms(&restp
[resind
],resind
,at
,i0
,i
);
343 static void print_top_heavy_H(FILE *out
, real mHmult
)
346 fprintf(out
,"; Using deuterium instead of hydrogen\n\n");
347 else if (mHmult
== 4.0)
348 fprintf(out
,"#define HEAVY_H\n\n");
349 else if (mHmult
!= 1.0)
350 fprintf(stderr
,"WARNING: unsupported proton mass multiplier (%g) "
351 "in pdb2top\n",mHmult
);
354 void print_top_comment(FILE *out
,const char *filename
,
355 const char *generator
,bool bITP
)
359 nice_header(out
,filename
);
360 fprintf(out
,";\tThis is your %stopology file\n",bITP
? "include " : "");
361 fprintf(out
,";\tit was generated using program:\n;\t%s\n",
362 (NULL
== generator
) ? "unknown" : generator
);
363 fprintf(out
,";\twith command line:\n;\t%s\n;\n\n",command_line());
366 void print_top_header(FILE *out
,const char *filename
,
367 const char *title
,bool bITP
,const char *ffdir
,real mHmult
)
369 print_top_comment(out
,filename
,title
,bITP
);
371 print_top_heavy_H(out
, mHmult
);
372 fprintf(out
,"; Include forcefield parameters\n");
373 fprintf(out
,"#include \"%s%c%s\"\n\n",
374 ffdir
,DIR_SEPARATOR
,fflib_forcefield_itp());
377 static void print_top_posre(FILE *out
,const char *pr
)
379 fprintf(out
,"; Include Position restraint file\n");
380 fprintf(out
,"#ifdef POSRES\n");
381 fprintf(out
,"#include \"%s\"\n",pr
);
382 fprintf(out
,"#endif\n\n");
385 static void print_top_water(FILE *out
,const char *ffdir
,const char *water
)
389 fprintf(out
,"; Include water topology\n");
390 fprintf(out
,"#include \"%s%c%s.itp\"\n",ffdir
,DIR_SEPARATOR
,water
);
392 fprintf(out
,"#ifdef POSRES_WATER\n");
393 fprintf(out
,"; Position restraint for each water oxygen\n");
394 fprintf(out
,"[ position_restraints ]\n");
395 fprintf(out
,";%3s %5s %9s %10s %10s\n","i","funct","fcx","fcy","fcz");
396 fprintf(out
,"%4d %4d %10g %10g %10g\n",1,1,1000.0,1000.0,1000.0);
397 fprintf(out
,"#endif\n");
400 sprintf(buf
,"%s%c%s",ffdir
,DIR_SEPARATOR
,"ions.itp");
401 if (fflib_fexist(buf
))
403 fprintf(out
,"; Include topology for ions\n");
404 fprintf(out
,"#include \"%s%cions.itp\"\n",ffdir
,DIR_SEPARATOR
);
409 static void print_top_system(FILE *out
, const char *title
)
411 fprintf(out
,"[ %s ]\n",dir2str(d_system
));
412 fprintf(out
,"; Name\n");
413 fprintf(out
,"%s\n\n",title
[0]?title
:"Protein");
416 void print_top_mols(FILE *out
,
417 const char *title
, const char *ffdir
, const char *water
,
418 int nincl
, char **incls
, int nmol
, t_mols
*mols
)
424 fprintf(out
,"; Include chain topologies\n");
425 for (i
=0; (i
<nincl
); i
++) {
426 incl
= strrchr(incls
[i
],DIR_SEPARATOR
);
430 /* Remove the path from the include name */
433 fprintf(out
,"#include \"%s\"\n",incl
);
440 print_top_water(out
,ffdir
,water
);
442 print_top_system(out
, title
);
445 fprintf(out
,"[ %s ]\n",dir2str(d_molecules
));
446 fprintf(out
,"; %-15s %5s\n","Compound","#mols");
447 for (i
=0; (i
<nmol
); i
++)
448 fprintf(out
,"%-15s %5d\n",mols
[i
].name
,mols
[i
].nr
);
452 void write_top(FILE *out
, char *pr
,char *molname
,
453 t_atoms
*at
,bool bRTPresname
,
454 int bts
[],t_params plist
[],t_excls excls
[],
455 gpp_atomtype_t atype
,int *cgnr
, int nrexcl
)
456 /* NOTE: nrexcl is not the size of *excl! */
458 if (at
&& atype
&& cgnr
) {
459 fprintf(out
,"[ %s ]\n",dir2str(d_moleculetype
));
460 fprintf(out
,"; %-15s %5s\n","Name","nrexcl");
461 fprintf(out
,"%-15s %5d\n\n",molname
?molname
:"Protein",nrexcl
);
463 print_atoms(out
, atype
, at
, cgnr
, bRTPresname
);
464 print_bondeds(out
,at
->nr
,d_bonds
, F_BONDS
, bts
[ebtsBONDS
], plist
);
465 print_bondeds(out
,at
->nr
,d_constraints
,F_CONSTR
, 0, plist
);
466 print_bondeds(out
,at
->nr
,d_constraints
,F_CONSTRNC
, 0, plist
);
467 print_bondeds(out
,at
->nr
,d_pairs
, F_LJ14
, 0, plist
);
468 print_excl(out
,at
->nr
,excls
);
469 print_bondeds(out
,at
->nr
,d_angles
, F_ANGLES
, bts
[ebtsANGLES
],plist
);
470 print_bondeds(out
,at
->nr
,d_dihedrals
, F_PDIHS
, bts
[ebtsPDIHS
], plist
);
471 print_bondeds(out
,at
->nr
,d_dihedrals
, F_IDIHS
, bts
[ebtsIDIHS
], plist
);
472 print_bondeds(out
,at
->nr
,d_cmap
, F_CMAP
, bts
[ebtsCMAP
], plist
);
473 print_bondeds(out
,at
->nr
,d_polarization
,F_POLARIZATION
, 0, plist
);
474 print_bondeds(out
,at
->nr
,d_thole_polarization
,F_THOLE_POL
,0, plist
);
475 print_bondeds(out
,at
->nr
,d_vsites2
, F_VSITE2
, 0, plist
);
476 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3
, 0, plist
);
477 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3FD
, 0, plist
);
478 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3FAD
,0, plist
);
479 print_bondeds(out
,at
->nr
,d_vsites3
, F_VSITE3OUT
,0, plist
);
480 print_bondeds(out
,at
->nr
,d_vsites4
, F_VSITE4FD
, 0, plist
);
481 print_bondeds(out
,at
->nr
,d_vsites4
, F_VSITE4FDN
, 0, plist
);
484 print_top_posre(out
,pr
);
488 static atom_id
search_res_atom(const char *type
,int resind
,
489 int natom
,t_atom at
[],
490 char ** const *aname
,
491 const char *bondtype
,bool bAllowMissing
)
495 for(i
=0; (i
<natom
); i
++)
496 if (at
[i
].resind
== resind
)
497 return search_atom(type
,i
,natom
,at
,aname
,bondtype
,bAllowMissing
);
502 static void do_ssbonds(t_params
*ps
,int natoms
,t_atom atom
[],char **aname
[],
503 int nssbonds
,t_ssbond
*ssbonds
,bool bAllowMissing
)
508 for(i
=0; (i
<nssbonds
); i
++) {
509 ri
= ssbonds
[i
].res1
;
510 rj
= ssbonds
[i
].res2
;
511 ai
= search_res_atom(ssbonds
[i
].a1
,ri
,natoms
,atom
,aname
,
512 "special bond",bAllowMissing
);
513 aj
= search_res_atom(ssbonds
[i
].a2
,rj
,natoms
,atom
,aname
,
514 "special bond",bAllowMissing
);
515 if ((ai
== NO_ATID
) || (aj
== NO_ATID
))
516 gmx_fatal(FARGS
,"Trying to make impossible special bond (%s-%s)!",
517 ssbonds
[i
].a1
,ssbonds
[i
].a2
);
518 add_param(ps
,ai
,aj
,NULL
,NULL
);
522 static bool inter_res_bond(const t_rbonded
*b
)
524 return (b
->AI
[0] == '-' || b
->AI
[0] == '+' ||
525 b
->AJ
[0] == '-' || b
->AJ
[0] == '+');
528 static void at2bonds(t_params
*psb
, t_hackblock
*hb
,
529 int natoms
, t_atom atom
[], char **aname
[],
531 real long_bond_dist
, real short_bond_dist
,
536 real dist2
, long_bond_dist2
, short_bond_dist2
;
539 long_bond_dist2
= sqr(long_bond_dist
);
540 short_bond_dist2
= sqr(short_bond_dist
);
547 fprintf(stderr
,"Making bonds...\n");
549 for(resind
=0; (resind
< nres
) && (i
<natoms
); resind
++) {
550 /* add bonds from list of bonded interactions */
551 for(j
=0; j
< hb
[resind
].rb
[ebtsBONDS
].nb
; j
++) {
552 /* Unfortunately we can not issue errors or warnings
553 * for missing atoms in bonds, as the hydrogens and terminal atoms
554 * have not been added yet.
556 ai
=search_atom(hb
[resind
].rb
[ebtsBONDS
].b
[j
].AI
,i
,natoms
,atom
,aname
,
558 aj
=search_atom(hb
[resind
].rb
[ebtsBONDS
].b
[j
].AJ
,i
,natoms
,atom
,aname
,
560 if (ai
!= NO_ATID
&& aj
!= NO_ATID
) {
561 dist2
= distance2(x
[ai
],x
[aj
]);
562 if (dist2
> long_bond_dist2
)
564 fprintf(stderr
,"Warning: Long Bond (%d-%d = %g nm)\n",
565 ai
+1,aj
+1,sqrt(dist2
));
567 else if (dist2
< short_bond_dist2
)
569 fprintf(stderr
,"Warning: Short Bond (%d-%d = %g nm)\n",
570 ai
+1,aj
+1,sqrt(dist2
));
572 add_param(psb
,ai
,aj
,NULL
,hb
[resind
].rb
[ebtsBONDS
].b
[j
].s
);
575 /* add bonds from list of hacks (each added atom gets a bond) */
576 while( (i
<natoms
) && (atom
[i
].resind
== resind
) ) {
577 for(j
=0; j
< hb
[resind
].nhack
; j
++)
578 if ( ( hb
[resind
].hack
[j
].tp
> 0 ||
579 hb
[resind
].hack
[j
].oname
==NULL
) &&
580 strcmp(hb
[resind
].hack
[j
].AI
,*(aname
[i
])) == 0 ) {
581 switch(hb
[resind
].hack
[j
].tp
) {
582 case 9: /* COOH terminus */
583 add_param(psb
,i
,i
+1,NULL
,NULL
); /* C-O */
584 add_param(psb
,i
,i
+2,NULL
,NULL
); /* C-OA */
585 add_param(psb
,i
+2,i
+3,NULL
,NULL
); /* OA-H */
588 for(k
=0; (k
<hb
[resind
].hack
[j
].nr
); k
++)
589 add_param(psb
,i
,i
+k
+1,NULL
,NULL
);
594 /* we're now at the start of the next residue */
598 static int pcompar(const void *a
, const void *b
)
609 return strlen(pb
->s
) - strlen(pa
->s
);
614 static void clean_bonds(t_params
*ps
)
620 /* swap atomnumbers in bond if first larger than second: */
621 for(i
=0; (i
<ps
->nr
); i
++)
622 if ( ps
->param
[i
].AJ
< ps
->param
[i
].AI
) {
624 ps
->param
[i
].AI
= ps
->param
[i
].AJ
;
629 qsort(ps
->param
,ps
->nr
,(size_t)sizeof(ps
->param
[0]),pcompar
);
631 /* remove doubles, keep the first one always. */
633 for(i
=1; (i
<ps
->nr
); i
++) {
634 if ((ps
->param
[i
].AI
!= ps
->param
[j
-1].AI
) ||
635 (ps
->param
[i
].AJ
!= ps
->param
[j
-1].AJ
) ) {
636 cp_param(&(ps
->param
[j
]),&(ps
->param
[i
]));
640 fprintf(stderr
,"Number of bonds was %d, now %d\n",ps
->nr
,j
);
644 fprintf(stderr
,"No bonds\n");
647 void print_sums(t_atoms
*atoms
, bool bSystem
)
660 for(i
=0; (i
<atoms
->nr
); i
++) {
662 qtot
+=atoms
->atom
[i
].q
;
665 fprintf(stderr
,"Total mass%s %.3f a.m.u.\n",where
,m
);
666 fprintf(stderr
,"Total charge%s %.3f e\n",where
,qtot
);
669 static void check_restp_type(const char *name
,int t1
,int t2
)
673 gmx_fatal(FARGS
,"Residues in one molecule have a different '%s' type: %d and %d",name
,t1
,t2
);
677 static void check_restp_types(t_restp
*r0
,t_restp
*r1
)
681 check_restp_type("all dihedrals",r0
->bAlldih
,r1
->bAlldih
);
682 check_restp_type("nrexcl",r0
->nrexcl
,r1
->nrexcl
);
683 check_restp_type("HH14",r0
->HH14
,r1
->HH14
);
684 check_restp_type("remove dihedrals",r0
->bRemoveDih
,r1
->bRemoveDih
);
686 for(i
=0; i
<ebtsNR
; i
++)
688 check_restp_type(btsNames
[i
],r0
->rb
[i
].type
,r1
->rb
[i
].type
);
692 void add_atom_to_restp(t_restp
*restp
,int resnr
,int at_start
,const t_hack
*hack
)
696 const char *Hnum
="123456";
700 fprintf(debug,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
702 *restp->atomname[at_start], resnr, restp->resname);
704 strcpy(buf
, hack
->nname
);
705 buf
[strlen(buf
)+1]='\0';
708 buf
[strlen(buf
)]='-';
711 restp
->natom
+= hack
->nr
;
712 srenew(restp
->atom
, restp
->natom
);
713 srenew(restp
->atomname
, restp
->natom
);
714 srenew(restp
->cgnr
, restp
->natom
);
716 for(k
=restp
->natom
-1; k
> at_start
+hack
->nr
; k
--)
719 restp
->atom
[k
- hack
->nr
];
721 restp
->atomname
[k
- hack
->nr
];
723 restp
->cgnr
[k
- hack
->nr
];
726 for(k
=0; k
< hack
->nr
; k
++)
728 /* set counter in atomname */
731 buf
[strlen(buf
)-1] = Hnum
[k
];
733 snew( restp
->atomname
[at_start
+1+k
], 1);
734 restp
->atom
[at_start
+1+k
] = *hack
->atom
;
735 *restp
->atomname
[at_start
+1+k
] = strdup(buf
);
736 if ( hack
->cgnr
!= NOTSET
)
738 restp
->cgnr
[at_start
+1+k
] = hack
->cgnr
;
742 restp
->cgnr
[at_start
+1+k
] = restp
->cgnr
[at_start
];
747 void get_hackblocks_rtp(t_hackblock
**hb
, t_restp
**restp
,
748 int nrtp
, t_restp rtp
[],
749 int nres
, t_resinfo
*resinfo
,
751 t_hackblock
**ntdb
, t_hackblock
**ctdb
,
757 const char *Hnum
="123456";
763 /* first the termini */
764 for(i
=0; i
<nterpairs
; i
++) {
765 if (rn
[i
] >= 0 && ntdb
[i
] != NULL
) {
766 copy_t_hackblock(ntdb
[i
], &(*hb
)[rn
[i
]]);
768 if (rc
[i
] >= 0 && ctdb
[i
] != NULL
) {
769 merge_t_hackblock(ctdb
[i
], &(*hb
)[rc
[i
]]);
773 /* then the whole rtp */
774 for(i
=0; i
< nres
; i
++) {
775 res
= search_rtp(*resinfo
[i
].rtp
,nrtp
,rtp
);
776 copy_t_restp(res
, &(*restp
)[i
]);
778 /* Check that we do not have different bonded types in one molecule */
779 check_restp_types(&(*restp
)[0],&(*restp
)[i
]);
782 for(j
=0; j
<nterpairs
&& tern
==-1; j
++) {
788 for(j
=0; j
<nterpairs
&& terc
== -1; j
++) {
793 bRM
= merge_t_bondeds(res
->rb
, (*hb
)[i
].rb
,tern
>=0,terc
>=0);
795 if (bRM
&& ((tern
>= 0 && ntdb
[tern
] == NULL
) ||
796 (terc
>= 0 && ctdb
[terc
] == NULL
))) {
797 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.");
799 if (bRM
&& ((tern
>= 0 && ntdb
[tern
]->nhack
== 0) ||
800 (terc
>= 0 && ctdb
[terc
]->nhack
== 0))) {
801 gmx_fatal(FARGS
,"There is a dangling bond at at least one of the terminal ends. Select a proper terminal entry.");
805 /* now perform t_hack's on t_restp's,
806 i.e. add's and deletes from termini database will be
807 added to/removed from residue topology
808 we'll do this on one big dirty loop, so it won't make easy reading! */
809 for(i
=0; i
< nres
; i
++)
811 for(j
=0; j
< (*hb
)[i
].nhack
; j
++)
813 if ( (*hb
)[i
].hack
[j
].nr
)
815 /* find atom in restp */
816 for(l
=0; l
< (*restp
)[i
].natom
; l
++)
817 if ( ( (*hb
)[i
].hack
[j
].oname
==NULL
&&
818 strcmp((*hb
)[i
].hack
[j
].AI
, *(*restp
)[i
].atomname
[l
])==0 ) ||
819 ( (*hb
)[i
].hack
[j
].oname
!=NULL
&&
820 strcmp((*hb
)[i
].hack
[j
].oname
,*(*restp
)[i
].atomname
[l
])==0 ) )
822 if (l
== (*restp
)[i
].natom
)
824 /* If we are doing an atom rename only, we don't need
825 * to generate a fatal error if the old name is not found
828 /* Deleting can happen also only on the input atoms,
829 * not necessarily always on the rtp entry.
831 if (!((*hb
)[i
].hack
[j
].oname
!= NULL
&&
832 (*hb
)[i
].hack
[j
].nname
!= NULL
) &&
833 !((*hb
)[i
].hack
[j
].oname
!= NULL
&&
834 (*hb
)[i
].hack
[j
].nname
== NULL
))
837 "atom %s not found in buiding block %d%s "
838 "while combining tdb and rtp",
839 (*hb
)[i
].hack
[j
].oname
!=NULL
?
840 (*hb
)[i
].hack
[j
].oname
: (*hb
)[i
].hack
[j
].AI
,
841 i
+1,*resinfo
[i
].rtp
);
846 if ( (*hb
)[i
].hack
[j
].oname
==NULL
) {
848 add_atom_to_restp(&(*restp
)[i
],resinfo
[i
].nr
,l
,
854 if ( (*hb
)[i
].hack
[j
].nname
==NULL
) {
857 fprintf(debug
, "deleting atom %s from res %d%s in rtp\n",
858 *(*restp
)[i
].atomname
[l
],
859 i
+1,(*restp
)[i
].resname
);
862 for(k
=l
; k
< (*restp
)[i
].natom
; k
++) {
863 (*restp
)[i
].atom
[k
] = (*restp
)[i
].atom
[k
+1];
864 (*restp
)[i
].atomname
[k
] = (*restp
)[i
].atomname
[k
+1];
865 (*restp
)[i
].cgnr
[k
] = (*restp
)[i
].cgnr
[k
+1];
867 /* give back space */
868 srenew((*restp
)[i
].atom
, (*restp
)[i
].natom
);
869 srenew((*restp
)[i
].atomname
, (*restp
)[i
].natom
);
870 srenew((*restp
)[i
].cgnr
, (*restp
)[i
].natom
);
871 } else { /* nname != NULL */
872 /* we're replacing */
874 fprintf(debug
, "replacing atom %s by %s in res %d%s in rtp\n",
875 *(*restp
)[i
].atomname
[l
], (*hb
)[i
].hack
[j
].nname
,
876 i
+1,(*restp
)[i
].resname
);
877 snew( (*restp
)[i
].atomname
[l
], 1);
878 (*restp
)[i
].atom
[l
] = *(*hb
)[i
].hack
[j
].atom
;
879 *(*restp
)[i
].atomname
[l
] = strdup((*hb
)[i
].hack
[j
].nname
);
880 if ( (*hb
)[i
].hack
[j
].cgnr
!= NOTSET
)
881 (*restp
)[i
].cgnr
[l
] = (*hb
)[i
].hack
[j
].cgnr
;
890 static bool atomname_cmp_nr(const char *anm
,t_hack
*hack
,int *nr
)
897 return (strcasecmp(anm
,hack
->nname
) == 0);
901 if (isdigit(anm
[strlen(anm
)-1]))
903 *nr
= anm
[strlen(anm
)-1] - '0';
909 if (*nr
<= 0 || *nr
> hack
->nr
)
915 return (strlen(anm
) == strlen(hack
->nname
) + 1 &&
916 strncasecmp(anm
,hack
->nname
,strlen(hack
->nname
)) == 0);
921 static bool match_atomnames_with_rtp_atom(t_atoms
*pdba
,int atind
,
922 t_restp
*rptr
,t_hackblock
*hbr
,
929 char *start_at
,buf
[STRLEN
];
931 bool bReplaceReplace
,bFoundInAdd
;
934 oldnm
= *pdba
->atomname
[atind
];
935 resnr
= pdba
->resinfo
[pdba
->atom
[atind
].resind
].nr
;
938 for(j
=0; j
<hbr
->nhack
; j
++)
940 if (hbr
->hack
[j
].oname
!= NULL
&& hbr
->hack
[j
].nname
!= NULL
&&
941 strcasecmp(oldnm
,hbr
->hack
[j
].oname
) == 0)
943 /* This is a replace entry. */
944 /* Check if we are not replacing a replaced atom. */
945 bReplaceReplace
= FALSE
;
946 for(k
=0; k
<hbr
->nhack
; k
++) {
948 hbr
->hack
[k
].oname
!= NULL
&& hbr
->hack
[k
].nname
!= NULL
&&
949 strcasecmp(hbr
->hack
[k
].nname
,hbr
->hack
[j
].oname
) == 0)
951 /* The replace in hack[j] replaces an atom that
952 * was already replaced in hack[k], we do not want
953 * second or higher level replaces at this stage.
955 bReplaceReplace
= TRUE
;
960 /* Skip this replace. */
964 /* This atom still has the old name, rename it */
965 newnm
= hbr
->hack
[j
].nname
;
966 for(k
=0; k
<rptr
->natom
; k
++)
968 if (strcasecmp(newnm
,*rptr
->atomname
[k
]) == 0)
973 if (k
== rptr
->natom
)
975 /* The new name is not present in the rtp.
976 * We need to apply the replace also to the rtp entry.
979 /* We need to find the add hack that can add this atom
980 * to find out after which atom it should be added.
983 for(k
=0; k
<hbr
->nhack
; k
++)
985 if (hbr
->hack
[k
].oname
== NULL
&&
986 hbr
->hack
[k
].nname
!= NULL
&&
987 atomname_cmp_nr(newnm
,&hbr
->hack
[k
],&anmnr
))
991 start_at
= hbr
->hack
[k
].a
[0];
995 sprintf(buf
,"%s%d",hbr
->hack
[k
].nname
,anmnr
-1);
998 for(start_nr
=0; start_nr
<rptr
->natom
; start_nr
++)
1000 if (strcasecmp(start_at
,(*rptr
->atomname
[start_nr
])) == 0)
1005 if (start_nr
== rptr
->natom
)
1007 gmx_fatal(FARGS
,"Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1008 start_at
,rptr
->resname
,newnm
);
1010 /* We can add the atom after atom start_nr */
1011 add_atom_to_restp(rptr
,resnr
,start_nr
,
1020 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'",
1022 hbr
->hack
[j
].oname
,hbr
->hack
[j
].nname
,
1029 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1030 oldnm
,rptr
->resname
,resnr
,newnm
);
1032 /* Rename the atom in pdba */
1033 snew(pdba
->atomname
[atind
],1);
1034 *pdba
->atomname
[atind
] = strdup(newnm
);
1036 else if (hbr
->hack
[j
].oname
!= NULL
&& hbr
->hack
[j
].nname
== NULL
&&
1037 strcasecmp(oldnm
,hbr
->hack
[j
].oname
) == 0)
1039 /* This is a delete entry, check if this atom is present
1040 * in the rtp entry of this residue.
1042 for(k
=0; k
<rptr
->natom
; k
++)
1044 if (strcasecmp(oldnm
,*rptr
->atomname
[k
]) == 0)
1049 if (k
== rptr
->natom
)
1051 /* This atom is not present in the rtp entry,
1052 * delete is now from the input pdba.
1056 printf("Deleting atom '%s' in residue '%s' %d\n",
1057 oldnm
,rptr
->resname
,resnr
);
1059 sfree(pdba
->atomname
[atind
]);
1060 for(k
=atind
+1; k
<pdba
->nr
; k
++)
1062 pdba
->atom
[k
-1] = pdba
->atom
[k
];
1063 pdba
->atomname
[k
-1] = pdba
->atomname
[k
];
1074 void match_atomnames_with_rtp(t_restp restp
[],t_hackblock hb
[],
1084 char *start_at
,buf
[STRLEN
];
1088 for(i
=0; i
<pdba
->nr
; i
++)
1090 oldnm
= *pdba
->atomname
[i
];
1091 resnr
= pdba
->resinfo
[pdba
->atom
[i
].resind
].nr
;
1092 rptr
= &restp
[pdba
->atom
[i
].resind
];
1093 for(j
=0; (j
<rptr
->natom
); j
++)
1095 if (strcasecmp(oldnm
,*(rptr
->atomname
[j
])) == 0)
1100 if (j
== rptr
->natom
)
1102 /* Not found yet, check if we have to rename this atom */
1103 if (match_atomnames_with_rtp_atom(pdba
,i
,
1104 rptr
,&(hb
[pdba
->atom
[i
].resind
]),
1107 /* We deleted this atom, decrease the atom counter by 1. */
1114 void gen_cmap(t_params
*psb
, t_restp
*restp
, int natoms
, t_atom atom
[], char **aname
[], int nres
)
1116 int residx
,i
,ii
,j
,k
;
1117 atom_id ai
,aj
,ak
,al
,am
;
1125 fprintf(stderr
,"Making cmap torsions...");
1127 /* End loop at nres-1, since the very last residue does not have a +N atom, and
1128 * therefore we get a valgrind invalid 4 byte read error with atom am */
1129 for(residx
=0; residx
<nres
-1; residx
++)
1131 /* Add CMAP terms from the list of CMAP interactions */
1132 for(j
=0;j
<restp
[residx
].rb
[ebtsCMAP
].nb
; j
++)
1134 ai
=search_atom(restp
[residx
].rb
[ebtsCMAP
].b
[j
].a
[0],i
,natoms
,atom
,aname
,
1136 aj
=search_atom(restp
[residx
].rb
[ebtsCMAP
].b
[j
].a
[1],i
,natoms
,atom
,aname
,
1138 ak
=search_atom(restp
[residx
].rb
[ebtsCMAP
].b
[j
].a
[2],i
,natoms
,atom
,aname
,
1140 al
=search_atom(restp
[residx
].rb
[ebtsCMAP
].b
[j
].a
[3],i
,natoms
,atom
,aname
,
1142 am
=search_atom(restp
[residx
].rb
[ebtsCMAP
].b
[j
].a
[4],i
,natoms
,atom
,aname
,
1145 /* The first and last residues no not have cmap torsions */
1146 if(ai
!=NO_ATID
&& aj
!=NO_ATID
&& ak
!=NO_ATID
&& al
!=NO_ATID
&& am
!=NO_ATID
)
1148 add_cmap_param(psb
,ai
,aj
,ak
,al
,am
,restp
[residx
].rb
[ebtsCMAP
].b
[j
].s
);
1154 while(atom
[i
].resind
<residx
+1)
1161 /* Start the next residue */
1165 scrub_charge_groups(int *cgnr
, int natoms
)
1169 for(i
=0;i
<natoms
;i
++)
1176 void pdb2top(FILE *top_file
, char *posre_fn
, char *molname
,
1177 t_atoms
*atoms
, rvec
**x
, gpp_atomtype_t atype
, t_symtab
*tab
,
1178 int nrtp
, t_restp rtp
[],
1179 t_restp
*restp
, t_hackblock
*hb
,
1180 int nterpairs
,t_hackblock
**ntdb
, t_hackblock
**ctdb
,
1181 int *rn
, int *rc
, bool bAllowMissing
,
1182 bool bVsites
, bool bVsiteAromatics
,
1183 const char *ff
, const char *ffdir
, real mHmult
,
1184 int nssbonds
, t_ssbond
*ssbonds
,
1185 real long_bond_dist
, real short_bond_dist
,
1186 bool bDeuterate
, bool bChargeGroups
, bool bCmap
,
1187 bool bRenumRes
,bool bRTPresname
)
1193 t_params plist
[F_NRE
];
1204 print_resall(debug
, atoms
->nres
, restp
, atype
);
1205 dump_hb(debug
, atoms
->nres
, hb
);
1209 at2bonds(&(plist
[F_BONDS
]), hb
,
1210 atoms
->nr
, atoms
->atom
, atoms
->atomname
, atoms
->nres
, *x
,
1211 long_bond_dist
, short_bond_dist
, bAllowMissing
);
1213 /* specbonds: disulphide bonds & heme-his */
1214 do_ssbonds(&(plist
[F_BONDS
]),
1215 atoms
->nr
, atoms
->atom
, atoms
->atomname
, nssbonds
, ssbonds
,
1218 nmissat
= name2type(atoms
, &cgnr
, atype
, restp
);
1221 fprintf(stderr
,"There were %d missing atoms in molecule %s\n",
1224 gmx_fatal(FARGS
,"There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1228 /* Cleanup bonds (sort and rm doubles) */
1229 clean_bonds(&(plist
[F_BONDS
]));
1231 snew(vsite_type
,atoms
->nr
);
1232 for(i
=0; i
<atoms
->nr
; i
++)
1233 vsite_type
[i
]=NOTSET
;
1235 /* determine which atoms will be vsites and add dummy masses
1236 also renumber atom numbers in plist[0..F_NRE]! */
1237 do_vsites(nrtp
, rtp
, atype
, atoms
, tab
, x
, plist
,
1238 &vsite_type
, &cgnr
, mHmult
, bVsiteAromatics
, ffdir
);
1241 /* Make Angles and Dihedrals */
1242 fprintf(stderr
,"Generating angles, dihedrals and pairs...\n");
1243 snew(excls
,atoms
->nr
);
1244 init_nnb(&nnb
,atoms
->nr
,4);
1245 gen_nnb(&nnb
,plist
);
1246 print_nnb(&nnb
,"NNB");
1247 gen_pad(&nnb
,atoms
,restp
[0].nrexcl
,restp
[0].HH14
,
1248 plist
,excls
,hb
,restp
[0].bAlldih
,restp
[0].bRemoveDih
,
1255 gen_cmap(&(plist
[F_CMAP
]), restp
, atoms
->nr
, atoms
->atom
, atoms
->atomname
, atoms
->nres
);
1256 if (plist
[F_CMAP
].nr
> 0)
1258 fprintf(stderr
, "There are %4d cmap torsion pairs\n",
1263 /* set mass of all remaining hydrogen atoms */
1265 do_h_mass(&(plist
[F_BONDS
]),vsite_type
,atoms
,mHmult
,bDeuterate
);
1268 /* Cleanup bonds (sort and rm doubles) */
1269 /* clean_bonds(&(plist[F_BONDS]));*/
1272 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1273 " %4d pairs, %4d bonds and %4d virtual sites\n",
1274 plist
[F_PDIHS
].nr
, plist
[F_IDIHS
].nr
, plist
[F_ANGLES
].nr
,
1275 plist
[F_LJ14
].nr
, plist
[F_BONDS
].nr
,
1276 plist
[F_VSITE2
].nr
+
1277 plist
[F_VSITE3
].nr
+
1278 plist
[F_VSITE3FD
].nr
+
1279 plist
[F_VSITE3FAD
].nr
+
1280 plist
[F_VSITE3OUT
].nr
+
1281 plist
[F_VSITE4FD
].nr
+
1282 plist
[F_VSITE4FDN
].nr
);
1284 print_sums(atoms
, FALSE
);
1286 if (FALSE
== bChargeGroups
)
1288 scrub_charge_groups(cgnr
, atoms
->nr
);
1293 for(i
=0; i
<atoms
->nres
; i
++)
1295 atoms
->resinfo
[i
].nr
= i
+ 1;
1296 atoms
->resinfo
[i
].ic
= ' ';
1301 fprintf(stderr
,"Writing topology\n");
1302 /* We can copy the bonded types from the first restp,
1303 * since the types have to be identical for all residues in one molecule.
1305 for(i
=0; i
<ebtsNR
; i
++) {
1306 bts
[i
] = restp
[0].rb
[i
].type
;
1308 write_top(top_file
, posre_fn
, molname
,
1310 bts
, plist
, excls
, atype
, cgnr
, restp
[0].nrexcl
);
1314 free_t_hackblock(atoms
->nres
, &hb
);
1315 free_t_restp(atoms
->nres
, &restp
);
1317 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1319 for (i
=0; i
<F_NRE
; i
++)
1320 sfree(plist
[i
].param
);
1321 for (i
=0; i
<atoms
->nr
; i
++)