2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
43 #include "gromacs/fileio/confio.h"
44 #include "gromacs/math/vec.h"
45 #include "gromacs/utility/futil.h"
54 #include "gromacs/topology/symtab.h"
55 #include "gromacs/utility/fatalerror.h"
56 #include "gromacs/utility/smalloc.h"
58 static void copy_atom(t_atoms
*atoms1
, int a1
, t_atoms
*atoms2
, int a2
)
60 atoms2
->atom
[a2
] = atoms1
->atom
[a1
];
61 snew(atoms2
->atomname
[a2
], 1);
62 *atoms2
->atomname
[a2
] = strdup(*atoms1
->atomname
[a1
]);
65 static atom_id
pdbasearch_atom(const char *name
, int resind
, t_atoms
*pdba
,
66 const char *searchtype
, gmx_bool bAllowMissing
)
70 for (i
= 0; (i
< pdba
->nr
) && (pdba
->atom
[i
].resind
!= resind
); i
++)
75 return search_atom(name
, i
, pdba
,
76 searchtype
, bAllowMissing
);
79 static void hacksearch_atom(int *ii
, int *jj
, char *name
,
80 int nab
[], t_hack
*ab
[],
81 int resind
, t_atoms
*pdba
)
91 for (i
= 0; (i
< pdba
->nr
) && (pdba
->atom
[i
].resind
!= resind
); i
++)
95 for (; (i
< pdba
->nr
) && (pdba
->atom
[i
].resind
== resind
) && (*ii
< 0); i
++)
97 for (j
= 0; (j
< nab
[i
]) && (*ii
< 0); j
++)
99 if (ab
[i
][j
].nname
&& strcmp(name
, ab
[i
][j
].nname
) == 0)
110 void dump_ab(FILE *out
, int natom
, int nab
[], t_hack
*ab
[], gmx_bool bHeader
)
114 #define SS(s) (s) ? (s) : "-"
118 fprintf(out
, "ADDBLOCK (t_hack) natom=%d\n"
119 "%4s %2s %-4s %-4s %2s %-4s %-4s %-4s %-4s %1s %s\n",
120 natom
, "atom", "nr", "old", "new", "tp", "ai", "aj", "ak", "al", "a", "x");
122 for (i
= 0; i
< natom
; i
++)
124 for (j
= 0; j
< nab
[i
]; j
++)
126 fprintf(out
, "%4d %2d %-4s %-4s %2d %-4s %-4s %-4s %-4s %s %g %g %g\n",
127 i
+1, ab
[i
][j
].nr
, SS(ab
[i
][j
].oname
), SS(ab
[i
][j
].nname
),
129 SS(ab
[i
][j
].AI
), SS(ab
[i
][j
].AJ
),
130 SS(ab
[i
][j
].AK
), SS(ab
[i
][j
].AL
),
131 ab
[i
][j
].atom
? "+" : "",
132 ab
[i
][j
].newx
[XX
], ab
[i
][j
].newx
[YY
], ab
[i
][j
].newx
[ZZ
]);
138 static t_hackblock
*get_hackblocks(t_atoms
*pdba
, int nah
, t_hackblock ah
[],
140 t_hackblock
**ntdb
, t_hackblock
**ctdb
,
144 t_hackblock
*hb
, *ahptr
;
147 snew(hb
, pdba
->nres
);
148 /* first the termini */
149 for (i
= 0; i
< nterpairs
; i
++)
153 copy_t_hackblock(ntdb
[i
], &hb
[rN
[i
]]);
157 merge_t_hackblock(ctdb
[i
], &hb
[rC
[i
]]);
160 /* then the whole hdb */
161 for (rnr
= 0; rnr
< pdba
->nres
; rnr
++)
163 ahptr
= search_h_db(nah
, ah
, *pdba
->resinfo
[rnr
].rtp
);
166 if (hb
[rnr
].name
== NULL
)
168 hb
[rnr
].name
= strdup(ahptr
->name
);
170 merge_hacks(ahptr
, &hb
[rnr
]);
176 static void expand_hackblocks_one(t_hackblock
*hbr
, char *atomname
,
177 int *nabi
, t_hack
**abi
, gmx_bool bN
, gmx_bool bC
)
182 /* we'll recursively add atoms to atoms */
183 for (j
= 0; j
< hbr
->nhack
; j
++)
185 /* first check if we're in the N- or C-terminus, then we should ignore
186 all hacks involving atoms from resp. previous or next residue
187 (i.e. which name begins with '-' (N) or '+' (C) */
189 if (bN
) /* N-terminus: ignore '-' */
191 for (k
= 0; k
< 4 && hbr
->hack
[j
].a
[k
] && !bIgnore
; k
++)
193 bIgnore
= hbr
->hack
[j
].a
[k
][0] == '-';
196 if (bC
) /* C-terminus: ignore '+' */
198 for (k
= 0; k
< 4 && hbr
->hack
[j
].a
[k
] && !bIgnore
; k
++)
200 bIgnore
= hbr
->hack
[j
].a
[k
][0] == '+';
203 /* must be either hdb entry (tp>0) or add from tdb (oname==NULL)
204 and first control aton (AI) matches this atom or
205 delete/replace from tdb (oname!=NULL) and oname matches this atom */
208 fprintf(debug
, " %s", hbr
->hack
[j
].oname
? hbr
->hack
[j
].oname
: hbr
->hack
[j
].AI
);
212 ( ( ( hbr
->hack
[j
].tp
> 0 || hbr
->hack
[j
].oname
== NULL
) &&
213 strcmp(atomname
, hbr
->hack
[j
].AI
) == 0 ) ||
214 ( hbr
->hack
[j
].oname
!= NULL
&&
215 strcmp(atomname
, hbr
->hack
[j
].oname
) == 0) ) )
217 /* now expand all hacks for this atom */
220 fprintf(debug
, " +%dh", hbr
->hack
[j
].nr
);
222 srenew(*abi
, *nabi
+ hbr
->hack
[j
].nr
);
223 for (k
= 0; k
< hbr
->hack
[j
].nr
; k
++)
225 copy_t_hack(&hbr
->hack
[j
], &(*abi
)[*nabi
+ k
]);
226 (*abi
)[*nabi
+ k
].bXSet
= FALSE
;
227 /* if we're adding (oname==NULL) and don't have a new name (nname)
228 yet, build it from atomname */
229 if ( (*abi
)[*nabi
+ k
].nname
== NULL
)
231 if ( (*abi
)[*nabi
+ k
].oname
== NULL
)
233 (*abi
)[*nabi
+ k
].nname
= strdup(atomname
);
234 (*abi
)[*nabi
+ k
].nname
[0] = 'H';
241 fprintf(debug
, "Hack '%s' %d, replacing nname '%s' with '%s' (old name '%s')\n",
243 (*abi
)[*nabi
+ k
].nname
, hbr
->hack
[j
].nname
,
244 (*abi
)[*nabi
+ k
].oname
? (*abi
)[*nabi
+ k
].oname
: "");
246 sfree((*abi
)[*nabi
+ k
].nname
);
247 (*abi
)[*nabi
+ k
].nname
= strdup(hbr
->hack
[j
].nname
);
250 if (hbr
->hack
[j
].tp
== 10 && k
== 2)
252 /* This is a water virtual site, not a hydrogen */
253 /* Ugly hardcoded name hack */
254 (*abi
)[*nabi
+ k
].nname
[0] = 'M';
256 else if (hbr
->hack
[j
].tp
== 11 && k
>= 2)
258 /* This is a water lone pair, not a hydrogen */
259 /* Ugly hardcoded name hack */
260 srenew((*abi
)[*nabi
+ k
].nname
, 4);
261 (*abi
)[*nabi
+ k
].nname
[0] = 'L';
262 (*abi
)[*nabi
+ k
].nname
[1] = 'P';
263 (*abi
)[*nabi
+ k
].nname
[2] = '1' + k
- 2;
264 (*abi
)[*nabi
+ k
].nname
[3] = '\0';
266 else if (hbr
->hack
[j
].nr
> 1)
268 /* adding more than one atom, number them */
269 l
= strlen((*abi
)[*nabi
+ k
].nname
);
270 srenew((*abi
)[*nabi
+ k
].nname
, l
+2);
271 (*abi
)[*nabi
+ k
].nname
[l
] = '1' + k
;
272 (*abi
)[*nabi
+ k
].nname
[l
+1] = '\0';
275 (*nabi
) += hbr
->hack
[j
].nr
;
277 /* add hacks to atoms we've just added */
278 if (hbr
->hack
[j
].tp
> 0 || hbr
->hack
[j
].oname
== NULL
)
280 for (k
= 0; k
< hbr
->hack
[j
].nr
; k
++)
282 expand_hackblocks_one(hbr
, (*abi
)[*nabi
-hbr
->hack
[j
].nr
+k
].nname
,
290 static void expand_hackblocks(t_atoms
*pdba
, t_hackblock hb
[],
291 int nab
[], t_hack
*ab
[],
292 int nterpairs
, int *rN
, int *rC
)
297 for (i
= 0; i
< pdba
->nr
; i
++)
300 for (j
= 0; j
< nterpairs
&& !bN
; j
++)
302 bN
= pdba
->atom
[i
].resind
== rN
[j
];
305 for (j
= 0; j
< nterpairs
&& !bC
; j
++)
307 bC
= pdba
->atom
[i
].resind
== rC
[j
];
310 /* add hacks to this atom */
311 expand_hackblocks_one(&hb
[pdba
->atom
[i
].resind
], *pdba
->atomname
[i
],
312 &nab
[i
], &ab
[i
], bN
, bC
);
316 fprintf(debug
, "\n");
320 static int check_atoms_present(t_atoms
*pdba
, int nab
[], t_hack
*ab
[])
322 int i
, j
, k
, d
, rnr
, nadd
;
325 for (i
= 0; i
< pdba
->nr
; i
++)
327 rnr
= pdba
->atom
[i
].resind
;
328 for (j
= 0; j
< nab
[i
]; j
++)
330 if (ab
[i
][j
].oname
== NULL
)
333 if (ab
[i
][j
].nname
== NULL
)
335 gmx_incons("ab[i][j].nname not allocated");
337 /* check if the atom is already present */
338 k
= pdbasearch_atom(ab
[i
][j
].nname
, rnr
, pdba
, "check", TRUE
);
341 /* We found the added atom. */
342 ab
[i
][j
].bAlreadyPresent
= TRUE
;
345 fprintf(debug
, "Atom '%s' in residue '%s' %d is already present\n",
347 *pdba
->resinfo
[rnr
].name
, pdba
->resinfo
[rnr
].nr
);
352 ab
[i
][j
].bAlreadyPresent
= FALSE
;
353 /* count how many atoms we'll add */
357 else if (ab
[i
][j
].nname
== NULL
)
368 static void calc_all_pos(t_atoms
*pdba
, rvec x
[], int nab
[], t_hack
*ab
[],
369 gmx_bool bCheckMissing
)
371 int i
, j
, ii
, jj
, m
, ia
, d
, rnr
, l
= 0;
373 rvec xa
[4]; /* control atoms for calc_h_pos */
374 rvec xh
[MAXH
]; /* hydrogen positions from calc_h_pos */
379 for (i
= 0; i
< pdba
->nr
; i
++)
381 rnr
= pdba
->atom
[i
].resind
;
382 for (j
= 0; j
< nab
[i
]; j
+= ab
[i
][j
].nr
)
384 /* check if we're adding: */
385 if (ab
[i
][j
].oname
== NULL
&& ab
[i
][j
].tp
> 0)
388 for (m
= 0; (m
< ab
[i
][j
].nctl
&& bFoundAll
); m
++)
390 ia
= pdbasearch_atom(ab
[i
][j
].a
[m
], rnr
, pdba
,
391 bCheckMissing
? "atom" : "check",
395 /* not found in original atoms, might still be in t_hack (ab) */
396 hacksearch_atom(&ii
, &jj
, ab
[i
][j
].a
[m
], nab
, ab
, rnr
, pdba
);
399 copy_rvec(ab
[ii
][jj
].newx
, xa
[m
]);
406 gmx_fatal(FARGS
, "Atom %s not found in residue %s %d"
408 " while adding hydrogens",
410 *pdba
->resinfo
[rnr
].name
,
411 pdba
->resinfo
[rnr
].nr
,
412 *pdba
->resinfo
[rnr
].rtp
);
418 copy_rvec(x
[ia
], xa
[m
]);
423 for (m
= 0; (m
< MAXH
); m
++)
425 for (d
= 0; d
< DIM
; d
++)
437 calc_h_pos(ab
[i
][j
].tp
, xa
, xh
, &l
);
438 for (m
= 0; m
< ab
[i
][j
].nr
; m
++)
440 copy_rvec(xh
[m
], ab
[i
][j
+m
].newx
);
441 ab
[i
][j
+m
].bXSet
= TRUE
;
449 static void free_ab(int natoms
, int *nab
, t_hack
**ab
)
453 for (i
= 0; i
< natoms
; i
++)
455 free_t_hack(nab
[i
], &ab
[i
]);
461 static int add_h_low(t_atoms
**pdbaptr
, rvec
*xptr
[],
462 int nah
, t_hackblock ah
[],
463 int nterpairs
, t_hackblock
**ntdb
, t_hackblock
**ctdb
,
464 int *rN
, int *rC
, gmx_bool bCheckMissing
,
465 int **nabptr
, t_hack
***abptr
,
466 gmx_bool bUpdate_pdba
, gmx_bool bKeep_old_pdba
)
468 t_atoms
*newpdba
= NULL
, *pdba
= NULL
;
470 int i
, newi
, j
, d
, natoms
, nalreadypresent
;
477 /* set flags for adding hydrogens (according to hdb) */
483 /* the first time these will be pointers to NULL, but we will
484 return in them the completed arrays, which we will get back
491 fprintf(debug
, "pointer to ab found\n");
501 /* WOW, everything was already figured out */
502 bUpdate_pdba
= FALSE
;
505 fprintf(debug
, "pointer to non-null ab found\n");
510 /* We'll have to do all the hard work */
512 /* first get all the hackblocks for each residue: */
513 hb
= get_hackblocks(pdba
, nah
, ah
, nterpairs
, ntdb
, ctdb
, rN
, rC
);
516 dump_hb(debug
, pdba
->nres
, hb
);
519 /* expand the hackblocks to atom level */
522 expand_hackblocks(pdba
, hb
, nab
, ab
, nterpairs
, rN
, rC
);
523 free_t_hackblock(pdba
->nres
, &hb
);
528 fprintf(debug
, "before calc_all_pos\n");
529 dump_ab(debug
, natoms
, nab
, ab
, TRUE
);
532 /* Now calc the positions */
533 calc_all_pos(pdba
, *xptr
, nab
, ab
, bCheckMissing
);
537 fprintf(debug
, "after calc_all_pos\n");
538 dump_ab(debug
, natoms
, nab
, ab
, TRUE
);
543 /* we don't have to add atoms that are already present in pdba,
544 so we will remove them from the ab (t_hack) */
545 nadd
= check_atoms_present(pdba
, nab
, ab
);
548 fprintf(debug
, "removed add hacks that were already in pdba:\n");
549 dump_ab(debug
, natoms
, nab
, ab
, TRUE
);
550 fprintf(debug
, "will be adding %d atoms\n", nadd
);
553 /* Copy old atoms, making space for new ones */
555 init_t_atoms(newpdba
, natoms
+nadd
, FALSE
);
556 newpdba
->nres
= pdba
->nres
;
557 sfree(newpdba
->resinfo
);
558 newpdba
->resinfo
= pdba
->resinfo
;
566 fprintf(debug
, "snew xn for %d old + %d new atoms %d total)\n",
567 natoms
, nadd
, natoms
+nadd
);
572 /* There is nothing to do: return now */
575 free_ab(natoms
, nab
, ab
);
581 snew(xn
, natoms
+nadd
);
583 for (i
= 0; (i
< natoms
); i
++)
585 /* check if this atom wasn't scheduled for deletion */
586 if (nab
[i
] == 0 || (ab
[i
][0].nname
!= NULL
) )
588 if (newi
>= natoms
+nadd
)
590 /*gmx_fatal(FARGS,"Not enough space for adding atoms");*/
592 srenew(xn
, natoms
+nadd
);
595 srenew(newpdba
->atom
, natoms
+nadd
);
596 srenew(newpdba
->atomname
, natoms
+nadd
);
602 fprintf(debug
, "(%3d) %3d %4s %4s%3d %3d",
603 i
+1, newi
+1, *pdba
->atomname
[i
],
604 *pdba
->resinfo
[pdba
->atom
[i
].resind
].name
,
605 pdba
->resinfo
[pdba
->atom
[i
].resind
].nr
, nab
[i
]);
609 copy_atom(pdba
, i
, newpdba
, newi
);
611 copy_rvec((*xptr
)[i
], xn
[newi
]);
612 /* process the hacks for this atom */
614 for (j
= 0; j
< nab
[i
]; j
++)
616 if (ab
[i
][j
].oname
== NULL
) /* add */
619 if (newi
>= natoms
+nadd
)
621 /* gmx_fatal(FARGS,"Not enough space for adding atoms");*/
623 srenew(xn
, natoms
+nadd
);
626 srenew(newpdba
->atom
, natoms
+nadd
);
627 srenew(newpdba
->atomname
, natoms
+nadd
);
633 newpdba
->atom
[newi
].resind
= pdba
->atom
[i
].resind
;
637 fprintf(debug
, " + %d", newi
+1);
640 if (ab
[i
][j
].nname
!= NULL
&&
641 (ab
[i
][j
].oname
== NULL
||
642 strcmp(ab
[i
][j
].oname
, *newpdba
->atomname
[newi
]) == 0))
645 if (ab
[i
][j
].oname
== NULL
&& ab
[i
][j
].bAlreadyPresent
)
647 /* This atom is already present, copy it from the input. */
651 copy_atom(pdba
, i
+nalreadypresent
, newpdba
, newi
);
653 copy_rvec((*xptr
)[i
+nalreadypresent
], xn
[newi
]);
661 fprintf(debug
, "Replacing %d '%s' with (old name '%s') %s\n",
663 (newpdba
->atomname
[newi
] && *newpdba
->atomname
[newi
]) ? *newpdba
->atomname
[newi
] : "",
664 ab
[i
][j
].oname
? ab
[i
][j
].oname
: "",
667 snew(newpdba
->atomname
[newi
], 1);
668 *newpdba
->atomname
[newi
] = strdup(ab
[i
][j
].nname
);
669 if (ab
[i
][j
].oname
!= NULL
&& ab
[i
][j
].atom
) /* replace */
670 { /* newpdba->atom[newi].m = ab[i][j].atom->m; */
671 /* newpdba->atom[newi].q = ab[i][j].atom->q; */
672 /* newpdba->atom[newi].type = ab[i][j].atom->type; */
677 copy_rvec(ab
[i
][j
].newx
, xn
[newi
]);
680 if (bUpdate_pdba
&& debug
)
682 fprintf(debug
, " %s %g %g", *newpdba
->atomname
[newi
],
683 newpdba
->atom
[newi
].m
, newpdba
->atom
[newi
].q
);
688 i
+= nalreadypresent
;
691 fprintf(debug
, "\n");
708 free_ab(natoms
, nab
, ab
);
715 for (i
= 0; i
< natoms
; i
++)
717 /* Do not free the atomname string itself, it might be in symtab */
718 /* sfree(*(pdba->atomname[i])); */
719 /* sfree(pdba->atomname[i]); */
721 sfree(pdba
->atomname
);
723 sfree(pdba
->pdbinfo
);
739 void deprotonate(t_atoms
*atoms
, rvec
*x
)
744 for (i
= 0; i
< atoms
->nr
; i
++)
746 if ( (*atoms
->atomname
[i
])[0] != 'H')
748 atoms
->atomname
[j
] = atoms
->atomname
[i
];
749 atoms
->atom
[j
] = atoms
->atom
[i
];
750 copy_rvec(x
[i
], x
[j
]);
757 int add_h(t_atoms
**pdbaptr
, rvec
*xptr
[],
758 int nah
, t_hackblock ah
[],
759 int nterpairs
, t_hackblock
**ntdb
, t_hackblock
**ctdb
,
760 int *rN
, int *rC
, gmx_bool bAllowMissing
,
761 int **nabptr
, t_hack
***abptr
,
762 gmx_bool bUpdate_pdba
, gmx_bool bKeep_old_pdba
)
764 int nold
, nnew
, niter
;
766 /* Here we loop to be able to add atoms to added atoms.
767 * We should not check for missing atoms here.
774 nnew
= add_h_low(pdbaptr
, xptr
, nah
, ah
, nterpairs
, ntdb
, ctdb
, rN
, rC
, FALSE
,
775 nabptr
, abptr
, bUpdate_pdba
, bKeep_old_pdba
);
779 gmx_fatal(FARGS
, "More than 100 iterations of add_h. Maybe you are trying to replace an added atom (this is not supported)?");
786 /* Call add_h_low once more, now only for the missing atoms check */
787 add_h_low(pdbaptr
, xptr
, nah
, ah
, nterpairs
, ntdb
, ctdb
, rN
, rC
, TRUE
,
788 nabptr
, abptr
, bUpdate_pdba
, bKeep_old_pdba
);
794 int protonate(t_atoms
**atomsptr
, rvec
**xptr
, t_protonate
*protdata
)
798 gmx_bool bUpdate_pdba
, bKeep_old_pdba
;
799 int nntdb
, nctdb
, nt
, ct
;
803 if (!protdata
->bInit
)
807 fprintf(debug
, "protonate: Initializing protdata\n");
810 /* set forcefield to use: */
811 strcpy(protdata
->FF
, "oplsaa.ff");
813 /* get the databases: */
814 protdata
->nah
= read_h_db(protdata
->FF
, &protdata
->ah
);
815 open_symtab(&protdata
->tab
);
816 protdata
->atype
= read_atype(protdata
->FF
, &protdata
->tab
);
817 nntdb
= read_ter_db(protdata
->FF
, 'n', &protdata
->ntdb
, protdata
->atype
);
820 gmx_fatal(FARGS
, "no N-terminus database");
822 nctdb
= read_ter_db(protdata
->FF
, 'c', &protdata
->ctdb
, protdata
->atype
);
825 gmx_fatal(FARGS
, "no C-terminus database");
828 /* set terminus types: -NH3+ (different for Proline) and -COO- */
830 snew(protdata
->sel_ntdb
, NTERPAIRS
);
831 snew(protdata
->sel_ctdb
, NTERPAIRS
);
833 if (nntdb
>= 4 && nctdb
>= 2)
835 /* Yuk, yuk, hardcoded default termini selections !!! */
836 if (strncmp(*atoms
->resinfo
[atoms
->atom
[atoms
->nr
-1].resind
].name
, "PRO", 3) == 0)
851 protdata
->sel_ntdb
[0] = &(protdata
->ntdb
[nt
]);
852 protdata
->sel_ctdb
[0] = &(protdata
->ctdb
[ct
]);
854 /* set terminal residue numbers: */
855 snew(protdata
->rN
, NTERPAIRS
);
856 snew(protdata
->rC
, NTERPAIRS
);
858 protdata
->rC
[0] = atoms
->atom
[atoms
->nr
-1].resind
;
860 /* keep unprotonated topology: */
861 protdata
->upatoms
= atoms
;
862 /* we don't have these yet: */
863 protdata
->patoms
= NULL
;
865 bKeep_old_pdba
= TRUE
;
867 /* clear hackblocks: */
868 protdata
->nab
= NULL
;
871 /* set flag to show we're initialized: */
872 protdata
->bInit
= TRUE
;
878 fprintf(debug
, "protonate: using available protdata\n");
880 /* add_h will need the unprotonated topology again: */
881 atoms
= protdata
->upatoms
;
882 bUpdate_pdba
= FALSE
;
883 bKeep_old_pdba
= FALSE
;
887 nadd
= add_h(&atoms
, xptr
, protdata
->nah
, protdata
->ah
,
888 NTERPAIRS
, protdata
->sel_ntdb
, protdata
->sel_ctdb
,
889 protdata
->rN
, protdata
->rC
, TRUE
,
890 &protdata
->nab
, &protdata
->ab
, bUpdate_pdba
, bKeep_old_pdba
);
891 if (!protdata
->patoms
)
893 /* store protonated topology */
894 protdata
->patoms
= atoms
;
896 *atomsptr
= protdata
->patoms
;
899 fprintf(debug
, "natoms: %d -> %d (nadd=%d)\n",
900 protdata
->upatoms
->nr
, protdata
->patoms
->nr
, nadd
);