merge with upstream gromacs
[gromacs/adressmacs.git] / src / kernel / genhydro.c
blob8b83dc9362f1bb78199fe69f1709b61bebf5e35f
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
40 #include <time.h>
41 #include <ctype.h>
42 #include "sysstuff.h"
43 #include "typedefs.h"
44 #include "smalloc.h"
45 #include "copyrite.h"
46 #include "string2.h"
47 #include "confio.h"
48 #include "symtab.h"
49 #include "vec.h"
50 #include "statutil.h"
51 #include "futil.h"
52 #include "gmx_fatal.h"
53 #include "physics.h"
54 #include "calch.h"
55 #include "genhydro.h"
56 #include "h_db.h"
57 #include "ter_db.h"
58 #include "resall.h"
59 #include "pgutil.h"
60 #include "network.h"
62 static void copy_atom(t_atoms *atoms1,int a1,t_atoms *atoms2,int a2)
64 atoms2->atom[a2] = atoms1->atom[a1];
65 snew(atoms2->atomname[a2],1);
66 *atoms2->atomname[a2]=strdup(*atoms1->atomname[a1]);
69 static atom_id pdbasearch_atom(const char *name,int resind,t_atoms *pdba,
70 const char *searchtype,bool bAllowMissing)
72 int i;
74 for(i=0; (i<pdba->nr) && (pdba->atom[i].resind != resind); i++)
77 return search_atom(name,i,pdba->nr,pdba->atom,pdba->atomname,
78 searchtype,bAllowMissing);
81 static void hacksearch_atom(int *ii, int *jj, char *name,
82 int nab[], t_hack *ab[],
83 int resind, t_atoms *pdba)
85 int i,j;
87 *ii=-1;
88 if (name[0] == '-') {
89 name++;
90 resind--;
92 for(i=0; (i<pdba->nr) && (pdba->atom[i].resind != resind); i++)
94 for( ; (i<pdba->nr) && (pdba->atom[i].resind == resind) && (*ii<0); i++)
95 for(j=0; (j < nab[i]) && (*ii<0); j++)
96 if (ab[i][j].nname && strcmp(name,ab[i][j].nname) == 0) {
97 *ii=i;
98 *jj=j;
101 return;
104 void dump_ab(FILE *out,int natom,int nab[], t_hack *ab[], bool bHeader)
106 int i,j;
108 #define SS(s) (s)?(s):"-"
109 /* dump ab */
110 if (bHeader)
111 fprintf(out,"ADDBLOCK (t_hack) natom=%d\n"
112 "%4s %2s %-4s %-4s %2s %-4s %-4s %-4s %-4s %1s %s\n",
113 natom,"atom","nr","old","new","tp","ai","aj","ak","al","a","x");
114 for(i=0; i<natom; i++)
115 for(j=0; j<nab[i]; j++)
116 fprintf(out,"%4d %2d %-4s %-4s %2d %-4s %-4s %-4s %-4s %s %g %g %g\n",
117 i+1, ab[i][j].nr, SS(ab[i][j].oname), SS(ab[i][j].nname),
118 ab[i][j].tp,
119 SS(ab[i][j].AI), SS(ab[i][j].AJ),
120 SS(ab[i][j].AK), SS(ab[i][j].AL),
121 ab[i][j].atom?"+":"",
122 ab[i][j].newx[XX], ab[i][j].newx[YY], ab[i][j].newx[ZZ]);
123 #undef SS
126 static t_hackblock *get_hackblocks(t_atoms *pdba, int nah, t_hackblock ah[],
127 int nterpairs,
128 t_hackblock **ntdb, t_hackblock **ctdb,
129 int *rN, int *rC)
131 int i,rnr;
132 t_hackblock *hb,*ahptr;
134 /* make space */
135 snew(hb,pdba->nres);
136 /* first the termini */
137 for(i=0; i<nterpairs; i++) {
138 if (ntdb[i] != NULL) {
139 copy_t_hackblock(ntdb[i], &hb[rN[i]]);
141 if (ctdb[i] != NULL) {
142 merge_t_hackblock(ctdb[i], &hb[rC[i]]);
145 /* then the whole hdb */
146 for(rnr=0; rnr < pdba->nres; rnr++) {
147 ahptr=search_h_db(nah,ah,*pdba->resinfo[rnr].name);
148 if ( ahptr ) {
149 if (hb[rnr].name==NULL)
150 hb[rnr].name=strdup(ahptr->name);
151 merge_hacks(ahptr, &hb[rnr]);
154 return hb;
157 static const char Hnum[] = "123456";
159 static void expand_hackblocks_one(t_hackblock *hbr, char *atomname,
160 int *nabi, t_hack **abi, bool bN, bool bC)
162 int j, k, l, d;
163 bool bIgnore;
165 /* we'll recursively add atoms to atoms */
166 for(j=0; j < hbr->nhack; j++) {
167 /* first check if we're in the N- or C-terminus, then we should ignore
168 all hacks involving atoms from resp. previous or next residue
169 (i.e. which name begins with '-' (N) or '+' (C) */
170 bIgnore = FALSE;
171 if ( bN ) /* N-terminus: ignore '-' */
172 for(k=0; k<4 && hbr->hack[j].a[k] && !bIgnore; k++)
173 bIgnore = hbr->hack[j].a[k][0]=='-';
174 if ( bC ) /* C-terminus: ignore '+' */
175 for(k=0; k<4 && hbr->hack[j].a[k] && !bIgnore; k++)
176 bIgnore = hbr->hack[j].a[k][0]=='+';
177 /* must be either hdb entry (tp>0) or add from tdb (oname==NULL)
178 and first control aton (AI) matches this atom or
179 delete/replace from tdb (oname!=NULL) and oname matches this atom */
180 if (debug) fprintf(debug," %s",
181 hbr->hack[j].oname?hbr->hack[j].oname:hbr->hack[j].AI);
183 if ( !bIgnore &&
184 ( ( ( hbr->hack[j].tp > 0 || hbr->hack[j].oname==NULL ) &&
185 strcmp(atomname, hbr->hack[j].AI) == 0 ) ||
186 ( hbr->hack[j].oname!=NULL &&
187 strcmp(atomname, hbr->hack[j].oname) == 0) ) ) {
188 /* now expand all hacks for this atom */
189 if (debug) fprintf(debug," +%dh",hbr->hack[j].nr);
190 srenew(*abi,*nabi + hbr->hack[j].nr);
191 for(k=0; k < hbr->hack[j].nr; k++) {
192 copy_t_hack(&hbr->hack[j], &(*abi)[*nabi + k]);
193 for(d=0; d<DIM; d++)
194 (*abi)[*nabi + k].newx[d]=NOTSET;
195 /* if we're adding (oname==NULL) and don't have a new name (nname)
196 yet, build it from atomname */
197 if ( (*abi)[*nabi + k].nname==NULL ) {
198 if ( (*abi)[*nabi + k].oname==NULL ) {
199 (*abi)[*nabi + k].nname=strdup(atomname);
200 (*abi)[*nabi + k].nname[0]='H';
202 } else {
203 if (gmx_debug_at) {
204 fprintf(debug,"Hack '%s' %d, replacing nname '%s' with '%s' (old name '%s')\n",
205 atomname,j,
206 (*abi)[*nabi + k].nname,hbr->hack[j].nname,
207 (*abi)[*nabi + k].oname ? (*abi)[*nabi + k].oname : "");
209 sfree((*abi)[*nabi + k].nname);
210 (*abi)[*nabi + k].nname=strdup(hbr->hack[j].nname);
212 /* if adding more than one atom, number them */
213 if ( hbr->hack[j].nr > 1 ) {
214 l = strlen((*abi)[*nabi + k].nname);
215 srenew((*abi)[*nabi + k].nname, l+2);
216 (*abi)[*nabi + k].nname[l] = Hnum[k]; /* 1, 2, 3 .... */
217 (*abi)[*nabi + k].nname[l+1] = '\0';
220 (*nabi) += hbr->hack[j].nr;
222 /* add hacks to atoms we've just added */
223 if ( hbr->hack[j].tp > 0 || hbr->hack[j].oname==NULL )
224 for(k=0; k < hbr->hack[j].nr; k++)
225 expand_hackblocks_one(hbr, (*abi)[*nabi-hbr->hack[j].nr+k].nname,
226 nabi, abi, bN, bC);
231 static void expand_hackblocks(t_atoms *pdba, t_hackblock hb[],
232 int nab[], t_hack *ab[],
233 int nterpairs, int *rN, int *rC)
235 int i,j;
236 bool bN,bC;
238 for(i=0; i < pdba->nr; i++) {
239 bN = FALSE;
240 for(j=0; j<nterpairs && !bN; j++)
241 bN = pdba->atom[i].resind==rN[j];
242 bC = FALSE;
243 for(j=0; j<nterpairs && !bC; j++)
244 bC = pdba->atom[i].resind==rC[j];
246 /* add hacks to this atom */
247 expand_hackblocks_one(&hb[pdba->atom[i].resind], *pdba->atomname[i],
248 &nab[i], &ab[i], bN, bC);
250 if (debug) fprintf(debug,"\n");
253 static int check_atoms_present(t_atoms *pdba, int nab[], t_hack *ab[])
255 int i, j, k, d, rnr, nadd;
257 nadd=0;
258 for(i=0; i < pdba->nr; i++) {
259 rnr = pdba->atom[i].resind;
260 for(j=0; j<nab[i]; j++) {
261 if ( ab[i][j].oname==NULL ) {
262 /* we're adding */
263 if (ab[i][j].nname == NULL)
264 gmx_incons("ab[i][j].nname not allocated");
265 /* check if the atom is already present */
266 k = pdbasearch_atom(ab[i][j].nname, rnr, pdba, "check", TRUE);
267 if ( k != -1 ) {
268 /* We found the added atom. */
269 ab[i][j].bAlreadyPresent = TRUE;
270 if (debug) {
271 fprintf(debug,"Atom '%s' in residue '%s' %d is already present\n",
272 ab[i][j].nname,
273 *pdba->resinfo[rnr].name,pdba->resinfo[rnr].nr);
275 } else {
276 ab[i][j].bAlreadyPresent = FALSE;
277 /* count how many atoms we'll add */
278 nadd++;
280 } else if ( ab[i][j].nname==NULL ) {
281 /* we're deleting */
282 nadd--;
287 return nadd;
290 static void calc_all_pos(t_atoms *pdba, rvec x[], int nab[], t_hack *ab[],
291 bool bCheckMissing)
293 int i, j, ii, jj, m, ia, d, rnr,l=0;
294 #define MAXH 4
295 rvec xa[4]; /* control atoms for calc_h_pos */
296 rvec xh[MAXH]; /* hydrogen positions from calc_h_pos */
297 bool bFoundAll;
299 jj = 0;
301 for(i=0; i < pdba->nr; i++) {
302 rnr = pdba->atom[i].resind;
303 for(j=0; j < nab[i]; j+=ab[i][j].nr) {
304 /* check if we're adding: */
305 if (ab[i][j].oname==NULL && ab[i][j].tp > 0) {
306 bFoundAll = TRUE;
307 for(m=0; (m<ab[i][j].nctl && bFoundAll); m++) {
308 ia = pdbasearch_atom(ab[i][j].a[m], rnr, pdba,
309 bCheckMissing ? "atom" : "check",
310 !bCheckMissing);
311 if (ia < 0) {
312 /* not found in original atoms, might still be in t_hack (ab) */
313 hacksearch_atom(&ii, &jj, ab[i][j].a[m], nab, ab, rnr, pdba);
314 if (ii >= 0) {
315 copy_rvec(ab[ii][jj].newx, xa[m]);
316 } else {
317 bFoundAll = FALSE;
318 if (bCheckMissing) {
319 gmx_fatal(FARGS,"Atom %s not found in residue %s%d"
320 " while adding hydrogens",
321 ab[i][j].a[m],
322 *pdba->resinfo[rnr].name,
323 pdba->resinfo[rnr].nr);
326 } else
327 copy_rvec(x[ia], xa[m]);
329 if (bFoundAll) {
330 for(m=0; (m<MAXH); m++)
331 for(d=0; d<DIM; d++)
332 if (m<ab[i][j].nr)
333 xh[m][d] = 0;
334 else
335 xh[m][d] = NOTSET;
336 calc_h_pos(ab[i][j].tp, xa, xh, &l);
337 for(m=0; m<ab[i][j].nr; m++)
338 copy_rvec(xh[m],ab[i][j+m].newx);
345 static void free_ab(int natoms,int *nab,t_hack **ab)
347 int i;
349 for(i=0; i<natoms; i++) {
350 free_t_hack(nab[i], &ab[i]);
352 sfree(nab);
353 sfree(ab);
356 static int add_h_low(t_atoms **pdbaptr, rvec *xptr[],
357 int nah, t_hackblock ah[],
358 int nterpairs, t_hackblock **ntdb, t_hackblock **ctdb,
359 int *rN, int *rC, bool bCheckMissing,
360 int **nabptr, t_hack ***abptr,
361 bool bUpdate_pdba, bool bKeep_old_pdba)
363 t_atoms *newpdba=NULL,*pdba=NULL;
364 bool bSet;
365 int nadd;
366 int i,newi,j,d,natoms,nalreadypresent;
367 int *nab=NULL;
368 t_hack **ab=NULL;
369 t_hackblock *hb;
370 rvec *xn;
371 bool bKeep_ab;
373 /* set flags for adding hydrogens (according to hdb) */
374 pdba=*pdbaptr;
375 natoms=pdba->nr;
377 if (nabptr && abptr) {
378 /* the first time these will be pointers to NULL, but we will
379 return in them the completed arrays, which we will get back
380 the second time */
381 nab = *nabptr;
382 ab = *abptr;
383 bKeep_ab=TRUE;
384 if (debug) fprintf(debug,"pointer to ab found\n");
385 } else {
386 bKeep_ab=FALSE;
389 if (nab && ab) {
390 /* WOW, everything was already figured out */
391 bUpdate_pdba = FALSE;
392 if (debug) fprintf(debug,"pointer to non-null ab found\n");
393 } else {
394 /* We'll have to do all the hard work */
395 bUpdate_pdba = TRUE;
396 /* first get all the hackblocks for each residue: */
397 hb = get_hackblocks(pdba, nah, ah, nterpairs, ntdb, ctdb, rN, rC);
398 if (debug) dump_hb(debug, pdba->nres, hb);
400 /* expand the hackblocks to atom level */
401 snew(nab,natoms);
402 snew(ab,natoms);
403 expand_hackblocks(pdba, hb, nab, ab, nterpairs, rN, rC);
404 free_t_hackblock(pdba->nres, &hb);
407 if (debug) {
408 fprintf(debug,"before calc_all_pos\n");
409 dump_ab(debug, natoms, nab, ab, TRUE);
412 /* Now calc the positions */
413 calc_all_pos(pdba, *xptr, nab, ab, bCheckMissing);
415 if (debug) {
416 fprintf(debug,"after calc_all_pos\n");
417 dump_ab(debug, natoms, nab, ab, TRUE);
420 if (bUpdate_pdba) {
421 /* we don't have to add atoms that are already present in pdba,
422 so we will remove them from the ab (t_hack) */
423 nadd = check_atoms_present(pdba, nab, ab);
424 if (debug) {
425 fprintf(debug, "removed add hacks that were already in pdba:\n");
426 dump_ab(debug, natoms, nab, ab, TRUE);
427 fprintf(debug, "will be adding %d atoms\n",nadd);
430 /* Copy old atoms, making space for new ones */
431 snew(newpdba,1);
432 init_t_atoms(newpdba,natoms+nadd,FALSE);
433 newpdba->nres = pdba->nres;
434 sfree(newpdba->resinfo);
435 newpdba->resinfo = pdba->resinfo;
436 } else {
437 nadd = 0;
439 if (debug) fprintf(debug,"snew xn for %d old + %d new atoms %d total)\n",
440 natoms, nadd, natoms+nadd);
442 if (nadd == 0) {
443 /* There is nothing to do: return now */
444 if (!bKeep_ab) {
445 free_ab(natoms,nab,ab);
448 return natoms;
451 snew(xn,natoms+nadd);
452 newi=0;
453 for(i=0; (i<natoms); i++) {
454 /* check if this atom wasn't scheduled for deletion */
455 if ( nab[i]==0 || (ab[i][0].nname != NULL) ) {
456 if (newi >= natoms+nadd) {
457 /*gmx_fatal(FARGS,"Not enough space for adding atoms");*/
458 nadd+=10;
459 srenew(xn,natoms+nadd);
460 if (bUpdate_pdba) {
461 srenew(newpdba->atom,natoms+nadd);
462 srenew(newpdba->atomname,natoms+nadd);
464 debug_gmx();
466 if (debug) fprintf(debug,"(%3d) %3d %4s %4s%3d %3d",
467 i+1, newi+1, *pdba->atomname[i],
468 *pdba->resinfo[pdba->atom[i].resind].name,
469 pdba->resinfo[pdba->atom[i].resind].nr, nab[i]);
470 if (bUpdate_pdba)
471 copy_atom(pdba,i, newpdba,newi);
472 copy_rvec((*xptr)[i],xn[newi]);
473 /* process the hacks for this atom */
474 nalreadypresent = 0;
475 for(j=0; j<nab[i]; j++) {
476 if ( ab[i][j].oname==NULL ) { /* add */
477 newi++;
478 if (newi >= natoms+nadd) {
479 /* gmx_fatal(FARGS,"Not enough space for adding atoms");*/
480 nadd+=10;
481 srenew(xn,natoms+nadd);
482 if (bUpdate_pdba) {
483 srenew(newpdba->atom,natoms+nadd);
484 srenew(newpdba->atomname,natoms+nadd);
486 debug_gmx();
488 if (bUpdate_pdba) {
489 newpdba->atom[newi].resind=pdba->atom[i].resind;
491 if (debug) fprintf(debug," + %d",newi+1);
493 if (ab[i][j].nname != NULL &&
494 (ab[i][j].oname == NULL ||
495 strcmp(ab[i][j].oname,*newpdba->atomname[newi]) == 0)) {
496 /* add or replace */
497 if (ab[i][j].oname == NULL && ab[i][j].bAlreadyPresent) {
498 /* This atom is already present, copy it from the input. */
499 nalreadypresent++;
500 if (bUpdate_pdba) {
501 copy_atom(pdba,i+nalreadypresent, newpdba,newi);
503 copy_rvec((*xptr)[i+nalreadypresent],xn[newi]);
504 } else {
505 if (bUpdate_pdba) {
506 if (gmx_debug_at) {
507 fprintf(debug,"Replacing %d '%s' with (old name '%s') %s\n",
508 newi,
509 (newpdba->atomname[newi] && *newpdba->atomname[newi]) ? *newpdba->atomname[newi] : "",
510 ab[i][j].oname ? ab[i][j].oname : "",
511 ab[i][j].nname);
513 snew(newpdba->atomname[newi],1);
514 *newpdba->atomname[newi]=strdup(ab[i][j].nname);
515 if ( ab[i][j].oname!=NULL && ab[i][j].atom ) { /* replace */
516 /* newpdba->atom[newi].m = ab[i][j].atom->m; */
517 /* newpdba->atom[newi].q = ab[i][j].atom->q; */
518 /* newpdba->atom[newi].type = ab[i][j].atom->type; */
521 bSet=TRUE;
522 for(d=0; d<DIM; d++)
523 bSet = bSet && ab[i][j].newx[d]!=NOTSET;
524 if (bSet)
525 copy_rvec(ab[i][j].newx, xn[newi]);
527 if (bUpdate_pdba && debug)
528 fprintf(debug," %s %g %g",*newpdba->atomname[newi],
529 newpdba->atom[newi].m,newpdba->atom[newi].q);
532 newi++;
533 i += nalreadypresent;
534 if (debug) fprintf(debug,"\n");
537 if (bUpdate_pdba)
538 newpdba->nr = newi;
540 if ( bKeep_ab ) {
541 *nabptr=nab;
542 *abptr=ab;
543 } else {
544 /* Clean up */
545 free_ab(natoms,nab,ab);
548 if ( bUpdate_pdba ) {
549 if ( !bKeep_old_pdba ) {
550 for(i=0; i < natoms; i++) {
551 /* Do not free the atomname string itself, it might be in symtab */
552 /* sfree(*(pdba->atomname[i])); */
553 /* sfree(pdba->atomname[i]); */
555 sfree(pdba->atomname);
556 sfree(pdba->atom);
557 sfree(pdba->pdbinfo);
558 sfree(pdba);
560 *pdbaptr=newpdba;
561 } else
562 nadd = newi-natoms;
564 sfree(*xptr);
565 *xptr=xn;
567 return newi;
570 void deprotonate(t_atoms *atoms,rvec *x)
572 int i,j;
574 j=0;
575 for(i=0; i<atoms->nr; i++) {
576 if ( (*atoms->atomname[i])[0] != 'H' ) {
577 atoms->atomname[j]=atoms->atomname[i];
578 atoms->atom[j]=atoms->atom[i];
579 copy_rvec(x[i],x[j]);
580 j++;
583 atoms->nr=j;
586 int add_h(t_atoms **pdbaptr, rvec *xptr[],
587 int nah, t_hackblock ah[],
588 int nterpairs, t_hackblock **ntdb, t_hackblock **ctdb,
589 int *rN, int *rC, bool bAllowMissing,
590 int **nabptr, t_hack ***abptr,
591 bool bUpdate_pdba, bool bKeep_old_pdba)
593 int nold,nnew,niter;
595 /* Here we loop to be able to add atoms to added atoms.
596 * We should not check for missing atoms here.
598 niter = 0;
599 nnew = 0;
600 do {
601 nold = nnew;
602 nnew = add_h_low(pdbaptr,xptr,nah,ah,nterpairs,ntdb,ctdb,rN,rC,FALSE,
603 nabptr,abptr,bUpdate_pdba,bKeep_old_pdba);
604 niter++;
605 if (niter > 100) {
606 gmx_fatal(FARGS,"More than 100 iterations of add_h. Maybe you are trying to replace an added atom (this is not supported)?");
608 } while (nnew > nold);
610 if (!bAllowMissing) {
611 /* Call add_h_low once more, now only for the missing atoms check */
612 add_h_low(pdbaptr,xptr,nah,ah,nterpairs,ntdb,ctdb,rN,rC,TRUE,
613 nabptr,abptr,bUpdate_pdba,bKeep_old_pdba);
616 return nnew;
619 int protonate(t_atoms **atomsptr,rvec **xptr,t_protonate *protdata)
621 #define NTERPAIRS 1
622 t_atoms *atoms;
623 bool bUpdate_pdba,bKeep_old_pdba;
624 int nntdb,nctdb,nt,ct;
625 int nadd;
627 atoms=NULL;
628 if ( !protdata->bInit ) {
629 if (debug) fprintf(debug,"protonate: Initializing protdata\n");
630 /* set forcefield to use: */
631 strcpy(protdata->FF,"ffgmx2");
632 /* get the databases: */
633 protdata->nah=read_h_db(protdata->FF,&protdata->ah);
634 open_symtab(&protdata->tab);
635 protdata->atype=read_atype(protdata->FF,&protdata->tab);
636 nntdb = read_ter_db(protdata->FF,'n',&protdata->ntdb,protdata->atype);
637 if (nntdb < 1)
638 gmx_fatal(FARGS,"no n-terminus db");
639 nctdb = read_ter_db(protdata->FF,'c',&protdata->ctdb,protdata->atype);
640 if (nctdb < 1)
641 gmx_fatal(FARGS,"no c-terminus db");
643 /* set terminus types: -NH3+ (different for Proline) and -COO- */
644 atoms=*atomsptr;
645 snew(protdata->sel_ntdb, NTERPAIRS);
646 snew(protdata->sel_ctdb, NTERPAIRS);
648 if (nntdb>=4 && nctdb>=2) {
649 /* Yuk, yuk, hardcoded default termini selections !!! */
650 if (strncmp(*atoms->resinfo[atoms->atom[atoms->nr-1].resind].name,"PRO",3)==0)
651 nt = 3;
652 else
653 nt = 1;
654 ct = 1;
655 } else {
656 nt = 0;
657 ct = 0;
659 protdata->sel_ntdb[0]=&(protdata->ntdb[nt]);
660 protdata->sel_ctdb[0]=&(protdata->ctdb[ct]);
662 /* set terminal residue numbers: */
663 snew(protdata->rN, NTERPAIRS);
664 snew(protdata->rC, NTERPAIRS);
665 protdata->rN[0]=0;
666 protdata->rC[0]=atoms->atom[atoms->nr-1].resind;
668 /* keep unprotonated topology: */
669 protdata->upatoms = atoms;
670 /* we don't have these yet: */
671 protdata->patoms = NULL;
672 bUpdate_pdba=TRUE;
673 bKeep_old_pdba=TRUE;
675 /* clear hackblocks: */
676 protdata->nab=NULL;
677 protdata->ab=NULL;
679 /* set flag to show we're initialized: */
680 protdata->bInit=TRUE;
681 } else {
682 if (debug) fprintf(debug,"protonate: using available protdata\n");
683 /* add_h will need the unprotonated topoloy again: */
684 atoms = protdata->upatoms;
685 bUpdate_pdba=FALSE;
686 bKeep_old_pdba=FALSE;
689 /* now protonate */
690 nadd = add_h(&atoms, xptr, protdata->nah, protdata->ah,
691 NTERPAIRS, protdata->sel_ntdb, protdata->sel_ctdb,
692 protdata->rN, protdata->rC, TRUE,
693 &protdata->nab, &protdata->ab, bUpdate_pdba, bKeep_old_pdba);
694 if ( ! protdata->patoms )
695 /* store protonated topology */
696 protdata->patoms = atoms;
697 *atomsptr = protdata->patoms;
698 if (debug) fprintf(debug,"natoms: %d -> %d (nadd=%d)\n",
699 protdata->upatoms->nr, protdata->patoms->nr, nadd);
700 return nadd;
701 #undef NTERPAIRS