Remove all unnecessary HAVE_CONFIG_H
[gromacs.git] / src / gromacs / gmxpreprocess / genhydro.c
blob238a3db4806d1f3e7fc9f3d3d8a0c626678c899d
1 /*
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.
37 #include "config.h"
39 #include <string.h>
40 #include <time.h>
42 #include "typedefs.h"
43 #include "gromacs/fileio/confio.h"
44 #include "gromacs/math/vec.h"
45 #include "gromacs/utility/futil.h"
46 #include "calch.h"
47 #include "genhydro.h"
48 #include "h_db.h"
49 #include "ter_db.h"
50 #include "resall.h"
51 #include "pgutil.h"
52 #include "network.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)
68 int i;
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)
83 int i, j;
85 *ii = -1;
86 if (name[0] == '-')
88 name++;
89 resind--;
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)
101 *ii = i;
102 *jj = j;
107 return;
110 void dump_ab(FILE *out, int natom, int nab[], t_hack *ab[], gmx_bool bHeader)
112 int i, j;
114 #define SS(s) (s) ? (s) : "-"
115 /* dump ab */
116 if (bHeader)
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),
128 ab[i][j].tp,
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]);
135 #undef SS
138 static t_hackblock *get_hackblocks(t_atoms *pdba, int nah, t_hackblock ah[],
139 int nterpairs,
140 t_hackblock **ntdb, t_hackblock **ctdb,
141 int *rN, int *rC)
143 int i, rnr;
144 t_hackblock *hb, *ahptr;
146 /* make space */
147 snew(hb, pdba->nres);
148 /* first the termini */
149 for (i = 0; i < nterpairs; i++)
151 if (ntdb[i] != NULL)
153 copy_t_hackblock(ntdb[i], &hb[rN[i]]);
155 if (ctdb[i] != NULL)
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);
164 if (ahptr)
166 if (hb[rnr].name == NULL)
168 hb[rnr].name = strdup(ahptr->name);
170 merge_hacks(ahptr, &hb[rnr]);
173 return hb;
176 static void expand_hackblocks_one(t_hackblock *hbr, char *atomname,
177 int *nabi, t_hack **abi, gmx_bool bN, gmx_bool bC)
179 int j, k, l, d;
180 gmx_bool bIgnore;
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) */
188 bIgnore = FALSE;
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 */
206 if (debug)
208 fprintf(debug, " %s", hbr->hack[j].oname ? hbr->hack[j].oname : hbr->hack[j].AI);
211 if (!bIgnore &&
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 */
218 if (debug)
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';
237 else
239 if (gmx_debug_at)
241 fprintf(debug, "Hack '%s' %d, replacing nname '%s' with '%s' (old name '%s')\n",
242 atomname, j,
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,
283 nabi, abi, bN, bC);
290 static void expand_hackblocks(t_atoms *pdba, t_hackblock hb[],
291 int nab[], t_hack *ab[],
292 int nterpairs, int *rN, int *rC)
294 int i, j;
295 gmx_bool bN, bC;
297 for (i = 0; i < pdba->nr; i++)
299 bN = FALSE;
300 for (j = 0; j < nterpairs && !bN; j++)
302 bN = pdba->atom[i].resind == rN[j];
304 bC = FALSE;
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);
314 if (debug)
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;
324 nadd = 0;
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)
332 /* we're adding */
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);
339 if (k != -1)
341 /* We found the added atom. */
342 ab[i][j].bAlreadyPresent = TRUE;
343 if (debug)
345 fprintf(debug, "Atom '%s' in residue '%s' %d is already present\n",
346 ab[i][j].nname,
347 *pdba->resinfo[rnr].name, pdba->resinfo[rnr].nr);
350 else
352 ab[i][j].bAlreadyPresent = FALSE;
353 /* count how many atoms we'll add */
354 nadd++;
357 else if (ab[i][j].nname == NULL)
359 /* we're deleting */
360 nadd--;
365 return nadd;
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;
372 #define MAXH 4
373 rvec xa[4]; /* control atoms for calc_h_pos */
374 rvec xh[MAXH]; /* hydrogen positions from calc_h_pos */
375 gmx_bool bFoundAll;
377 jj = 0;
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)
387 bFoundAll = TRUE;
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",
392 !bCheckMissing);
393 if (ia < 0)
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);
397 if (ii >= 0)
399 copy_rvec(ab[ii][jj].newx, xa[m]);
401 else
403 bFoundAll = FALSE;
404 if (bCheckMissing)
406 gmx_fatal(FARGS, "Atom %s not found in residue %s %d"
407 ", rtp entry %s"
408 " while adding hydrogens",
409 ab[i][j].a[m],
410 *pdba->resinfo[rnr].name,
411 pdba->resinfo[rnr].nr,
412 *pdba->resinfo[rnr].rtp);
416 else
418 copy_rvec(x[ia], xa[m]);
421 if (bFoundAll)
423 for (m = 0; (m < MAXH); m++)
425 for (d = 0; d < DIM; d++)
427 if (m < ab[i][j].nr)
429 xh[m][d] = 0;
431 else
433 xh[m][d] = NOTSET;
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)
451 int i;
453 for (i = 0; i < natoms; i++)
455 free_t_hack(nab[i], &ab[i]);
457 sfree(nab);
458 sfree(ab);
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;
469 int nadd;
470 int i, newi, j, d, natoms, nalreadypresent;
471 int *nab = NULL;
472 t_hack **ab = NULL;
473 t_hackblock *hb;
474 rvec *xn;
475 gmx_bool bKeep_ab;
477 /* set flags for adding hydrogens (according to hdb) */
478 pdba = *pdbaptr;
479 natoms = pdba->nr;
481 if (nabptr && abptr)
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
485 the second time */
486 nab = *nabptr;
487 ab = *abptr;
488 bKeep_ab = TRUE;
489 if (debug)
491 fprintf(debug, "pointer to ab found\n");
494 else
496 bKeep_ab = FALSE;
499 if (nab && ab)
501 /* WOW, everything was already figured out */
502 bUpdate_pdba = FALSE;
503 if (debug)
505 fprintf(debug, "pointer to non-null ab found\n");
508 else
510 /* We'll have to do all the hard work */
511 bUpdate_pdba = TRUE;
512 /* first get all the hackblocks for each residue: */
513 hb = get_hackblocks(pdba, nah, ah, nterpairs, ntdb, ctdb, rN, rC);
514 if (debug)
516 dump_hb(debug, pdba->nres, hb);
519 /* expand the hackblocks to atom level */
520 snew(nab, natoms);
521 snew(ab, natoms);
522 expand_hackblocks(pdba, hb, nab, ab, nterpairs, rN, rC);
523 free_t_hackblock(pdba->nres, &hb);
526 if (debug)
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);
535 if (debug)
537 fprintf(debug, "after calc_all_pos\n");
538 dump_ab(debug, natoms, nab, ab, TRUE);
541 if (bUpdate_pdba)
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);
546 if (debug)
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 */
554 snew(newpdba, 1);
555 init_t_atoms(newpdba, natoms+nadd, FALSE);
556 newpdba->nres = pdba->nres;
557 sfree(newpdba->resinfo);
558 newpdba->resinfo = pdba->resinfo;
560 else
562 nadd = 0;
564 if (debug)
566 fprintf(debug, "snew xn for %d old + %d new atoms %d total)\n",
567 natoms, nadd, natoms+nadd);
570 if (nadd == 0)
572 /* There is nothing to do: return now */
573 if (!bKeep_ab)
575 free_ab(natoms, nab, ab);
578 return natoms;
581 snew(xn, natoms+nadd);
582 newi = 0;
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");*/
591 nadd += 10;
592 srenew(xn, natoms+nadd);
593 if (bUpdate_pdba)
595 srenew(newpdba->atom, natoms+nadd);
596 srenew(newpdba->atomname, natoms+nadd);
598 debug_gmx();
600 if (debug)
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]);
607 if (bUpdate_pdba)
609 copy_atom(pdba, i, newpdba, newi);
611 copy_rvec((*xptr)[i], xn[newi]);
612 /* process the hacks for this atom */
613 nalreadypresent = 0;
614 for (j = 0; j < nab[i]; j++)
616 if (ab[i][j].oname == NULL) /* add */
618 newi++;
619 if (newi >= natoms+nadd)
621 /* gmx_fatal(FARGS,"Not enough space for adding atoms");*/
622 nadd += 10;
623 srenew(xn, natoms+nadd);
624 if (bUpdate_pdba)
626 srenew(newpdba->atom, natoms+nadd);
627 srenew(newpdba->atomname, natoms+nadd);
629 debug_gmx();
631 if (bUpdate_pdba)
633 newpdba->atom[newi].resind = pdba->atom[i].resind;
635 if (debug)
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))
644 /* add or replace */
645 if (ab[i][j].oname == NULL && ab[i][j].bAlreadyPresent)
647 /* This atom is already present, copy it from the input. */
648 nalreadypresent++;
649 if (bUpdate_pdba)
651 copy_atom(pdba, i+nalreadypresent, newpdba, newi);
653 copy_rvec((*xptr)[i+nalreadypresent], xn[newi]);
655 else
657 if (bUpdate_pdba)
659 if (gmx_debug_at)
661 fprintf(debug, "Replacing %d '%s' with (old name '%s') %s\n",
662 newi,
663 (newpdba->atomname[newi] && *newpdba->atomname[newi]) ? *newpdba->atomname[newi] : "",
664 ab[i][j].oname ? ab[i][j].oname : "",
665 ab[i][j].nname);
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; */
675 if (ab[i][j].bXSet)
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);
687 newi++;
688 i += nalreadypresent;
689 if (debug)
691 fprintf(debug, "\n");
695 if (bUpdate_pdba)
697 newpdba->nr = newi;
700 if (bKeep_ab)
702 *nabptr = nab;
703 *abptr = ab;
705 else
707 /* Clean up */
708 free_ab(natoms, nab, ab);
711 if (bUpdate_pdba)
713 if (!bKeep_old_pdba)
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);
722 sfree(pdba->atom);
723 sfree(pdba->pdbinfo);
724 sfree(pdba);
726 *pdbaptr = newpdba;
728 else
730 nadd = newi-natoms;
733 sfree(*xptr);
734 *xptr = xn;
736 return newi;
739 void deprotonate(t_atoms *atoms, rvec *x)
741 int i, j;
743 j = 0;
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]);
751 j++;
754 atoms->nr = 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.
769 niter = 0;
770 nnew = 0;
773 nold = nnew;
774 nnew = add_h_low(pdbaptr, xptr, nah, ah, nterpairs, ntdb, ctdb, rN, rC, FALSE,
775 nabptr, abptr, bUpdate_pdba, bKeep_old_pdba);
776 niter++;
777 if (niter > 100)
779 gmx_fatal(FARGS, "More than 100 iterations of add_h. Maybe you are trying to replace an added atom (this is not supported)?");
782 while (nnew > nold);
784 if (!bAllowMissing)
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);
791 return nnew;
794 int protonate(t_atoms **atomsptr, rvec **xptr, t_protonate *protdata)
796 #define NTERPAIRS 1
797 t_atoms *atoms;
798 gmx_bool bUpdate_pdba, bKeep_old_pdba;
799 int nntdb, nctdb, nt, ct;
800 int nadd;
802 atoms = NULL;
803 if (!protdata->bInit)
805 if (debug)
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);
818 if (nntdb < 1)
820 gmx_fatal(FARGS, "no N-terminus database");
822 nctdb = read_ter_db(protdata->FF, 'c', &protdata->ctdb, protdata->atype);
823 if (nctdb < 1)
825 gmx_fatal(FARGS, "no C-terminus database");
828 /* set terminus types: -NH3+ (different for Proline) and -COO- */
829 atoms = *atomsptr;
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)
838 nt = 3;
840 else
842 nt = 1;
844 ct = 1;
846 else
848 nt = 0;
849 ct = 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);
857 protdata->rN[0] = 0;
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;
864 bUpdate_pdba = TRUE;
865 bKeep_old_pdba = TRUE;
867 /* clear hackblocks: */
868 protdata->nab = NULL;
869 protdata->ab = NULL;
871 /* set flag to show we're initialized: */
872 protdata->bInit = TRUE;
874 else
876 if (debug)
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;
886 /* now protonate */
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;
897 if (debug)
899 fprintf(debug, "natoms: %d -> %d (nadd=%d)\n",
900 protdata->upatoms->nr, protdata->patoms->nr, nadd);
902 return nadd;
903 #undef NTERPAIRS