4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_pdb2top_c
= "$Id$";
57 /* this must correspond to enum in pdb2top.h */
58 char *hh
[ehisNR
] = { "HISA", "HISB", "HISH", "HIS1" };
60 static bool missing_atoms(t_restp
*rp
, int resnr
,
61 t_atoms
*at
, int i0
, int i
, bool bCTer
)
68 for (j
=0; j
<rp
->natom
; j
++) {
69 name
=*(rp
->atomname
[j
]);
70 if ((name
[0]!='H') && (name
[0]!='h') && (!bCTer
|| (name
[0]!='O'))) {
73 bFound
=(bFound
|| !strcasecmp(*(at
->atomname
[k
]),name
));
76 fprintf(stderr
,"\nWARNING: "
77 "atom %s is missing in residue %s %d in the pdb file\n\n",
78 name
,*(at
->resname
[resnr
]),resnr
+1);
88 const double tol
= 1e-4;
95 return (fabs(x
-ix
) < tol
);
100 typedef struct { char *desc
,*fn
; } t_fff
;
105 char *c
,buf
[STRLEN
],fn
[32];
107 in
=libopen("FF.dat");
109 sscanf(buf
,"%d",&nff
);
111 for(i
=0; (i
<nff
); i
++) {
114 fff
[i
].fn
=strdup(fn
);
115 /* Search for next non-space character, there starts description */
116 c
=&(buf
[strlen(fn
)+1]);
117 while (isspace(*c
)) c
++;
118 fff
[i
].desc
=strdup(c
);
123 printf("\nSelect the Force Field:\n");
124 for(i
=0; (i
<nff
); i
++)
125 printf("%2d: %s\n",i
,fff
[i
].desc
);
127 fgets(buf
,STRLEN
,stdin
);
128 sscanf(buf
,"%d",&sel
);
129 } while ((sel
< 0) || (sel
>= nff
));
134 fnsel
=strdup(fff
[sel
].fn
);
136 for(i
=0; (i
<nff
); i
++) {
145 static void name2type(t_atoms
*at
, int **cgnr
, t_atomtype
*atype
,
148 int i
,j
,prevresnr
,resnr
,i0
,prevcg
,cg
,curcg
;
163 for(i
=0; (i
<at
->nr
); i
++) {
165 if (at
->atom
[i
].resnr
!= resnr
) {
166 resnr
=at
->atom
[i
].resnr
;
167 bProt
=is_protein(*(at
->resname
[resnr
]));
168 bNterm
=bProt
&& (resnr
== 0);
170 missing_atoms(&restp
[prevresnr
],resnr
,at
,i0
,i
,
171 (!bProt
&& is_protein(restp
[prevresnr
].resname
)));
174 if (at
->atom
[i
].m
== 0) {
176 fprintf(debug
,"atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
177 i
+1,*(at
->atomname
[i
]),curcg
,prevcg
,
178 j
==NOTSET
? NOTSET
: restp
[resnr
].cgnr
[j
]);
181 name
=*(at
->atomname
[i
]);
182 j
=search_jtype(&restp
[resnr
],name
,bNterm
);
183 at
->atom
[i
].type
= restp
[resnr
].atom
[j
].type
;
184 at
->atom
[i
].q
= restp
[resnr
].atom
[j
].q
;
185 at
->atom
[i
].m
= atype
->atom
[restp
[resnr
].atom
[j
].type
].m
;
186 cg
= restp
[resnr
].cgnr
[j
];
187 if ( (cg
!= prevcg
) || (resnr
!= prevresnr
) )
191 fprintf(debug
,"atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
192 i
+1,*(at
->atomname
[i
]),curcg
,qt
,is_int(qt
));
201 at
->atom
[i
].typeB
= at
->atom
[i
].type
;
202 at
->atom
[i
].qB
= at
->atom
[i
].q
;
203 at
->atom
[i
].mB
= at
->atom
[i
].m
;
205 missing_atoms(&restp
[resnr
],resnr
,at
,i0
,i
,
206 (!bProt
|| is_protein(restp
[resnr
].resname
)));
209 static void print_top_heavy_H(FILE *out
, real mHmult
)
212 fprintf(out
,"; heavy hydrogens:\n");
214 fprintf(out
,"#define HEAVY_H\n\n");
216 fprintf(stderr
,"WARNING: unsupported proton mass multiplier (%g) "
217 "in pdb2top\n",mHmult
);
221 void print_top_comment(FILE *out
, char *title
, bool bITP
)
223 fprintf(out
,"; This is your %stopology file\n",bITP
? "include " : "");
224 fprintf(out
,"; %s\n\n",title
[0]?title
:cool_quote());
227 void print_top_header(FILE *out
, char *title
, bool bITP
, char *ff
, real mHmult
)
229 print_top_comment(out
,title
,bITP
);
231 print_top_heavy_H(out
, mHmult
);
232 fprintf(out
,"; Include forcefield parameters\n");
233 fprintf(out
,"#include \"%s.itp\"\n\n",ff
);
236 static void print_top_posre(FILE *out
,char *pr
)
238 fprintf(out
,"; Include Position restraint file\n");
239 fprintf(out
,"#ifdef POSRES\n");
240 fprintf(out
,"#include \"%s\"\n",pr
);
241 fprintf(out
,"#endif\n\n");
244 static void print_top_water(FILE *out
)
246 fprintf(out
,"; Include water topology\n");
247 fprintf(out
,"#ifdef FLEX_SPC\n");
248 fprintf(out
,"#include \"flexspc.itp\"\n");
249 fprintf(out
,"#else\n");
250 fprintf(out
,"#include \"spc.itp\"\n");
251 fprintf(out
,"#endif\n");
253 fprintf(out
,"#ifdef POSRES_WATER\n");
254 fprintf(out
,"; Position restraint for each water oxygen\n");
255 fprintf(out
,"[ position_restraints ]\n");
256 fprintf(out
,";%3s %5s %9s %10s %10s\n","i","funct","fcx","fcy","fcz");
257 fprintf(out
,"%4d %4d %10g %10g %10g\n",1,1,1000.0,1000.0,1000.0);
258 fprintf(out
,"#endif\n");
262 static void print_top_system(FILE *out
, char *title
)
264 fprintf(out
,"[ %s ]\n",dir2str(d_system
));
265 fprintf(out
,"; Name\n");
266 fprintf(out
,"%s\n\n",title
[0]?title
:"Protein");
269 void print_top_mols(FILE *out
, char *title
,
270 int nincl
, char **incls
, int nmol
, t_mols
*mols
)
275 fprintf(out
,"; Include chain topologies\n");
276 for (i
=0; (i
<nincl
); i
++)
277 fprintf(out
,"#include \"%s\"\n",incls
[i
]);
281 print_top_water(out
);
282 print_top_system(out
, title
);
285 fprintf(out
,"[ %s ]\n",dir2str(d_molecules
));
286 fprintf(out
,"; %-15s %5s\n","Compound","#mols");
287 for (i
=0; (i
<nmol
); i
++)
288 fprintf(out
,"%-15s %5d\n",mols
[i
].name
,mols
[i
].nr
);
292 void write_top(FILE *out
, char *pr
,char *molname
,
293 t_atoms
*at
,int bts
[],t_params plist
[],t_block
*excl
,
294 t_atomtype
*atype
,int *cgnr
, int nrexcl
)
295 /* NOTE: nrexcl is not the size of *excl! */
297 if (at
&& atype
&& cgnr
) {
298 fprintf(out
,"[ %s ]\n",dir2str(d_moleculetype
));
299 fprintf(out
,"; %-15s %5s\n","Name","nrexcl");
300 fprintf(out
,"%-15s %5d\n\n",molname
?molname
:"Protein",nrexcl
);
302 print_atoms(out
, atype
, at
, cgnr
);
303 print_bondeds(out
,at
->nr
,d_bonds
, F_BONDS
, bts
[ebtsBONDS
], plist
);
304 print_bondeds(out
,at
->nr
,d_constraints
,F_SHAKE
, 0, plist
);
305 print_bondeds(out
,at
->nr
,d_constraints
,F_SHAKENC
, 0, plist
);
306 print_bondeds(out
,at
->nr
,d_pairs
, F_LJ14
, 0, plist
);
307 print_bondeds(out
,at
->nr
,d_angles
, F_ANGLES
, bts
[ebtsANGLES
],plist
);
308 print_bondeds(out
,at
->nr
,d_dihedrals
, F_PDIHS
, bts
[ebtsPDIHS
], plist
);
309 print_bondeds(out
,at
->nr
,d_dihedrals
, F_IDIHS
, bts
[ebtsIDIHS
], plist
);
310 print_bondeds(out
,at
->nr
,d_dum3
, F_DUMMY3
, 0, plist
);
311 print_bondeds(out
,at
->nr
,d_dum3
, F_DUMMY3FD
, 0, plist
);
312 print_bondeds(out
,at
->nr
,d_dum3
, F_DUMMY3FAD
,0, plist
);
313 print_bondeds(out
,at
->nr
,d_dum3
, F_DUMMY3OUT
,0, plist
);
314 print_bondeds(out
,at
->nr
,d_dum4
, F_DUMMY4FD
, 0, plist
);
316 if ( excl
&& excl
->nr
> 0 )
317 print_excl(out
,excl
);
320 print_top_posre(out
,pr
);
324 static atom_id
search_res_atom(char *type
,int resnr
,
325 int natom
,t_atom at
[],char **aname
[])
329 for(i
=0; (i
<natom
); i
++)
330 if (at
[i
].resnr
== resnr
)
331 return search_atom(type
,i
,natom
,at
,aname
);
336 static void do_ssbonds(t_params
*ps
,int natoms
,t_atom atom
[],char **aname
[],
337 int nssbonds
,t_ssbond
*ssbonds
)
342 for(i
=0; (i
<nssbonds
); i
++) {
343 ri
= ssbonds
[i
].res1
;
344 rj
= ssbonds
[i
].res2
;
345 ai
= search_res_atom(ssbonds
[i
].a1
,ri
,natoms
,atom
,aname
);
346 aj
= search_res_atom(ssbonds
[i
].a2
,rj
,natoms
,atom
,aname
);
347 if ((ai
== NO_ATID
) || (aj
== NO_ATID
))
348 fatal_error(0,"Trying to make impossible special bond (%s-%s)!",
349 ssbonds
[i
].a1
,ssbonds
[i
].a2
);
350 add_param(ps
,ai
,aj
,NULL
,NULL
);
354 static void at2bonds(t_params
*psb
, t_hackblock
*hb
,
355 int natoms
, t_atom atom
[], char **aname
[],
357 real long_bond_dist
, real short_bond_dist
)
361 real dist2
, long_bond_dist2
, short_bond_dist2
;
363 long_bond_dist2
= sqr(long_bond_dist
);
364 short_bond_dist2
= sqr(short_bond_dist
);
366 fprintf(stderr
,"Making bonds...\n");
368 for(resnr
=0; (resnr
< nres
) && (i
<natoms
); resnr
++) {
369 /* add bonds from list of bonded interactions */
370 for(j
=0; j
< hb
[resnr
].rb
[ebtsBONDS
].nb
; j
++) {
371 ai
=search_atom(hb
[resnr
].rb
[ebtsBONDS
].b
[j
].AI
,i
,natoms
,atom
,aname
);
372 aj
=search_atom(hb
[resnr
].rb
[ebtsBONDS
].b
[j
].AJ
,i
,natoms
,atom
,aname
);
373 if ( ai
!= NO_ATID
&& aj
!= NO_ATID
) {
374 dist2
= distance2(x
[ai
],x
[aj
]);
375 if (dist2
> long_bond_dist2
)
376 fprintf(stderr
,"Warning: Long Bond (%d-%d = %g nm)\n",
377 ai
+1,aj
+1,sqrt(dist2
));
378 else if (dist2
< short_bond_dist2
)
379 fprintf(stderr
,"Warning: Short Bond (%d-%d = %g nm)\n",
380 ai
+1,aj
+1,sqrt(dist2
));
381 add_param(psb
,ai
,aj
,NULL
,hb
[resnr
].rb
[ebtsBONDS
].b
[j
].s
);
384 /* add bonds from list of hacks (each added atom gets a bond) */
385 while( (i
<natoms
) && (atom
[i
].resnr
== resnr
) ) {
386 for(j
=0; j
< hb
[resnr
].nhack
; j
++)
387 if ( ( hb
[resnr
].hack
[j
].tp
> 0 ||
388 hb
[resnr
].hack
[j
].oname
==NULL
) &&
389 strcmp(hb
[resnr
].hack
[j
].AI
,*(aname
[i
])) == 0 ) {
390 switch(hb
[resnr
].hack
[j
].tp
) {
391 case 9: /* COOH terminus */
392 add_param(psb
,i
,i
+1,NULL
,NULL
); /* C-O */
393 add_param(psb
,i
,i
+2,NULL
,NULL
); /* C-OA */
394 add_param(psb
,i
+2,i
+3,NULL
,NULL
); /* OA-H */
397 for(k
=0; (k
<hb
[resnr
].hack
[j
].nr
); k
++)
398 add_param(psb
,i
,i
+k
+1,NULL
,NULL
);
403 /* we're now at the start of the next residue */
407 static int pcompar(const void *a
, const void *b
)
418 /* we'll keep the first bond in the list,
419 doing inverse sort will put the bond with the longest string first */
420 d
= -strcmp(pa
->s
, pb
->s
);
425 static void clean_bonds(t_params
*ps
)
431 /* swap atomnumbers in bond if first larger than second: */
432 for(i
=0; (i
<ps
->nr
); i
++)
433 if ( ps
->param
[i
].AJ
< ps
->param
[i
].AI
) {
435 ps
->param
[i
].AI
= ps
->param
[i
].AJ
;
440 qsort(ps
->param
,ps
->nr
,(size_t)sizeof(ps
->param
[0]),pcompar
);
444 for (i
=1; (i
<ps
->nr
); i
++) {
445 if ( ps
->param
[i
].AI
!= ps
->param
[j
-1].AI
||
446 ps
->param
[i
].AJ
!= ps
->param
[j
-1].AJ
) {
447 ps
->param
[j
] = ps
->param
[i
];
450 sfree(ps
->param
[i
].s
);
452 fprintf(stderr
,"Number of bonds was %d, now %d\n",ps
->nr
,j
);
455 fprintf(stderr
,"No bonds\n");
458 void print_sums(t_atoms
*atoms
, bool bSystem
)
471 for(i
=0; (i
<atoms
->nr
); i
++) {
473 qtot
+=atoms
->atom
[i
].q
;
476 fprintf(stderr
,"Total mass%s %.3f a.m.u.\n",where
,m
);
477 fprintf(stderr
,"Total charge%s %.3f e\n",where
,qtot
);
480 void get_hackblocks_rtp(t_hackblock
**hb
, t_restp
**restp
,
481 int nrtp
, t_restp rtp
[], int nres
, char **resname
[],
482 t_hackblock
*ntdb
, t_hackblock
*ctdb
, int rn
, int rc
)
487 char Hnum
[6]="123456";
491 /* first the termini */
493 copy_t_hackblock(ntdb
, &(*hb
)[rn
]);
495 merge_t_hackblock(ctdb
, &(*hb
)[rc
]);
497 /* then the whole rtp */
498 for(i
=0; i
< nres
; i
++) {
499 res
= search_rtp(*resname
[i
],nrtp
,rtp
);
500 copy_t_restp(res
, &(*restp
)[i
]);
501 merge_t_bondeds(res
->rb
, (*hb
)[i
].rb
);
504 /* now perform t_hack's on t_restp's,
505 i.e. add's and deletes from termini database will be
506 added to/removed from residue topology
507 we'll do this on one big dirty loop, so it won't make easy reading! */
508 for(i
=0; i
< nres
; i
++)
509 for(j
=0; j
< (*hb
)[i
].nhack
; j
++)
510 if ( (*hb
)[i
].hack
[j
].nr
) {
511 /* find atom in restp */
512 for(l
=0; l
< (*restp
)[i
].natom
; l
++)
513 if ( ( (*hb
)[i
].hack
[j
].oname
==NULL
&&
514 strcmp((*hb
)[i
].hack
[j
].AI
, *(*restp
)[i
].atomname
[l
])==0 ) ||
515 ( (*hb
)[i
].hack
[j
].oname
!=NULL
&&
516 strcmp((*hb
)[i
].hack
[j
].oname
,*(*restp
)[i
].atomname
[l
])==0 ) )
518 if (l
== (*restp
)[i
].natom
)
519 fatal_error(0,"atom %s not found in residue %d%s "
520 "while combining tdb and rtp",
521 (*hb
)[i
].hack
[j
].oname
!=NULL
?
522 (*hb
)[i
].hack
[j
].oname
: (*hb
)[i
].hack
[j
].AI
,
524 if ( (*hb
)[i
].hack
[j
].oname
==NULL
) {
527 fprintf(debug
,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
528 (*hb
)[i
].hack
[j
].nname
,
529 *(*restp
)[i
].atomname
[l
], i
+1, (*restp
)[i
].resname
);
530 strcpy(buf
, (*hb
)[i
].hack
[j
].nname
);
531 buf
[strlen(buf
)+1]='\0';
532 if ( (*hb
)[i
].hack
[j
].nr
> 1 )
533 buf
[strlen(buf
)]='-';
535 (*restp
)[i
].natom
+= (*hb
)[i
].hack
[j
].nr
;
536 srenew((*restp
)[i
].atom
, (*restp
)[i
].natom
);
537 srenew((*restp
)[i
].atomname
, (*restp
)[i
].natom
);
538 srenew((*restp
)[i
].cgnr
, (*restp
)[i
].natom
);
540 for(k
=(*restp
)[i
].natom
-1; k
> l
+(*hb
)[i
].hack
[j
].nr
; k
--) {
541 (*restp
)[i
].atom
[k
] =
542 (*restp
)[i
].atom
[k
- (*hb
)[i
].hack
[j
].nr
];
543 (*restp
)[i
].atomname
[k
] =
544 (*restp
)[i
].atomname
[k
- (*hb
)[i
].hack
[j
].nr
];
545 (*restp
)[i
].cgnr
[k
] =
546 (*restp
)[i
].cgnr
[k
- (*hb
)[i
].hack
[j
].nr
];
549 for(k
=0; k
< (*hb
)[i
].hack
[j
].nr
; k
++) {
550 /* set counter in atomname */
551 if ( (*hb
)[i
].hack
[j
].nr
> 1 )
552 buf
[strlen(buf
)-1]=Hnum
[k
];
553 snew( (*restp
)[i
].atomname
[l
+1+k
], 1);
554 (*restp
)[i
].atom
[l
+1+k
] = *(*hb
)[i
].hack
[j
].atom
;
555 *(*restp
)[i
].atomname
[l
+1+k
] = strdup(buf
);
556 if ( (*hb
)[i
].hack
[j
].cgnr
!= NOTSET
)
557 (*restp
)[i
].cgnr
[l
+1+k
] = (*hb
)[i
].hack
[j
].cgnr
;
559 (*restp
)[i
].cgnr
[l
+1+k
] = (*restp
)[i
].cgnr
[l
];
561 } else /* oname != NULL */
562 if ( (*hb
)[i
].hack
[j
].nname
==NULL
) {
565 fprintf(debug
, "deleting atom %s from res %d%s in rtp\n",
566 *(*restp
)[i
].atomname
[l
],
567 i
+1,(*restp
)[i
].resname
);
570 for(k
=l
; k
< (*restp
)[i
].natom
; k
++) {
571 (*restp
)[i
].atom
[k
] = (*restp
)[i
].atom
[k
+1];
572 (*restp
)[i
].atomname
[k
] = (*restp
)[i
].atomname
[k
+1];
573 (*restp
)[i
].cgnr
[k
] = (*restp
)[i
].cgnr
[k
+1];
575 /* give back space */
576 srenew((*restp
)[i
].atom
, (*restp
)[i
].natom
);
577 srenew((*restp
)[i
].atomname
, (*restp
)[i
].natom
);
578 srenew((*restp
)[i
].cgnr
, (*restp
)[i
].natom
);
579 } else { /* nname != NULL */
580 /* we're replacing */
582 fprintf(debug
, "replacing atom %s by %s in res %d%s in rtp\n",
583 *(*restp
)[i
].atomname
[l
], (*hb
)[i
].hack
[j
].nname
,
584 i
+1,(*restp
)[i
].resname
);
585 snew( (*restp
)[i
].atomname
[l
], 1);
586 (*restp
)[i
].atom
[l
] = *(*hb
)[i
].hack
[j
].atom
;
587 *(*restp
)[i
].atomname
[l
] = strdup((*hb
)[i
].hack
[j
].nname
);
588 if ( (*hb
)[i
].hack
[j
].cgnr
!= NOTSET
)
589 (*restp
)[i
].cgnr
[l
] = (*hb
)[i
].hack
[j
].cgnr
;
594 void pdb2top(FILE *top_file
, char *posre_fn
, char *molname
,
595 t_atoms
*atoms
, rvec
**x
, t_atomtype
*atype
, t_symtab
*tab
,
596 int bts
[], int nrtp
, t_restp rtp
[],
597 t_hackblock
*ntdb
, t_hackblock
*ctdb
,
598 bool bH14
, int rn
, int rc
, bool bAlldih
,
599 bool bDummies
, bool bDummyAromatics
, real mHmult
,
600 int nssbonds
, t_ssbond
*ssbonds
, int nrexcl
,
601 real long_bond_dist
, real short_bond_dist
)
605 t_params plist
[F_NRE
];
613 /* lookup hackblocks and rtp for all residues */
614 get_hackblocks_rtp(&hb
, &restp
, nrtp
, rtp
, atoms
->nres
, atoms
->resname
,
616 /* ideally, now we would not need the rtp itself anymore, but do
617 everything using the hb and restp arrays. Unfortunately, that
618 requires some re-thinking of code in gen_dum.c, which I won't
619 do now :( AF 26-7-99 */
622 print_resall(debug
, bts
, atoms
->nres
, restp
, atype
);
623 dump_hb(debug
, atoms
->nres
, hb
);
627 at2bonds(&(plist
[F_BONDS
]), hb
,
628 atoms
->nr
, atoms
->atom
, atoms
->atomname
, atoms
->nres
, *x
,
629 long_bond_dist
, short_bond_dist
);
631 /* specbonds: disulphide bonds & heme-his */
632 do_ssbonds(&(plist
[F_BONDS
]),
633 atoms
->nr
, atoms
->atom
, atoms
->atomname
, nssbonds
, ssbonds
);
635 name2type(atoms
, &cgnr
, atype
, restp
);
637 /* Cleanup bonds (sort and rm doubles) */
638 clean_bonds(&(plist
[F_BONDS
]));
640 snew(dummy_type
,atoms
->nr
);
641 for(i
=0; i
<atoms
->nr
; i
++)
642 dummy_type
[i
]=NOTSET
;
644 /* determine which atoms will be dummies and add dummy masses
645 also renumber atom numbers in plist[0..F_NRE]! */
646 do_dummies(nrtp
, rtp
, atype
, atoms
, tab
, x
, plist
,
647 &dummy_type
, &cgnr
, mHmult
, bDummyAromatics
);
649 /* Make Angles and Dihedrals */
650 fprintf(stderr
,"Generating angles and dihedrals...\n");
651 init_nnb(&nnb
,atoms
->nr
,4);
653 print_nnb(&nnb
,"NNB");
654 gen_pad(&nnb
,atoms
,bH14
,plist
,hb
,bAlldih
);
657 /* set mass of all remaining hydrogen atoms */
659 do_h_mass(&(plist
[F_BONDS
]),dummy_type
,atoms
,mHmult
);
662 /* Cleanup bonds (sort and rm doubles) */
663 clean_bonds(&(plist
[F_BONDS
]));
666 "There are %4d dihedrals, %4d impropers, %4d angles\n"
667 " %4d pairs, %4d bonds and %4d dummies\n",
668 plist
[F_PDIHS
].nr
, plist
[F_IDIHS
].nr
, plist
[F_ANGLES
].nr
,
669 plist
[F_LJ14
].nr
, plist
[F_BONDS
].nr
,
672 plist
[F_DUMMY3FD
].nr
+
673 plist
[F_DUMMY3FAD
].nr
+
674 plist
[F_DUMMY3OUT
].nr
+
675 plist
[F_DUMMY4FD
].nr
);
677 print_sums(atoms
, FALSE
);
680 fprintf(stderr
,"Writing topology\n");
681 write_top(top_file
, posre_fn
, molname
,
682 atoms
, bts
, plist
, NULL
, atype
, cgnr
, nrexcl
);
686 free_t_hackblock(atoms
->nres
, &hb
);
687 free_t_restp(atoms
->nres
, &restp
);
689 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
691 for (i
=0; (i
<F_NRE
); i
++)
692 sfree(plist
[i
].param
);