Added a comment to gen_cmap to clarify ending a for-loop
[gromacs.git] / src / kernel / pdb2top.c
blob005d6763fb5f7e656e1be68c777dda851a8be588
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <stdio.h>
40 #include <math.h>
41 #include <ctype.h>
42 #include "vec.h"
43 #include "copyrite.h"
44 #include "smalloc.h"
45 #include "macros.h"
46 #include "symtab.h"
47 #include "futil.h"
48 #include "gmx_fatal.h"
49 #include "pdb2top.h"
50 #include "gpp_nextnb.h"
51 #include "topdirs.h"
52 #include "toputil.h"
53 #include "h_db.h"
54 #include "pgutil.h"
55 #include "resall.h"
56 #include "topio.h"
57 #include "string2.h"
58 #include "physics.h"
59 #include "pdbio.h"
60 #include "gen_ad.h"
61 #include "filenm.h"
62 #include "index.h"
63 #include "gen_vsite.h"
64 #include "add_par.h"
65 #include "toputil.h"
67 /* this must correspond to enum in pdb2top.h */
68 const char *hh[ehisNR] = { "HISA", "HISB", "HISH", "HIS1" };
70 static int missing_atoms(t_restp *rp, int resind,
71 t_atoms *at, int i0, int i, bool bCTer)
73 int j,k,nmiss;
74 char *name;
75 bool bFound, bRet;
77 nmiss = 0;
78 for (j=0; j<rp->natom; j++) {
79 name=*(rp->atomname[j]);
80 /* if ((name[0]!='H') && (name[0]!='h') && (!bCTer || (name[0]!='O'))) { */
81 bFound=FALSE;
82 for (k=i0; k<i; k++)
83 bFound=(bFound || !strcasecmp(*(at->atomname[k]),name));
84 if (!bFound) {
85 nmiss++;
86 fprintf(stderr,"\nWARNING: "
87 "atom %s is missing in residue %s %d in the pdb file\n",
88 name,*(at->resinfo[resind].name),at->resinfo[resind].nr);
89 if (name[0]=='H' || name[0]=='h')
90 fprintf(stderr," You might need to add atom %s to the hydrogen database of residue %s\n"
91 " in the file ff???.hdb (see the manual)\n",
92 name,*(at->resinfo[resind].name));
93 fprintf(stderr,"\n");
95 /* } */
98 return nmiss;
101 bool is_int(double x)
103 const double tol = 1e-4;
104 int ix;
106 if (x < 0)
107 x=-x;
108 ix=gmx_nint(x);
110 return (fabs(x-ix) < tol);
113 typedef struct { char *desc,*fn; } t_fff;
115 void
116 choose_ff(char *forcefield, int maxlen)
118 FILE *in;
119 t_fff *fff;
120 int i,nff,sel;
121 char *c,buf[STRLEN],fn[32];
122 char *pret;
124 in=libopen("FF.dat");
125 fgets2(buf,255,in);
126 sscanf(buf,"%d",&nff);
127 snew(fff,nff);
128 for(i=0; (i<nff); i++) {
129 fgets2(buf,255,in);
130 sscanf(buf,"%s",fn);
131 fff[i].fn=strdup(fn);
132 /* Search for next non-space character, there starts description */
133 c=&(buf[strlen(fn)+1]);
134 while (isspace(*c)) c++;
135 fff[i].desc=strdup(c);
137 fclose(in);
139 if (nff > 1) {
140 printf("\nSelect the Force Field:\n");
141 for(i=0; (i<nff); i++)
142 printf("%2d: %s\n",i,fff[i].desc);
143 do {
144 pret = fgets(buf,STRLEN,stdin);
146 if(pret != NULL)
147 sscanf(buf,"%d",&sel);
148 } while ( pret==NULL || (sel < 0) || (sel >= nff));
150 else
151 sel=0;
153 strncpy(forcefield,fff[sel].fn,maxlen);
155 for(i=0; (i<nff); i++) {
156 sfree(fff[i].desc);
157 sfree(fff[i].fn);
159 sfree(fff);
164 static int name2type(t_atoms *at, int **cgnr, gpp_atomtype_t atype,
165 t_restp restp[])
167 int i,j,prevresind,resind,i0,prevcg,cg,curcg;
168 char *name;
169 bool bProt, bNterm;
170 double qt;
171 int nmissat;
172 t_aa_names *aan;
174 nmissat = 0;
176 resind=-1;
177 bProt=FALSE;
178 bNterm=FALSE;
179 i0=0;
180 snew(*cgnr,at->nr);
181 qt=0;
182 prevcg=NOTSET;
183 curcg=0;
184 cg=-1;
185 j=NOTSET;
186 aan = get_aa_names();
188 for(i=0; (i<at->nr); i++) {
189 prevresind=resind;
190 if (at->atom[i].resind != resind) {
191 resind = at->atom[i].resind;
192 bProt = is_protein(aan,*(at->resinfo[resind].name));
193 bNterm=bProt && (resind == 0);
194 if (resind > 0)
195 nmissat +=
196 missing_atoms(&restp[prevresind],prevresind,at,i0,i,
197 (!bProt && is_protein(aan,restp[prevresind].resname)));
198 i0=i;
200 if (at->atom[i].m == 0) {
201 if (debug)
202 fprintf(debug,"atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
203 i+1,*(at->atomname[i]),curcg,prevcg,
204 j==NOTSET ? NOTSET : restp[resind].cgnr[j]);
205 qt=0;
206 prevcg=cg;
207 name=*(at->atomname[i]);
208 j=search_jtype(&restp[resind],name,bNterm);
209 at->atom[i].type = restp[resind].atom[j].type;
210 at->atom[i].q = restp[resind].atom[j].q;
211 at->atom[i].m = get_atomtype_massA(restp[resind].atom[j].type,
212 atype);
213 cg = restp[resind].cgnr[j];
214 if ( (cg != prevcg) || (resind != prevresind) )
215 curcg++;
216 } else {
217 if (debug)
218 fprintf(debug,"atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
219 i+1,*(at->atomname[i]),curcg,qt,is_int(qt));
220 cg=-1;
221 if (is_int(qt)) {
222 qt=0;
223 curcg++;
225 qt+=at->atom[i].q;
227 (*cgnr)[i]=curcg;
228 at->atom[i].typeB = at->atom[i].type;
229 at->atom[i].qB = at->atom[i].q;
230 at->atom[i].mB = at->atom[i].m;
232 nmissat += missing_atoms(&restp[resind],resind,at,i0,i,
233 (!bProt || is_protein(aan,restp[resind].resname)));
234 done_aa_names(&aan);
236 return nmissat;
239 static void print_top_heavy_H(FILE *out, real mHmult)
241 if (mHmult == 2.0)
242 fprintf(out,"; Using deuterium instead of hydrogen\n\n");
243 else if (mHmult == 4.0)
244 fprintf(out,"#define HEAVY_H\n\n");
245 else if (mHmult != 1.0)
246 fprintf(stderr,"WARNING: unsupported proton mass multiplier (%g) "
247 "in pdb2top\n",mHmult);
250 void print_top_comment(FILE *out,const char *filename,const char *title,bool bITP)
252 char tmp[256];
254 nice_header(out,filename);
255 fprintf(out,";\tThis is your %stopology file\n",bITP ? "include " : "");
256 cool_quote(tmp,255,NULL);
257 fprintf(out,";\t%s\n",title[0]?title:tmp);
258 fprintf(out,";\n");
261 void print_top_header(FILE *out,const char *filename,
262 const char *title,bool bITP,const char *ff,real mHmult)
264 print_top_comment(out,filename,title,bITP);
266 print_top_heavy_H(out, mHmult);
267 fprintf(out,"; Include forcefield parameters\n");
268 fprintf(out,"#include \"%s.itp\"\n\n",ff);
271 static void print_top_posre(FILE *out,const char *pr)
273 fprintf(out,"; Include Position restraint file\n");
274 fprintf(out,"#ifdef POSRES\n");
275 fprintf(out,"#include \"%s\"\n",pr);
276 fprintf(out,"#endif\n\n");
279 static void print_top_water(FILE *out,const char *water)
281 fprintf(out,"; Include water topology\n");
282 fprintf(out,"#include \"%s.itp\"\n",water);
283 fprintf(out,"\n");
284 fprintf(out,"#ifdef POSRES_WATER\n");
285 fprintf(out,"; Position restraint for each water oxygen\n");
286 fprintf(out,"[ position_restraints ]\n");
287 fprintf(out,";%3s %5s %9s %10s %10s\n","i","funct","fcx","fcy","fcz");
288 fprintf(out,"%4d %4d %10g %10g %10g\n",1,1,1000.0,1000.0,1000.0);
289 fprintf(out,"#endif\n\n");
290 fprintf(out,"; Include generic topology for ions\n");
291 fprintf(out,"#include \"ions.itp\"\n");
292 fprintf(out,"\n");
295 static void print_top_system(FILE *out, const char *title)
297 fprintf(out,"[ %s ]\n",dir2str(d_system));
298 fprintf(out,"; Name\n");
299 fprintf(out,"%s\n\n",title[0]?title:"Protein");
302 void print_top_mols(FILE *out, const char *title, const char *water,
303 int nincl, char **incls, int nmol, t_mols *mols)
305 int i;
307 if (nincl>0) {
308 fprintf(out,"; Include chain topologies\n");
309 for (i=0; (i<nincl); i++)
310 fprintf(out,"#include \"%s\"\n",incls[i]);
311 fprintf(out,"\n");
314 if (water)
315 print_top_water(out,water);
316 print_top_system(out, title);
318 if (nmol) {
319 fprintf(out,"[ %s ]\n",dir2str(d_molecules));
320 fprintf(out,"; %-15s %5s\n","Compound","#mols");
321 for (i=0; (i<nmol); i++)
322 fprintf(out,"%-15s %5d\n",mols[i].name,mols[i].nr);
326 void write_top(FILE *out, char *pr,char *molname,
327 t_atoms *at,int bts[],t_params plist[],t_excls excls[],
328 gpp_atomtype_t atype,int *cgnr, int nrexcl)
329 /* NOTE: nrexcl is not the size of *excl! */
331 if (at && atype && cgnr) {
332 fprintf(out,"[ %s ]\n",dir2str(d_moleculetype));
333 fprintf(out,"; %-15s %5s\n","Name","nrexcl");
334 fprintf(out,"%-15s %5d\n\n",molname?molname:"Protein",nrexcl);
336 print_atoms(out, atype, at, cgnr);
337 print_bondeds(out,at->nr,d_bonds, F_BONDS, bts[ebtsBONDS], plist);
338 print_bondeds(out,at->nr,d_constraints,F_CONSTR, 0, plist);
339 print_bondeds(out,at->nr,d_constraints,F_CONSTRNC, 0, plist);
340 print_bondeds(out,at->nr,d_pairs, F_LJ14, 0, plist);
341 print_excl(out,at->nr,excls);
342 print_bondeds(out,at->nr,d_angles, F_ANGLES, bts[ebtsANGLES],plist);
343 print_bondeds(out,at->nr,d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist);
344 print_bondeds(out,at->nr,d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist);
345 print_bondeds(out,at->nr,d_cmap, F_CMAP, bts[ebtsCMAP], plist);
346 print_bondeds(out,at->nr,d_polarization,F_POLARIZATION, 0, plist);
347 print_bondeds(out,at->nr,d_thole_polarization,F_THOLE_POL,0, plist);
348 print_bondeds(out,at->nr,d_vsites2, F_VSITE2, 0, plist);
349 print_bondeds(out,at->nr,d_vsites3, F_VSITE3, 0, plist);
350 print_bondeds(out,at->nr,d_vsites3, F_VSITE3FD, 0, plist);
351 print_bondeds(out,at->nr,d_vsites3, F_VSITE3FAD,0, plist);
352 print_bondeds(out,at->nr,d_vsites3, F_VSITE3OUT,0, plist);
353 print_bondeds(out,at->nr,d_vsites4, F_VSITE4FD, 0, plist);
354 print_bondeds(out,at->nr,d_vsites4, F_VSITE4FDN, 0, plist);
356 if (pr)
357 print_top_posre(out,pr);
361 static atom_id search_res_atom(const char *type,int resind,
362 int natom,t_atom at[],
363 char ** const *aname,
364 const char *bondtype,bool bMissing)
366 int i;
368 for(i=0; (i<natom); i++)
369 if (at[i].resind == resind)
370 return search_atom(type,i,natom,at,aname,bondtype,bMissing);
372 return NO_ATID;
375 static void do_ssbonds(t_params *ps,int natoms,t_atom atom[],char **aname[],
376 int nssbonds,t_ssbond *ssbonds,bool bMissing)
378 int i,ri,rj;
379 atom_id ai,aj;
381 for(i=0; (i<nssbonds); i++) {
382 ri = ssbonds[i].res1;
383 rj = ssbonds[i].res2;
384 ai = search_res_atom(ssbonds[i].a1,ri,natoms,atom,aname,
385 "special bond",bMissing);
386 aj = search_res_atom(ssbonds[i].a2,rj,natoms,atom,aname,
387 "special bond",bMissing);
388 if ((ai == NO_ATID) || (aj == NO_ATID))
389 gmx_fatal(FARGS,"Trying to make impossible special bond (%s-%s)!",
390 ssbonds[i].a1,ssbonds[i].a2);
391 add_param(ps,ai,aj,NULL,NULL);
395 static void at2bonds(t_params *psb, t_hackblock *hb,
396 int natoms, t_atom atom[], char **aname[],
397 int nres, rvec x[],
398 real long_bond_dist, real short_bond_dist)
400 int resind,i,j,k;
401 atom_id ai,aj;
402 real dist2, long_bond_dist2, short_bond_dist2;
403 const char *ptr;
405 long_bond_dist2 = sqr(long_bond_dist);
406 short_bond_dist2 = sqr(short_bond_dist);
408 if (debug)
409 ptr = "bond";
410 else
411 ptr = "check";
413 fprintf(stderr,"Making bonds...\n");
414 i=0;
415 for(resind=0; (resind < nres) && (i<natoms); resind++) {
416 /* add bonds from list of bonded interactions */
417 for(j=0; j < hb[resind].rb[ebtsBONDS].nb; j++) {
418 /* Unfortunately we can not issue errors or warnings
419 * for missing atoms in bonds, as the hydrogens and terminal atoms
420 * have not been added yet.
422 ai=search_atom(hb[resind].rb[ebtsBONDS].b[j].AI,i,natoms,atom,aname,
423 ptr,TRUE);
424 aj=search_atom(hb[resind].rb[ebtsBONDS].b[j].AJ,i,natoms,atom,aname,
425 ptr,TRUE);
426 if (ai != NO_ATID && aj != NO_ATID) {
427 dist2 = distance2(x[ai],x[aj]);
428 if (dist2 > long_bond_dist2 )
429 fprintf(stderr,"Warning: Long Bond (%d-%d = %g nm)\n",
430 ai+1,aj+1,sqrt(dist2));
431 else if (dist2 < short_bond_dist2 )
432 fprintf(stderr,"Warning: Short Bond (%d-%d = %g nm)\n",
433 ai+1,aj+1,sqrt(dist2));
434 add_param(psb,ai,aj,NULL,hb[resind].rb[ebtsBONDS].b[j].s);
437 /* add bonds from list of hacks (each added atom gets a bond) */
438 while( (i<natoms) && (atom[i].resind == resind) ) {
439 for(j=0; j < hb[resind].nhack; j++)
440 if ( ( hb[resind].hack[j].tp > 0 ||
441 hb[resind].hack[j].oname==NULL ) &&
442 strcmp(hb[resind].hack[j].AI,*(aname[i])) == 0 ) {
443 switch(hb[resind].hack[j].tp) {
444 case 9: /* COOH terminus */
445 add_param(psb,i,i+1,NULL,NULL); /* C-O */
446 add_param(psb,i,i+2,NULL,NULL); /* C-OA */
447 add_param(psb,i+2,i+3,NULL,NULL); /* OA-H */
448 break;
449 default:
450 for(k=0; (k<hb[resind].hack[j].nr); k++)
451 add_param(psb,i,i+k+1,NULL,NULL);
454 i++;
456 /* we're now at the start of the next residue */
460 static int pcompar(const void *a, const void *b)
462 t_param *pa,*pb;
463 int d;
464 pa=(t_param *)a;
465 pb=(t_param *)b;
467 d = pa->AI - pb->AI;
468 if (d == 0)
469 d = pa->AJ - pb->AJ;
470 if (d == 0)
471 return strlen(pb->s) - strlen(pa->s);
472 else
473 return d;
476 static void clean_bonds(t_params *ps)
478 int i,j;
479 atom_id a;
481 if (ps->nr > 0) {
482 /* swap atomnumbers in bond if first larger than second: */
483 for(i=0; (i<ps->nr); i++)
484 if ( ps->param[i].AJ < ps->param[i].AI ) {
485 a = ps->param[i].AI;
486 ps->param[i].AI = ps->param[i].AJ;
487 ps->param[i].AJ = a;
490 /* Sort bonds */
491 qsort(ps->param,ps->nr,(size_t)sizeof(ps->param[0]),pcompar);
493 /* remove doubles, keep the first one always. */
494 j = 1;
495 for(i=1; (i<ps->nr); i++) {
496 if ((ps->param[i].AI != ps->param[j-1].AI) ||
497 (ps->param[i].AJ != ps->param[j-1].AJ) ) {
498 cp_param(&(ps->param[j]),&(ps->param[i]));
499 j++;
502 fprintf(stderr,"Number of bonds was %d, now %d\n",ps->nr,j);
503 ps->nr=j;
505 else
506 fprintf(stderr,"No bonds\n");
509 void print_sums(t_atoms *atoms, bool bSystem)
511 double m,qtot;
512 int i;
513 const char *where;
515 if (bSystem)
516 where=" in system";
517 else
518 where="";
520 m=0;
521 qtot=0;
522 for(i=0; (i<atoms->nr); i++) {
523 m+=atoms->atom[i].m;
524 qtot+=atoms->atom[i].q;
527 fprintf(stderr,"Total mass%s %.3f a.m.u.\n",where,m);
528 fprintf(stderr,"Total charge%s %.3f e\n",where,qtot);
531 static void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
532 int nrtp, t_restp rtp[],
533 int nres, t_resinfo *resinfo,
534 int nterpairs,
535 t_hackblock **ntdb, t_hackblock **ctdb,
536 int *rn, int *rc)
538 int i, j, k, l;
539 t_restp *res;
540 char buf[STRLEN];
541 const char *Hnum="123456";
542 bool bN,bC;
544 snew(*hb,nres);
545 snew(*restp,nres);
546 /* first the termini */
547 for(i=0; i<nterpairs; i++) {
548 if (rn[i]>=0)
549 copy_t_hackblock(ntdb[i], &(*hb)[rn[i]]);
550 if (rc[i]>=0)
551 merge_t_hackblock(ctdb[i], &(*hb)[rc[i]]);
554 /* then the whole rtp */
555 for(i=0; i < nres; i++) {
556 res = search_rtp(*resinfo[i].name,nrtp,rtp);
557 copy_t_restp(res, &(*restp)[i]);
558 bN = FALSE;
559 for(j=0; j<nterpairs && !bN; j++)
560 bN = i==rn[j];
561 bC = FALSE;
562 for(j=0; j<nterpairs && !bC; j++)
563 bC = i==rc[j];
564 merge_t_bondeds(res->rb, (*hb)[i].rb,bN,bC);
567 /* now perform t_hack's on t_restp's,
568 i.e. add's and deletes from termini database will be
569 added to/removed from residue topology
570 we'll do this on one big dirty loop, so it won't make easy reading! */
571 for(i=0; i < nres; i++)
572 for(j=0; j < (*hb)[i].nhack; j++)
573 if ( (*hb)[i].hack[j].nr ) {
574 /* find atom in restp */
575 for(l=0; l < (*restp)[i].natom; l++)
576 if ( ( (*hb)[i].hack[j].oname==NULL &&
577 strcmp((*hb)[i].hack[j].AI, *(*restp)[i].atomname[l])==0 ) ||
578 ( (*hb)[i].hack[j].oname!=NULL &&
579 strcmp((*hb)[i].hack[j].oname,*(*restp)[i].atomname[l])==0 ) )
580 break;
581 if (l == (*restp)[i].natom)
582 gmx_fatal(FARGS,"atom %s not found in residue %d%s "
583 "while combining tdb and rtp",
584 (*hb)[i].hack[j].oname!=NULL ?
585 (*hb)[i].hack[j].oname : (*hb)[i].hack[j].AI,
586 i+1,*resinfo[i].name);
587 if ( (*hb)[i].hack[j].oname==NULL ) {
588 /* we're adding: */
589 if (debug)
590 fprintf(debug,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
591 (*hb)[i].hack[j].nname,
592 *(*restp)[i].atomname[l], i+1, (*restp)[i].resname);
593 strcpy(buf, (*hb)[i].hack[j].nname);
594 buf[strlen(buf)+1]='\0';
595 if ( (*hb)[i].hack[j].nr > 1 )
596 buf[strlen(buf)]='-';
597 /* make space */
598 (*restp)[i].natom += (*hb)[i].hack[j].nr;
599 srenew((*restp)[i].atom, (*restp)[i].natom);
600 srenew((*restp)[i].atomname, (*restp)[i].natom);
601 srenew((*restp)[i].cgnr, (*restp)[i].natom);
602 /* shift the rest */
603 for(k=(*restp)[i].natom-1; k > l+(*hb)[i].hack[j].nr; k--) {
604 (*restp)[i].atom[k] =
605 (*restp)[i].atom [k - (*hb)[i].hack[j].nr];
606 (*restp)[i].atomname[k] =
607 (*restp)[i].atomname[k - (*hb)[i].hack[j].nr];
608 (*restp)[i].cgnr[k] =
609 (*restp)[i].cgnr [k - (*hb)[i].hack[j].nr];
611 /* now add them */
612 for(k=0; k < (*hb)[i].hack[j].nr; k++) {
613 /* set counter in atomname */
614 if ( (*hb)[i].hack[j].nr > 1 )
615 buf[strlen(buf)-1]=Hnum[k];
616 snew( (*restp)[i].atomname[l+1+k], 1);
617 (*restp)[i].atom [l+1+k] = *(*hb)[i].hack[j].atom;
618 *(*restp)[i].atomname[l+1+k] = strdup(buf);
619 if ( (*hb)[i].hack[j].cgnr != NOTSET )
620 (*restp)[i].cgnr [l+1+k] = (*hb)[i].hack[j].cgnr;
621 else
622 (*restp)[i].cgnr [l+1+k] = (*restp)[i].cgnr[l];
624 } else /* oname != NULL */
625 if ( (*hb)[i].hack[j].nname==NULL ) {
626 /* we're deleting */
627 if (debug)
628 fprintf(debug, "deleting atom %s from res %d%s in rtp\n",
629 *(*restp)[i].atomname[l],
630 i+1,(*restp)[i].resname);
631 /* shift the rest */
632 (*restp)[i].natom--;
633 for(k=l; k < (*restp)[i].natom; k++) {
634 (*restp)[i].atom [k] = (*restp)[i].atom [k+1];
635 (*restp)[i].atomname[k] = (*restp)[i].atomname[k+1];
636 (*restp)[i].cgnr [k] = (*restp)[i].cgnr [k+1];
638 /* give back space */
639 srenew((*restp)[i].atom, (*restp)[i].natom);
640 srenew((*restp)[i].atomname, (*restp)[i].natom);
641 srenew((*restp)[i].cgnr, (*restp)[i].natom);
642 } else { /* nname != NULL */
643 /* we're replacing */
644 if (debug)
645 fprintf(debug, "replacing atom %s by %s in res %d%s in rtp\n",
646 *(*restp)[i].atomname[l], (*hb)[i].hack[j].nname,
647 i+1,(*restp)[i].resname);
648 snew( (*restp)[i].atomname[l], 1);
649 (*restp)[i].atom[l] = *(*hb)[i].hack[j].atom;
650 *(*restp)[i].atomname[l] = strdup((*hb)[i].hack[j].nname);
651 if ( (*hb)[i].hack[j].cgnr != NOTSET )
652 (*restp)[i].cgnr [l] = (*hb)[i].hack[j].cgnr;
657 void gen_cmap(t_params *psb, t_restp *restp, int natoms, t_atom atom[], char **aname[], int nres)
659 int residx,i,ii,j,k;
660 atom_id ai,aj,ak,al,am;
661 const char *ptr;
663 if (debug)
664 ptr = "cmap";
665 else
666 ptr = "check";
668 fprintf(stderr,"Making cmap torsions...");
669 i=0;
670 /* End loop at nres-1, since the very last residue does not have a +N atom, and
671 * therefore we get a valgrind invalid 4 byte read error with atom am */
672 for(residx=0; residx<nres-1; residx++)
674 /* Add CMAP terms from the list of CMAP interactions */
675 for(j=0;j<restp[residx].rb[ebtsCMAP].nb; j++)
677 ai=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[0],i,natoms,atom,aname,
678 ptr,TRUE);
679 aj=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[1],i,natoms,atom,aname,
680 ptr,TRUE);
681 ak=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[2],i,natoms,atom,aname,
682 ptr,TRUE);
683 al=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[3],i,natoms,atom,aname,
684 ptr,TRUE);
685 am=search_atom(restp[residx].rb[ebtsCMAP].b[j].a[4],i,natoms,atom,aname,
686 ptr,TRUE);
688 /* The first and last residues no not have cmap torsions */
689 if(ai!=NO_ATID && aj!=NO_ATID && ak!=NO_ATID && al!=NO_ATID && am!=NO_ATID)
691 add_cmap_param(psb,ai,aj,ak,al,am,0,0,restp[residx].rb[ebtsCMAP].b[j].s);
695 if(residx<nres-1)
697 while(atom[i].resind<residx+1)
699 i++;
704 /* Start the next residue */
707 static void
708 scrub_charge_groups(int *cgnr, int natoms)
710 int i;
712 for(i=0;i<natoms;i++)
714 cgnr[i]=i+1;
719 void pdb2top(FILE *top_file, char *posre_fn, char *molname,
720 t_atoms *atoms, rvec **x, gpp_atomtype_t atype, t_symtab *tab,
721 int bts[], int nrtp, t_restp rtp[],
722 int nterpairs,t_hackblock **ntdb, t_hackblock **ctdb,
723 int *rn, int *rc, bool bMissing,
724 bool bH14, bool bAlldih, bool bRemoveDih,
725 bool bVsites, bool bVsiteAromatics, char *ff, real mHmult,
726 int nssbonds, t_ssbond *ssbonds, int nrexcl,
727 real long_bond_dist, real short_bond_dist,
728 bool bDeuterate, bool bChargeGroups)
730 t_hackblock *hb;
731 t_restp *restp;
732 t_params plist[F_NRE];
733 t_excls *excls;
734 t_nextnb nnb;
735 int *cgnr;
736 int *vsite_type;
737 int i,nmissat;
739 init_plist(plist);
741 /* lookup hackblocks and rtp for all residues */
742 get_hackblocks_rtp(&hb, &restp, nrtp, rtp, atoms->nres, atoms->resinfo,
743 nterpairs, ntdb, ctdb, rn, rc);
744 /* ideally, now we would not need the rtp itself anymore, but do
745 everything using the hb and restp arrays. Unfortunately, that
746 requires some re-thinking of code in gen_vsite.c, which I won't
747 do now :( AF 26-7-99 */
749 if (debug) {
750 print_resall(debug, bts, atoms->nres, restp, atype,bAlldih,nrexcl,
751 bH14,bRemoveDih);
752 dump_hb(debug, atoms->nres, hb);
755 /* Make bonds */
756 at2bonds(&(plist[F_BONDS]), hb,
757 atoms->nr, atoms->atom, atoms->atomname, atoms->nres, *x,
758 long_bond_dist, short_bond_dist);
760 /* specbonds: disulphide bonds & heme-his */
761 do_ssbonds(&(plist[F_BONDS]),
762 atoms->nr, atoms->atom, atoms->atomname, nssbonds, ssbonds,
763 bMissing);
765 nmissat = name2type(atoms, &cgnr, atype, restp);
766 if (nmissat) {
767 if (bMissing)
768 fprintf(stderr,"There were %d missing atoms in molecule %s\n",
769 nmissat,molname);
770 else
771 gmx_fatal(FARGS,"There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
772 nmissat,molname);
775 /* Cleanup bonds (sort and rm doubles) */
776 clean_bonds(&(plist[F_BONDS]));
778 snew(vsite_type,atoms->nr);
779 for(i=0; i<atoms->nr; i++)
780 vsite_type[i]=NOTSET;
781 if (bVsites)
782 /* determine which atoms will be vsites and add dummy masses
783 also renumber atom numbers in plist[0..F_NRE]! */
784 do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
785 &vsite_type, &cgnr, mHmult, bVsiteAromatics, ff);
787 /* Make Angles and Dihedrals */
788 fprintf(stderr,"Generating angles, dihedrals and pairs...\n");
789 snew(excls,atoms->nr);
790 init_nnb(&nnb,atoms->nr,4);
791 gen_nnb(&nnb,plist);
792 print_nnb(&nnb,"NNB");
793 gen_pad(&nnb,atoms,nrexcl,bH14,plist,excls,hb,bAlldih,bRemoveDih,bMissing);
794 done_nnb(&nnb);
796 /* Make CMAP */
797 gen_cmap(&(plist[F_CMAP]), restp, atoms->nr, atoms->atom, atoms->atomname, atoms->nres);
798 fprintf(stderr, "there are %4d cmap torsions\n",plist[F_CMAP].nr);
800 /* set mass of all remaining hydrogen atoms */
801 if (mHmult != 1.0)
802 do_h_mass(&(plist[F_BONDS]),vsite_type,atoms,mHmult,bDeuterate);
803 sfree(vsite_type);
805 /* Cleanup bonds (sort and rm doubles) */
806 /* clean_bonds(&(plist[F_BONDS]));*/
808 fprintf(stderr,
809 "There are %4d dihedrals, %4d impropers, %4d angles\n"
810 " %4d pairs, %4d bonds and %4d virtual sites\n",
811 plist[F_PDIHS].nr, plist[F_IDIHS].nr, plist[F_ANGLES].nr,
812 plist[F_LJ14].nr, plist[F_BONDS].nr,
813 plist[F_VSITE2].nr +
814 plist[F_VSITE3].nr +
815 plist[F_VSITE3FD].nr +
816 plist[F_VSITE3FAD].nr +
817 plist[F_VSITE3OUT].nr +
818 plist[F_VSITE4FD].nr +
819 plist[F_VSITE4FDN].nr );
821 print_sums(atoms, FALSE);
823 if (FALSE == bChargeGroups)
825 scrub_charge_groups(cgnr, atoms->nr);
828 if (top_file) {
829 fprintf(stderr,"Writing topology\n");
830 write_top(top_file, posre_fn, molname,
831 atoms, bts, plist, excls, atype, cgnr, nrexcl);
834 /* cleaning up */
835 free_t_hackblock(atoms->nres, &hb);
836 free_t_restp(atoms->nres, &restp);
838 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
839 sfree(cgnr);
840 for (i=0; i<F_NRE; i++)
841 sfree(plist[i].param);
842 for (i=0; i<atoms->nr; i++)
843 sfree(excls[i].e);
844 sfree(excls);