Replace most strdup with gmx_strdup
[alexxy/gromacs.git] / src / gromacs / gmxana / gmx_hbond.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2008, 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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 #include "config.h"
38 #include <math.h>
39
40 /*#define HAVE_NN_LOOPS*/
41
42 #include "gromacs/commandline/pargs.h"
43 #include "copyrite.h"
44 #include "txtdump.h"
45 #include "gromacs/math/units.h"
46 #include "macros.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/topology/index.h"
49 #include "gromacs/utility/smalloc.h"
50 #include "gromacs/math/vec.h"
51 #include "gromacs/fileio/xvgr.h"
52 #include "viewit.h"
53 #include "gstat.h"
54 #include "gromacs/utility/cstringutil.h"
55 #include "gromacs/pbcutil/pbc.h"
56 #include "correl.h"
57 #include "gmx_ana.h"
58 #include "geminate.h"
59
60 #include "gromacs/utility/futil.h"
61 #include "gromacs/fileio/matio.h"
62 #include "gromacs/fileio/tpxio.h"
63 #include "gromacs/fileio/trxio.h"
64 #include "gromacs/utility/gmxomp.h"
65
66 typedef short int t_E;
67 typedef int t_EEst;
68 #define max_hx 7
69 typedef int t_hx[max_hx];
70 #define NRHXTYPES max_hx
71 const char *hxtypenames[NRHXTYPES] =
72 {"n-n", "n-n+1", "n-n+2", "n-n+3", "n-n+4", "n-n+5", "n-n>6"};
73 #define MAXHH 4
74
75 #ifdef GMX_OPENMP
76 #define MASTER_THREAD_ONLY(threadNr) ((threadNr) == 0)
77 #else
78 #define MASTER_THREAD_ONLY(threadNr) ((threadNr) == (threadNr))
79 #endif
80
81 /* -----------------------------------------*/
82
83 enum {
84     gr0,  gr1,    grI,  grNR
85 };
86 enum {
87     hbNo, hbDist, hbHB, hbNR, hbR2
88 };
89 enum {
90     noDA, ACC, DON, DA, INGROUP
91 };
92 enum {
93     NN_NULL, NN_NONE, NN_BINARY, NN_1_over_r3, NN_dipole, NN_NR
94 };
95
96 static const char *grpnames[grNR] = {"0", "1", "I" };
97
98 static gmx_bool    bDebug = FALSE;
99
100 #define HB_NO 0
101 #define HB_YES 1<<0
102 #define HB_INS 1<<1
103 #define HB_YESINS HB_YES|HB_INS
104 #define HB_NR (1<<2)
105 #define MAXHYDRO 4
106
107 #define ISHB(h)   (((h) & 2) == 2)
108 #define ISDIST(h) (((h) & 1) == 1)
109 #define ISDIST2(h) (((h) & 4) == 4)
110 #define ISACC(h)  (((h) & 1) == 1)
111 #define ISDON(h)  (((h) & 2) == 2)
112 #define ISINGRP(h) (((h) & 4) == 4)
113
114 typedef struct {
115     int      nr;
116     int      maxnr;
117     atom_id *atoms;
118 } t_ncell;
119
120 typedef struct {
121     t_ncell d[grNR];
122     t_ncell a[grNR];
123 } t_gridcell;
124
125 typedef int     t_icell[grNR];
126 typedef atom_id h_id[MAXHYDRO];
127
128 typedef struct {
129     int      history[MAXHYDRO];
130     /* Has this hbond existed ever? If so as hbDist or hbHB or both.
131      * Result is stored as a bitmap (1 = hbDist) || (2 = hbHB)
132      */
133     /* Bitmask array which tells whether a hbond is present
134      * at a given time. Either of these may be NULL
135      */
136     int            n0;                 /* First frame a HB was found     */
137     int            nframes, maxframes; /* Amount of frames in this hbond */
138     unsigned int **h;
139     unsigned int **g;
140     /* See Xu and Berne, JPCB 105 (2001), p. 11929. We define the
141      * function g(t) = [1-h(t)] H(t) where H(t) is one when the donor-
142      * acceptor distance is less than the user-specified distance (typically
143      * 0.35 nm).
144      */
145 } t_hbond;
146
147 typedef struct {
148     int      nra, max_nra;
149     atom_id *acc;             /* Atom numbers of the acceptors     */
150     int     *grp;             /* Group index                       */
151     int     *aptr;            /* Map atom number to acceptor index */
152 } t_acceptors;
153
154 typedef struct {
155     int       nrd, max_nrd;
156     int      *don;               /* Atom numbers of the donors         */
157     int      *grp;               /* Group index                        */
158     int      *dptr;              /* Map atom number to donor index     */
159     int      *nhydro;            /* Number of hydrogens for each donor */
160     h_id     *hydro;             /* The atom numbers of the hydrogens  */
161     h_id     *nhbonds;           /* The number of HBs per H at current */
162 } t_donors;
163
164 /* Tune this to match memory requirements. It should be a signed integer type, e.g. signed char.*/
165 #define PSTYPE int
166
167 typedef struct {
168     int     len;   /* The length of frame and p. */
169     int    *frame; /* The frames at which transitio*/
170     PSTYPE *p;
171 } t_pShift;
172
173 typedef struct {
174     /* Periodicity history. Used for the reversible geminate recombination. */
175     t_pShift **pHist; /* The periodicity of every hbond in t_hbdata->hbmap:
176                        *   pHist[d][a]. We can safely assume that the same
177                        *   periodic shift holds for all hydrogens of a da-pair.
178                        *
179                        * Nowadays it only stores TRANSITIONS, and not the shift at every frame.
180                        *   That saves a LOT of memory, an hopefully kills a mysterious bug where
181                        *   pHist gets contaminated. */
182
183     PSTYPE nper;      /* The length of p2i */
184     ivec  *p2i;       /* Maps integer to periodic shift for a pair.*/
185     matrix P;         /* Projection matrix to find the box shifts. */
186     int    gemtype;   /* enumerated type */
187 } t_gemPeriod;
188
189 typedef struct {
190     int     nframes;
191     int    *Etot; /* Total energy for each frame */
192     t_E ****E;    /* Energy estimate for [d][a][h][frame-n0] */
193 } t_hbEmap;
194
195 typedef struct {
196     gmx_bool        bHBmap, bDAnr, bGem;
197     int             wordlen;
198     /* The following arrays are nframes long */
199     int             nframes, max_frames, maxhydro;
200     int            *nhb, *ndist;
201     h_id           *n_bound;
202     real           *time;
203     t_icell        *danr;
204     t_hx           *nhx;
205     /* These structures are initialized from the topology at start up */
206     t_donors        d;
207     t_acceptors     a;
208     /* This holds a matrix with all possible hydrogen bonds */
209     int             nrhb, nrdist;
210     t_hbond      ***hbmap;
211 #ifdef HAVE_NN_LOOPS
212     t_hbEmap        hbE;
213 #endif
214     /* For parallelization reasons this will have to be a pointer.
215      * Otherwise discrepancies may arise between the periodicity data
216      * seen by different threads. */
217     t_gemPeriod *per;
218 } t_hbdata;
219
220 static void clearPshift(t_pShift *pShift)
221 {
222     if (pShift->len > 0)
223     {
224         sfree(pShift->p);
225         sfree(pShift->frame);
226         pShift->len = 0;
227     }
228 }
229
230 static void calcBoxProjection(matrix B, matrix P)
231 {
232     const int vp[] = {XX, YY, ZZ};
233     int       i, j;
234     int       m, n;
235     matrix    M, N, U;
236
237     for (i = 0; i < 3; i++)
238     {
239         m = vp[i];
240         for (j = 0; j < 3; j++)
241         {
242             n       = vp[j];
243             U[m][n] = i == j ? 1 : 0;
244         }
245     }
246     m_inv(B, M);
247     for (i = 0; i < 3; i++)
248     {
249         m = vp[i];
250         mvmul(M, U[m], P[m]);
251     }
252     transpose(P, N);
253 }
254
255 static void calcBoxDistance(matrix P, rvec d, ivec ibd)
256 {
257     /* returns integer distance in box coordinates.
258      * P is the projection matrix from cartesian coordinates
259      * obtained with calcBoxProjection(). */
260     int  i;
261     rvec bd;
262     mvmul(P, d, bd);
263     /* extend it by 0.5 in all directions since (int) rounds toward 0.*/
264     for (i = 0; i < 3; i++)
265     {
266         bd[i] = bd[i] + (bd[i] < 0 ? -0.5 : 0.5);
267     }
268     ibd[XX] = (int)bd[XX];
269     ibd[YY] = (int)bd[YY];
270     ibd[ZZ] = (int)bd[ZZ];
271 }
272
273 /* Changed argument 'bMerge' into 'oneHB' below,
274  * since -contact should cause maxhydro to be 1,
275  * not just -merge.
276  * - Erik Marklund May 29, 2006
277  */
278
279 static PSTYPE periodicIndex(ivec r, t_gemPeriod *per, gmx_bool daSwap)
280 {
281     /* Try to merge hbonds on the fly. That means that if the
282      * acceptor and donor are mergable, then:
283      * 1) store the hb-info so that acceptor id > donor id,
284      * 2) add the periodic shift in pairs, so that [-x,-y,-z] is
285      *    stored in per.p2i[] whenever acceptor id < donor id.
286      * Note that [0,0,0] should already be the first element of per.p2i
287      * by the time this function is called. */
288
289     /* daSwap is TRUE if the donor and acceptor were swapped.
290      * If so, then the negative vector should be used. */
291     PSTYPE i;
292
293     if (per->p2i == NULL || per->nper == 0)
294     {
295         gmx_fatal(FARGS, "'per' not initialized properly.");
296     }
297     for (i = 0; i < per->nper; i++)
298     {
299         if (r[XX] == per->p2i[i][XX] &&
300             r[YY] == per->p2i[i][YY] &&
301             r[ZZ] == per->p2i[i][ZZ])
302         {
303             return i;
304         }
305     }
306     /* Not found apparently. Add it to the list! */
307     /* printf("New shift found: %i,%i,%i\n",r[XX],r[YY],r[ZZ]); */
308
309 #pragma omp critical
310     {
311         if (!per->p2i)
312         {
313             fprintf(stderr, "p2i not initialized. This shouldn't happen!\n");
314             snew(per->p2i, 1);
315         }
316         else
317         {
318             srenew(per->p2i, per->nper+2);
319         }
320         copy_ivec(r, per->p2i[per->nper]);
321         (per->nper)++;
322
323         /* Add the mirror too. It's rather likely that it'll be needed. */
324         per->p2i[per->nper][XX] = -r[XX];
325         per->p2i[per->nper][YY] = -r[YY];
326         per->p2i[per->nper][ZZ] = -r[ZZ];
327         (per->nper)++;
328     } /* omp critical */
329     return per->nper - 1 - (daSwap ? 0 : 1);
330 }
331
332 static t_hbdata *mk_hbdata(gmx_bool bHBmap, gmx_bool bDAnr, gmx_bool oneHB, gmx_bool bGem, int gemmode)
333 {
334     t_hbdata *hb;
335
336     snew(hb, 1);
337     hb->wordlen = 8*sizeof(unsigned int);
338     hb->bHBmap  = bHBmap;
339     hb->bDAnr   = bDAnr;
340     hb->bGem    = bGem;
341     if (oneHB)
342     {
343         hb->maxhydro = 1;
344     }
345     else
346     {
347         hb->maxhydro = MAXHYDRO;
348     }
349     snew(hb->per, 1);
350     hb->per->gemtype = bGem ? gemmode : 0;
351
352     return hb;
353 }
354
355 static void mk_hbmap(t_hbdata *hb)
356 {
357     int  i, j;
358
359     snew(hb->hbmap, hb->d.nrd);
360     for (i = 0; (i < hb->d.nrd); i++)
361     {
362         snew(hb->hbmap[i], hb->a.nra);
363         if (hb->hbmap[i] == NULL)
364         {
365             gmx_fatal(FARGS, "Could not allocate enough memory for hbmap");
366         }
367         for (j = 0; (j > hb->a.nra); j++)
368         {
369             hb->hbmap[i][j] = NULL;
370         }
371     }
372 }
373
374 /* Consider redoing pHist so that is only stores transitions between
375  * periodicities and not the periodicity for all frames. This eats heaps of memory. */
376 static void mk_per(t_hbdata *hb)
377 {
378     int i, j;
379     if (hb->bGem)
380     {
381         snew(hb->per->pHist, hb->d.nrd);
382         for (i = 0; i < hb->d.nrd; i++)
383         {
384             snew(hb->per->pHist[i], hb->a.nra);
385             if (hb->per->pHist[i] == NULL)
386             {
387                 gmx_fatal(FARGS, "Could not allocate enough memory for per->pHist");
388             }
389             for (j = 0; j < hb->a.nra; j++)
390             {
391                 clearPshift(&(hb->per->pHist[i][j]));
392             }
393         }
394         /* add the [0,0,0] shift to element 0 of p2i. */
395         snew(hb->per->p2i, 1);
396         clear_ivec(hb->per->p2i[0]);
397         hb->per->nper = 1;
398     }
399 }
400
401 #ifdef HAVE_NN_LOOPS
402 static void mk_hbEmap (t_hbdata *hb, int n0)
403 {
404     int i, j, k;
405     hb->hbE.E       = NULL;
406     hb->hbE.nframes = 0;
407     snew(hb->hbE.E, hb->d.nrd);
408     for (i = 0; i < hb->d.nrd; i++)
409     {
410         snew(hb->hbE.E[i], hb->a.nra);
411         for (j = 0; j < hb->a.nra; j++)
412         {
413             snew(hb->hbE.E[i][j], MAXHYDRO);
414             for (k = 0; k < MAXHYDRO; k++)
415             {
416                 hb->hbE.E[i][j][k] = NULL;
417             }
418         }
419     }
420     hb->hbE.Etot = NULL;
421 }
422
423 static void free_hbEmap (t_hbdata *hb)
424 {
425     int i, j, k;
426     for (i = 0; i < hb->d.nrd; i++)
427     {
428         for (j = 0; j < hb->a.nra; j++)
429         {
430             for (k = 0; k < MAXHYDRO; k++)
431             {
432                 sfree(hb->hbE.E[i][j][k]);
433             }
434             sfree(hb->hbE.E[i][j]);
435         }
436         sfree(hb->hbE.E[i]);
437     }
438     sfree(hb->hbE.E);
439     sfree(hb->hbE.Etot);
440 }
441
442 static void addFramesNN(t_hbdata *hb, int frame)
443 {
444
445 #define DELTAFRAMES_HBE 10
446
447     int d, a, h, nframes;
448
449     if (frame >= hb->hbE.nframes)
450     {
451         nframes =  hb->hbE.nframes + DELTAFRAMES_HBE;
452         srenew(hb->hbE.Etot, nframes);
453
454         for (d = 0; d < hb->d.nrd; d++)
455         {
456             for (a = 0; a < hb->a.nra; a++)
457             {
458                 for (h = 0; h < hb->d.nhydro[d]; h++)
459                 {
460                     srenew(hb->hbE.E[d][a][h], nframes);
461                 }
462             }
463         }
464
465         hb->hbE.nframes += DELTAFRAMES_HBE;
466     }
467 }
468
469 static t_E calcHbEnergy(int d, int a, int h, rvec x[], t_EEst EEst,
470                         matrix box, rvec hbox, t_donors *donors)
471 {
472     /* d     - donor atom
473      * a     - acceptor atom
474      * h     - hydrogen
475      * alpha - angle between dipoles
476      * x[]   - atomic positions
477      * EEst  - the type of energy estimate (see enum in hbplugin.h)
478      * box   - the box vectors   \
479      * hbox  - half box lengths  _These two are only needed for the pbc correction
480      */
481
482     t_E  E;
483     rvec dist;
484     rvec dipole[2], xmol[3], xmean[2];
485     int  i;
486     real r, realE;
487
488     if (d == a)
489     {
490         /* Self-interaction */
491         return NONSENSE_E;
492     }
493
494     switch (EEst)
495     {
496         case NN_BINARY:
497             /* This is a simple binary existence function that sets E=1 whenever
498              * the distance between the oxygens is equal too or less than 0.35 nm.
499              */
500             rvec_sub(x[d], x[a], dist);
501             pbc_correct_gem(dist, box, hbox);
502             if (norm(dist) <= 0.35)
503             {
504                 E = 1;
505             }
506             else
507             {
508                 E = 0;
509             }
510             break;
511
512         case NN_1_over_r3:
513             /* Negative potential energy of a dipole.
514              * E = -cos(alpha) * 1/r^3 */
515
516             copy_rvec(x[d], xmol[0]);                                 /* donor */
517             copy_rvec(x[donors->hydro[donors->dptr[d]][0]], xmol[1]); /* hydrogen */
518             copy_rvec(x[donors->hydro[donors->dptr[d]][1]], xmol[2]); /* hydrogen */
519
520             svmul(15.9994*(1/1.008), xmol[0], xmean[0]);
521             rvec_inc(xmean[0], xmol[1]);
522             rvec_inc(xmean[0], xmol[2]);
523             for (i = 0; i < 3; i++)
524             {
525                 xmean[0][i] /= (15.9994 + 1.008 + 1.008)/1.008;
526             }
527
528             /* Assumes that all acceptors are also donors. */
529             copy_rvec(x[a], xmol[0]);                                 /* acceptor */
530             copy_rvec(x[donors->hydro[donors->dptr[a]][0]], xmol[1]); /* hydrogen */
531             copy_rvec(x[donors->hydro[donors->dptr[a]][1]], xmol[2]); /* hydrogen */
532
533
534             svmul(15.9994*(1/1.008), xmol[0], xmean[1]);
535             rvec_inc(xmean[1], xmol[1]);
536             rvec_inc(xmean[1], xmol[2]);
537             for (i = 0; i < 3; i++)
538             {
539                 xmean[1][i] /= (15.9994 + 1.008 + 1.008)/1.008;
540             }
541
542             rvec_sub(xmean[0], xmean[1], dist);
543             pbc_correct_gem(dist, box, hbox);
544             r = norm(dist);
545
546             realE = pow(r, -3.0);
547             E     = (t_E)(SCALEFACTOR_E * realE);
548             break;
549
550         case NN_dipole:
551             /* Negative potential energy of a (unpolarizable) dipole.
552              * E = -cos(alpha) * 1/r^3 */
553             clear_rvec(dipole[1]);
554             clear_rvec(dipole[0]);
555
556             copy_rvec(x[d], xmol[0]);                                 /* donor */
557             copy_rvec(x[donors->hydro[donors->dptr[d]][0]], xmol[1]); /* hydrogen */
558             copy_rvec(x[donors->hydro[donors->dptr[d]][1]], xmol[2]); /* hydrogen */
559
560             rvec_inc(dipole[0], xmol[1]);
561             rvec_inc(dipole[0], xmol[2]);
562             for (i = 0; i < 3; i++)
563             {
564                 dipole[0][i] *= 0.5;
565             }
566             rvec_dec(dipole[0], xmol[0]);
567
568             svmul(15.9994*(1/1.008), xmol[0], xmean[0]);
569             rvec_inc(xmean[0], xmol[1]);
570             rvec_inc(xmean[0], xmol[2]);
571             for (i = 0; i < 3; i++)
572             {
573                 xmean[0][i] /= (15.9994 + 1.008 + 1.008)/1.008;
574             }
575
576             /* Assumes that all acceptors are also donors. */
577             copy_rvec(x[a], xmol[0]);                                 /* acceptor */
578             copy_rvec(x[donors->hydro[donors->dptr[a]][0]], xmol[1]); /* hydrogen */
579             copy_rvec(x[donors->hydro[donors->dptr[a]][2]], xmol[2]); /* hydrogen */
580
581
582             rvec_inc(dipole[1], xmol[1]);
583             rvec_inc(dipole[1], xmol[2]);
584             for (i = 0; i < 3; i++)
585             {
586                 dipole[1][i] *= 0.5;
587             }
588             rvec_dec(dipole[1], xmol[0]);
589
590             svmul(15.9994*(1/1.008), xmol[0], xmean[1]);
591             rvec_inc(xmean[1], xmol[1]);
592             rvec_inc(xmean[1], xmol[2]);
593             for (i = 0; i < 3; i++)
594             {
595                 xmean[1][i] /= (15.9994 + 1.008 + 1.008)/1.008;
596             }
597
598             rvec_sub(xmean[0], xmean[1], dist);
599             pbc_correct_gem(dist, box, hbox);
600             r = norm(dist);
601
602             double cosalpha = cos_angle(dipole[0], dipole[1]);
603             realE = cosalpha * pow(r, -3.0);
604             E     = (t_E)(SCALEFACTOR_E * realE);
605             break;
606
607         default:
608             printf("Can't do that type of energy estimate: %i\n.", EEst);
609             E = NONSENSE_E;
610     }
611
612     return E;
613 }
614
615 static void storeHbEnergy(t_hbdata *hb, int d, int a, int h, t_E E, int frame)
616 {
617     /* hb - hbond data structure
618        d  - donor
619        a  - acceptor
620        h  - hydrogen
621        E  - estimate of the energy
622        frame - the current frame.
623      */
624
625     /* Store the estimated energy */
626     if (E == NONSENSE_E)
627     {
628         E = 0;
629     }
630
631     hb->hbE.E[d][a][h][frame] = E;
632
633 #pragma omp critical
634     {
635         hb->hbE.Etot[frame] += E;
636     }
637 }
638 #endif /* HAVE_NN_LOOPS */
639
640
641 /* Finds -v[] in the periodicity index */
642 static int findMirror(PSTYPE p, ivec v[], PSTYPE nper)
643 {
644     PSTYPE i;
645     ivec   u;
646     for (i = 0; i < nper; i++)
647     {
648         if (v[i][XX] == -(v[p][XX]) &&
649             v[i][YY] == -(v[p][YY]) &&
650             v[i][ZZ] == -(v[p][ZZ]))
651         {
652             return (int)i;
653         }
654     }
655     printf("Couldn't find mirror of [%i, %i, %i], index \n",
656            v[p][XX],
657            v[p][YY],
658            v[p][ZZ]);
659     return -1;
660 }
661
662
663 static void add_frames(t_hbdata *hb, int nframes)
664 {
665     int  i, j, k, l;
666
667     if (nframes >= hb->max_frames)
668     {
669         hb->max_frames += 4096;
670         srenew(hb->time, hb->max_frames);
671         srenew(hb->nhb, hb->max_frames);
672         srenew(hb->ndist, hb->max_frames);
673         srenew(hb->n_bound, hb->max_frames);
674         srenew(hb->nhx, hb->max_frames);
675         if (hb->bDAnr)
676         {
677             srenew(hb->danr, hb->max_frames);
678         }
679     }
680     hb->nframes = nframes;
681 }
682
683 #define OFFSET(frame) (frame / 32)
684 #define MASK(frame)   (1 << (frame % 32))
685
686 static void _set_hb(unsigned int hbexist[], unsigned int frame, gmx_bool bValue)
687 {
688     if (bValue)
689     {
690         hbexist[OFFSET(frame)] |= MASK(frame);
691     }
692     else
693     {
694         hbexist[OFFSET(frame)] &= ~MASK(frame);
695     }
696 }
697
698 static gmx_bool is_hb(unsigned int hbexist[], int frame)
699 {
700     return ((hbexist[OFFSET(frame)] & MASK(frame)) != 0) ? 1 : 0;
701 }
702
703 static void set_hb(t_hbdata *hb, int id, int ih, int ia, int frame, int ihb)
704 {
705     unsigned int *ghptr = NULL;
706
707     if (ihb == hbHB)
708     {
709         ghptr = hb->hbmap[id][ia]->h[ih];
710     }
711     else if (ihb == hbDist)
712     {
713         ghptr = hb->hbmap[id][ia]->g[ih];
714     }
715     else
716     {
717         gmx_fatal(FARGS, "Incomprehensible iValue %d in set_hb", ihb);
718     }
719
720     _set_hb(ghptr, frame-hb->hbmap[id][ia]->n0, TRUE);
721 }
722
723 static void addPshift(t_pShift *pHist, PSTYPE p, int frame)
724 {
725     if (pHist->len == 0)
726     {
727         snew(pHist->frame, 1);
728         snew(pHist->p, 1);
729         pHist->len      = 1;
730         pHist->frame[0] = frame;
731         pHist->p[0]     = p;
732         return;
733     }
734     else
735     if (pHist->p[pHist->len-1] != p)
736     {
737         pHist->len++;
738         srenew(pHist->frame, pHist->len);
739         srenew(pHist->p, pHist->len);
740         pHist->frame[pHist->len-1] = frame;
741         pHist->p[pHist->len-1]     = p;
742     }     /* Otherwise, there is no transition. */
743     return;
744 }
745
746 static PSTYPE getPshift(t_pShift pHist, int frame)
747 {
748     int f, i;
749
750     if (pHist.len == 0
751         || (pHist.len > 0 && pHist.frame[0] > frame))
752     {
753         return -1;
754     }
755
756     for (i = 0; i < pHist.len; i++)
757     {
758         f = pHist.frame[i];
759         if (f == frame)
760         {
761             return pHist.p[i];
762         }
763         if (f > frame)
764         {
765             return pHist.p[i-1];
766         }
767     }
768
769     /* It seems that frame is after the last periodic transition. Return the last periodicity. */
770     return pHist.p[pHist.len-1];
771 }
772
773 static void add_ff(t_hbdata *hbd, int id, int h, int ia, int frame, int ihb, PSTYPE p)
774 {
775     int         i, j, n;
776     t_hbond    *hb       = hbd->hbmap[id][ia];
777     int         maxhydro = min(hbd->maxhydro, hbd->d.nhydro[id]);
778     int         wlen     = hbd->wordlen;
779     int         delta    = 32*wlen;
780     gmx_bool    bGem     = hbd->bGem;
781
782     if (!hb->h[0])
783     {
784         hb->n0        = frame;
785         hb->maxframes = delta;
786         for (i = 0; (i < maxhydro); i++)
787         {
788             snew(hb->h[i], hb->maxframes/wlen);
789             snew(hb->g[i], hb->maxframes/wlen);
790         }
791     }
792     else
793     {
794         hb->nframes = frame-hb->n0;
795         /* We need a while loop here because hbonds may be returning
796          * after a long time.
797          */
798         while (hb->nframes >= hb->maxframes)
799         {
800             n = hb->maxframes + delta;
801             for (i = 0; (i < maxhydro); i++)
802             {
803                 srenew(hb->h[i], n/wlen);
804                 srenew(hb->g[i], n/wlen);
805                 for (j = hb->maxframes/wlen; (j < n/wlen); j++)
806                 {
807                     hb->h[i][j] = 0;
808                     hb->g[i][j] = 0;
809                 }
810             }
811
812             hb->maxframes = n;
813         }
814     }
815     if (frame >= 0)
816     {
817         set_hb(hbd, id, h, ia, frame, ihb);
818         if (bGem)
819         {
820             if (p >= hbd->per->nper)
821             {
822                 gmx_fatal(FARGS, "invalid shift: p=%u, nper=%u", p, hbd->per->nper);
823             }
824             else
825             {
826                 addPshift(&(hbd->per->pHist[id][ia]), p, frame);
827             }
828
829         }
830     }
831
832 }
833
834 static void inc_nhbonds(t_donors *ddd, int d, int h)
835 {
836     int j;
837     int dptr = ddd->dptr[d];
838
839     for (j = 0; (j < ddd->nhydro[dptr]); j++)
840     {
841         if (ddd->hydro[dptr][j] == h)
842         {
843             ddd->nhbonds[dptr][j]++;
844             break;
845         }
846     }
847     if (j == ddd->nhydro[dptr])
848     {
849         gmx_fatal(FARGS, "No such hydrogen %d on donor %d\n", h+1, d+1);
850     }
851 }
852
853 static int _acceptor_index(t_acceptors *a, int grp, atom_id i,
854                            const char *file, int line)
855 {
856     int ai = a->aptr[i];
857
858     if (a->grp[ai] != grp)
859     {
860         if (debug && bDebug)
861         {
862             fprintf(debug, "Acc. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
863                     ai, a->grp[ai], grp, file, line);
864         }
865         return NOTSET;
866     }
867     else
868     {
869         return ai;
870     }
871 }
872 #define acceptor_index(a, grp, i) _acceptor_index(a, grp, i, __FILE__, __LINE__)
873
874 static int _donor_index(t_donors *d, int grp, atom_id i, const char *file, int line)
875 {
876     int di = d->dptr[i];
877
878     if (di == NOTSET)
879     {
880         return NOTSET;
881     }
882
883     if (d->grp[di] != grp)
884     {
885         if (debug && bDebug)
886         {
887             fprintf(debug, "Don. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
888                     di, d->grp[di], grp, file, line);
889         }
890         return NOTSET;
891     }
892     else
893     {
894         return di;
895     }
896 }
897 #define donor_index(d, grp, i) _donor_index(d, grp, i, __FILE__, __LINE__)
898
899 static gmx_bool isInterchangable(t_hbdata *hb, int d, int a, int grpa, int grpd)
900 {
901     /* g_hbond doesn't allow overlapping groups */
902     if (grpa != grpd)
903     {
904         return FALSE;
905     }
906     return
907         donor_index(&hb->d, grpd, a) != NOTSET
908         && acceptor_index(&hb->a, grpa, d) != NOTSET;
909 }
910
911
912 static void add_hbond(t_hbdata *hb, int d, int a, int h, int grpd, int grpa,
913                       int frame, gmx_bool bMerge, int ihb, gmx_bool bContact, PSTYPE p)
914 {
915     int      k, id, ia, hh;
916     gmx_bool daSwap = FALSE;
917
918     if ((id = hb->d.dptr[d]) == NOTSET)
919     {
920         gmx_fatal(FARGS, "No donor atom %d", d+1);
921     }
922     else if (grpd != hb->d.grp[id])
923     {
924         gmx_fatal(FARGS, "Inconsistent donor groups, %d iso %d, atom %d",
925                   grpd, hb->d.grp[id], d+1);
926     }
927     if ((ia = hb->a.aptr[a]) == NOTSET)
928     {
929         gmx_fatal(FARGS, "No acceptor atom %d", a+1);
930     }
931     else if (grpa != hb->a.grp[ia])
932     {
933         gmx_fatal(FARGS, "Inconsistent acceptor groups, %d iso %d, atom %d",
934                   grpa, hb->a.grp[ia], a+1);
935     }
936
937     if (bMerge)
938     {
939
940         if (isInterchangable(hb, d, a, grpd, grpa) && d > a)
941         /* Then swap identity so that the id of d is lower then that of a.
942          *
943          * This should really be redundant by now, as is_hbond() now ought to return
944          * hbNo in the cases where this conditional is TRUE. */
945         {
946             daSwap = TRUE;
947             k      = d;
948             d      = a;
949             a      = k;
950
951             /* Now repeat donor/acc check. */
952             if ((id = hb->d.dptr[d]) == NOTSET)
953             {
954                 gmx_fatal(FARGS, "No donor atom %d", d+1);
955             }
956             else if (grpd != hb->d.grp[id])
957             {
958                 gmx_fatal(FARGS, "Inconsistent donor groups, %d iso %d, atom %d",
959                           grpd, hb->d.grp[id], d+1);
960             }
961             if ((ia = hb->a.aptr[a]) == NOTSET)
962             {
963                 gmx_fatal(FARGS, "No acceptor atom %d", a+1);
964             }
965             else if (grpa != hb->a.grp[ia])
966             {
967                 gmx_fatal(FARGS, "Inconsistent acceptor groups, %d iso %d, atom %d",
968                           grpa, hb->a.grp[ia], a+1);
969             }
970         }
971     }
972
973     if (hb->hbmap)
974     {
975         /* Loop over hydrogens to find which hydrogen is in this particular HB */
976         if ((ihb == hbHB) && !bMerge && !bContact)
977         {
978             for (k = 0; (k < hb->d.nhydro[id]); k++)
979             {
980                 if (hb->d.hydro[id][k] == h)
981                 {
982                     break;
983                 }
984             }
985             if (k == hb->d.nhydro[id])
986             {
987                 gmx_fatal(FARGS, "Donor %d does not have hydrogen %d (a = %d)",
988                           d+1, h+1, a+1);
989             }
990         }
991         else
992         {
993             k = 0;
994         }
995
996         if (hb->bHBmap)
997         {
998
999 #pragma omp critical
1000             {
1001                 if (hb->hbmap[id][ia] == NULL)
1002                 {
1003                     snew(hb->hbmap[id][ia], 1);
1004                     snew(hb->hbmap[id][ia]->h, hb->maxhydro);
1005                     snew(hb->hbmap[id][ia]->g, hb->maxhydro);
1006                 }
1007                 add_ff(hb, id, k, ia, frame, ihb, p);
1008             }
1009         }
1010
1011         /* Strange construction with frame >=0 is a relic from old code
1012          * for selected hbond analysis. It may be necessary again if that
1013          * is made to work again.
1014          */
1015         if (frame >= 0)
1016         {
1017             hh = hb->hbmap[id][ia]->history[k];
1018             if (ihb == hbHB)
1019             {
1020                 hb->nhb[frame]++;
1021                 if (!(ISHB(hh)))
1022                 {
1023                     hb->hbmap[id][ia]->history[k] = hh | 2;
1024                     hb->nrhb++;
1025                 }
1026             }
1027             else
1028             {
1029                 if (ihb == hbDist)
1030                 {
1031                     hb->ndist[frame]++;
1032                     if (!(ISDIST(hh)))
1033                     {
1034                         hb->hbmap[id][ia]->history[k] = hh | 1;
1035                         hb->nrdist++;
1036                     }
1037                 }
1038             }
1039         }
1040     }
1041     else
1042     {
1043         if (frame >= 0)
1044         {
1045             if (ihb == hbHB)
1046             {
1047                 hb->nhb[frame]++;
1048             }
1049             else
1050             {
1051                 if (ihb == hbDist)
1052                 {
1053                     hb->ndist[frame]++;
1054                 }
1055             }
1056         }
1057     }
1058     if (bMerge && daSwap)
1059     {
1060         h = hb->d.hydro[id][0];
1061     }
1062     /* Increment number if HBonds per H */
1063     if (ihb == hbHB && !bContact)
1064     {
1065         inc_nhbonds(&(hb->d), d, h);
1066     }
1067 }
1068
1069 static char *mkatomname(t_atoms *atoms, int i)
1070 {
1071     static char buf[32];
1072     int         rnr;
1073
1074     rnr = atoms->atom[i].resind;
1075     sprintf(buf, "%4s%d%-4s",
1076             *atoms->resinfo[rnr].name, atoms->resinfo[rnr].nr, *atoms->atomname[i]);
1077
1078     return buf;
1079 }
1080
1081 static void gen_datable(atom_id *index, int isize, unsigned char *datable, int natoms)
1082 {
1083     /* Generates table of all atoms and sets the ingroup bit for atoms in index[] */
1084     int i;
1085
1086     for (i = 0; i < isize; i++)
1087     {
1088         if (index[i] >= natoms)
1089         {
1090             gmx_fatal(FARGS, "Atom has index %d larger than number of atoms %d.", index[i], natoms);
1091         }
1092         datable[index[i]] |= INGROUP;
1093     }
1094 }
1095
1096 static void clear_datable_grp(unsigned char *datable, int size)
1097 {
1098     /* Clears group information from the table */
1099     int        i;
1100     const char mask = !(char)INGROUP;
1101     if (size > 0)
1102     {
1103         for (i = 0; i < size; i++)
1104         {
1105             datable[i] &= mask;
1106         }
1107     }
1108 }
1109
1110 static void add_acc(t_acceptors *a, int ia, int grp)
1111 {
1112     if (a->nra >= a->max_nra)
1113     {
1114         a->max_nra += 16;
1115         srenew(a->acc, a->max_nra);
1116         srenew(a->grp, a->max_nra);
1117     }
1118     a->grp[a->nra]   = grp;
1119     a->acc[a->nra++] = ia;
1120 }
1121
1122 static void search_acceptors(t_topology *top, int isize,
1123                              atom_id *index, t_acceptors *a, int grp,
1124                              gmx_bool bNitAcc,
1125                              gmx_bool bContact, gmx_bool bDoIt, unsigned char *datable)
1126 {
1127     int i, n;
1128
1129     if (bDoIt)
1130     {
1131         for (i = 0; (i < isize); i++)
1132         {
1133             n = index[i];
1134             if ((bContact ||
1135                  (((*top->atoms.atomname[n])[0] == 'O') ||
1136                   (bNitAcc && ((*top->atoms.atomname[n])[0] == 'N')))) &&
1137                 ISINGRP(datable[n]))
1138             {
1139                 datable[n] |= ACC; /* set the atom's acceptor flag in datable. */
1140                 add_acc(a, n, grp);
1141             }
1142         }
1143     }
1144     snew(a->aptr, top->atoms.nr);
1145     for (i = 0; (i < top->atoms.nr); i++)
1146     {
1147         a->aptr[i] = NOTSET;
1148     }
1149     for (i = 0; (i < a->nra); i++)
1150     {
1151         a->aptr[a->acc[i]] = i;
1152     }
1153 }
1154
1155 static void add_h2d(int id, int ih, t_donors *ddd)
1156 {
1157     int i;
1158
1159     for (i = 0; (i < ddd->nhydro[id]); i++)
1160     {
1161         if (ddd->hydro[id][i] == ih)
1162         {
1163             printf("Hm. This isn't the first time I found this donor (%d,%d)\n",
1164                    ddd->don[id], ih);
1165             break;
1166         }
1167     }
1168     if (i == ddd->nhydro[id])
1169     {
1170         if (ddd->nhydro[id] >= MAXHYDRO)
1171         {
1172             gmx_fatal(FARGS, "Donor %d has more than %d hydrogens!",
1173                       ddd->don[id], MAXHYDRO);
1174         }
1175         ddd->hydro[id][i] = ih;
1176         ddd->nhydro[id]++;
1177     }
1178 }
1179
1180 static void add_dh(t_donors *ddd, int id, int ih, int grp, unsigned char *datable)
1181 {
1182     int i;
1183
1184     if (!datable || ISDON(datable[id]))
1185     {
1186         if (ddd->dptr[id] == NOTSET)   /* New donor */
1187         {
1188             i             = ddd->nrd;
1189             ddd->dptr[id] = i;
1190         }
1191         else
1192         {
1193             i = ddd->dptr[id];
1194         }
1195
1196         if (i == ddd->nrd)
1197         {
1198             if (ddd->nrd >= ddd->max_nrd)
1199             {
1200                 ddd->max_nrd += 128;
1201                 srenew(ddd->don, ddd->max_nrd);
1202                 srenew(ddd->nhydro, ddd->max_nrd);
1203                 srenew(ddd->hydro, ddd->max_nrd);
1204                 srenew(ddd->nhbonds, ddd->max_nrd);
1205                 srenew(ddd->grp, ddd->max_nrd);
1206             }
1207             ddd->don[ddd->nrd]    = id;
1208             ddd->nhydro[ddd->nrd] = 0;
1209             ddd->grp[ddd->nrd]    = grp;
1210             ddd->nrd++;
1211         }
1212         else
1213         {
1214             ddd->don[i] = id;
1215         }
1216         add_h2d(i, ih, ddd);
1217     }
1218     else
1219     if (datable)
1220     {
1221         printf("Warning: Atom %d is not in the d/a-table!\n", id);
1222     }
1223 }
1224
1225 static void search_donors(t_topology *top, int isize, atom_id *index,
1226                           t_donors *ddd, int grp, gmx_bool bContact, gmx_bool bDoIt,
1227                           unsigned char *datable)
1228 {
1229     int            i, j, nra, n;
1230     t_functype     func_type;
1231     t_ilist       *interaction;
1232     atom_id        nr1, nr2, nr3;
1233     gmx_bool       stop;
1234
1235     if (!ddd->dptr)
1236     {
1237         snew(ddd->dptr, top->atoms.nr);
1238         for (i = 0; (i < top->atoms.nr); i++)
1239         {
1240             ddd->dptr[i] = NOTSET;
1241         }
1242     }
1243
1244     if (bContact)
1245     {
1246         if (bDoIt)
1247         {
1248             for (i = 0; (i < isize); i++)
1249             {
1250                 datable[index[i]] |= DON;
1251                 add_dh(ddd, index[i], -1, grp, datable);
1252             }
1253         }
1254     }
1255     else
1256     {
1257         for (func_type = 0; (func_type < F_NRE); func_type++)
1258         {
1259             interaction = &(top->idef.il[func_type]);
1260             if (func_type == F_POSRES || func_type == F_FBPOSRES)
1261             {
1262                 /* The ilist looks strange for posre. Bug in grompp?
1263                  * We don't need posre interactions for hbonds anyway.*/
1264                 continue;
1265             }
1266             for (i = 0; i < interaction->nr;
1267                  i += interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1)
1268             {
1269                 /* next function */
1270                 if (func_type != top->idef.functype[interaction->iatoms[i]])
1271                 {
1272                     fprintf(stderr, "Error in func_type %s",
1273                             interaction_function[func_type].longname);
1274                     continue;
1275                 }
1276
1277                 /* check out this functype */
1278                 if (func_type == F_SETTLE)
1279                 {
1280                     nr1 = interaction->iatoms[i+1];
1281                     nr2 = interaction->iatoms[i+2];
1282                     nr3 = interaction->iatoms[i+3];
1283
1284                     if (ISINGRP(datable[nr1]))
1285                     {
1286                         if (ISINGRP(datable[nr2]))
1287                         {
1288                             datable[nr1] |= DON;
1289                             add_dh(ddd, nr1, nr1+1, grp, datable);
1290                         }
1291                         if (ISINGRP(datable[nr3]))
1292                         {
1293                             datable[nr1] |= DON;
1294                             add_dh(ddd, nr1, nr1+2, grp, datable);
1295                         }
1296                     }
1297                 }
1298                 else if (IS_CHEMBOND(func_type))
1299                 {
1300                     for (j = 0; j < 2; j++)
1301                     {
1302                         nr1 = interaction->iatoms[i+1+j];
1303                         nr2 = interaction->iatoms[i+2-j];
1304                         if ((*top->atoms.atomname[nr1][0] == 'H') &&
1305                             ((*top->atoms.atomname[nr2][0] == 'O') ||
1306                              (*top->atoms.atomname[nr2][0] == 'N')) &&
1307                             ISINGRP(datable[nr1]) && ISINGRP(datable[nr2]))
1308                         {
1309                             datable[nr2] |= DON;
1310                             add_dh(ddd, nr2, nr1, grp, datable);
1311                         }
1312                     }
1313                 }
1314             }
1315         }
1316 #ifdef SAFEVSITES
1317         for (func_type = 0; func_type < F_NRE; func_type++)
1318         {
1319             interaction = &top->idef.il[func_type];
1320             for (i = 0; i < interaction->nr;
1321                  i += interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1)
1322             {
1323                 /* next function */
1324                 if (func_type != top->idef.functype[interaction->iatoms[i]])
1325                 {
1326                     gmx_incons("function type in search_donors");
1327                 }
1328
1329                 if (interaction_function[func_type].flags & IF_VSITE)
1330                 {
1331                     nr1 = interaction->iatoms[i+1];
1332                     if (*top->atoms.atomname[nr1][0]  == 'H')
1333                     {
1334                         nr2  = nr1-1;
1335                         stop = FALSE;
1336                         while (!stop && ( *top->atoms.atomname[nr2][0] == 'H'))
1337                         {
1338                             if (nr2)
1339                             {
1340                                 nr2--;
1341                             }
1342                             else
1343                             {
1344                                 stop = TRUE;
1345                             }
1346                         }
1347                         if (!stop && ( ( *top->atoms.atomname[nr2][0] == 'O') ||
1348                                        ( *top->atoms.atomname[nr2][0] == 'N') ) &&
1349                             ISINGRP(datable[nr1]) && ISINGRP(datable[nr2]))
1350                         {
1351                             datable[nr2] |= DON;
1352                             add_dh(ddd, nr2, nr1, grp, datable);
1353                         }
1354                     }
1355                 }
1356             }
1357         }
1358 #endif
1359     }
1360 }
1361
1362 static t_gridcell ***init_grid(gmx_bool bBox, rvec box[], real rcut, ivec ngrid)
1363 {
1364     t_gridcell ***grid;
1365     int           i, y, z;
1366
1367     if (bBox)
1368     {
1369         for (i = 0; i < DIM; i++)
1370         {
1371             ngrid[i] = (box[i][i]/(1.2*rcut));
1372         }
1373     }
1374
1375     if (!bBox || (ngrid[XX] < 3) || (ngrid[YY] < 3) || (ngrid[ZZ] < 3) )
1376     {
1377         for (i = 0; i < DIM; i++)
1378         {
1379             ngrid[i] = 1;
1380         }
1381     }
1382     else
1383     {
1384         printf("\nWill do grid-seach on %dx%dx%d grid, rcut=%g\n",
1385                ngrid[XX], ngrid[YY], ngrid[ZZ], rcut);
1386     }
1387     snew(grid, ngrid[ZZ]);
1388     for (z = 0; z < ngrid[ZZ]; z++)
1389     {
1390         snew((grid)[z], ngrid[YY]);
1391         for (y = 0; y < ngrid[YY]; y++)
1392         {
1393             snew((grid)[z][y], ngrid[XX]);
1394         }
1395     }
1396     return grid;
1397 }
1398
1399 static void reset_nhbonds(t_donors *ddd)
1400 {
1401     int i, j;
1402
1403     for (i = 0; (i < ddd->nrd); i++)
1404     {
1405         for (j = 0; (j < MAXHH); j++)
1406         {
1407             ddd->nhbonds[i][j] = 0;
1408         }
1409     }
1410 }
1411
1412 void pbc_correct_gem(rvec dx, matrix box, rvec hbox);
1413
1414 static void build_grid(t_hbdata *hb, rvec x[], rvec xshell,
1415                        gmx_bool bBox, matrix box, rvec hbox,
1416                        real rcut, real rshell,
1417                        ivec ngrid, t_gridcell ***grid)
1418 {
1419     int         i, m, gr, xi, yi, zi, nr;
1420     atom_id    *ad;
1421     ivec        grididx;
1422     rvec        invdelta, dshell, xtemp = {0, 0, 0};
1423     t_ncell    *newgrid;
1424     gmx_bool    bDoRshell, bInShell, bAcc;
1425     real        rshell2 = 0;
1426     int         gx, gy, gz;
1427     int         dum = -1;
1428
1429     bDoRshell = (rshell > 0);
1430     rshell2   = sqr(rshell);
1431     bInShell  = TRUE;
1432
1433 #define DBB(x) if (debug && bDebug) fprintf(debug, "build_grid, line %d, %s = %d\n", __LINE__,#x, x)
1434     DBB(dum);
1435     for (m = 0; m < DIM; m++)
1436     {
1437         hbox[m] = box[m][m]*0.5;
1438         if (bBox)
1439         {
1440             invdelta[m] = ngrid[m]/box[m][m];
1441             if (1/invdelta[m] < rcut)
1442             {
1443                 gmx_fatal(FARGS, "Your computational box has shrunk too much.\n"
1444                           "%s can not handle this situation, sorry.\n",
1445                           ShortProgram());
1446             }
1447         }
1448         else
1449         {
1450             invdelta[m] = 0;
1451         }
1452     }
1453     grididx[XX] = 0;
1454     grididx[YY] = 0;
1455     grididx[ZZ] = 0;
1456     DBB(dum);
1457     /* resetting atom counts */
1458     for (gr = 0; (gr < grNR); gr++)
1459     {
1460         for (zi = 0; zi < ngrid[ZZ]; zi++)
1461         {
1462             for (yi = 0; yi < ngrid[YY]; yi++)
1463             {
1464                 for (xi = 0; xi < ngrid[XX]; xi++)
1465                 {
1466                     grid[zi][yi][xi].d[gr].nr = 0;
1467                     grid[zi][yi][xi].a[gr].nr = 0;
1468                 }
1469             }
1470         }
1471         DBB(dum);
1472
1473         /* put atoms in grid cells */
1474         for (bAcc = FALSE; (bAcc <= TRUE); bAcc++)
1475         {
1476             if (bAcc)
1477             {
1478                 nr = hb->a.nra;
1479                 ad = hb->a.acc;
1480             }
1481             else
1482             {
1483                 nr = hb->d.nrd;
1484                 ad = hb->d.don;
1485             }
1486             DBB(bAcc);
1487             for (i = 0; (i < nr); i++)
1488             {
1489                 /* check if we are inside the shell */
1490                 /* if bDoRshell=FALSE then bInShell=TRUE always */
1491                 DBB(i);
1492                 if (bDoRshell)
1493                 {
1494                     bInShell = TRUE;
1495                     rvec_sub(x[ad[i]], xshell, dshell);
1496                     if (bBox)
1497                     {
1498                         if (FALSE && !hb->bGem)
1499                         {
1500                             for (m = DIM-1; m >= 0 && bInShell; m--)
1501                             {
1502                                 if (dshell[m] < -hbox[m])
1503                                 {
1504                                     rvec_inc(dshell, box[m]);
1505                                 }
1506                                 else if (dshell[m] >= hbox[m])
1507                                 {
1508                                     dshell[m] -= 2*hbox[m];
1509                                 }
1510                                 /* if we're outside the cube, we're outside the sphere also! */
1511                                 if ( (dshell[m] > rshell) || (-dshell[m] > rshell) )
1512                                 {
1513                                     bInShell = FALSE;
1514                                 }
1515                             }
1516                         }
1517                         else
1518                         {
1519                             gmx_bool bDone = FALSE;
1520                             while (!bDone)
1521                             {
1522                                 bDone = TRUE;
1523                                 for (m = DIM-1; m >= 0 && bInShell; m--)
1524                                 {
1525                                     if (dshell[m] < -hbox[m])
1526                                     {
1527                                         bDone = FALSE;
1528                                         rvec_inc(dshell, box[m]);
1529                                     }
1530                                     if (dshell[m] >= hbox[m])
1531                                     {
1532                                         bDone      = FALSE;
1533                                         dshell[m] -= 2*hbox[m];
1534                                     }
1535                                 }
1536                             }
1537                             for (m = DIM-1; m >= 0 && bInShell; m--)
1538                             {
1539                                 /* if we're outside the cube, we're outside the sphere also! */
1540                                 if ( (dshell[m] > rshell) || (-dshell[m] > rshell) )
1541                                 {
1542                                     bInShell = FALSE;
1543                                 }
1544                             }
1545                         }
1546                     }
1547                     /* if we're inside the cube, check if we're inside the sphere */
1548                     if (bInShell)
1549                     {
1550                         bInShell = norm2(dshell) < rshell2;
1551                     }
1552                 }
1553                 DBB(i);
1554                 if (bInShell)
1555                 {
1556                     if (bBox)
1557                     {
1558                         if (hb->bGem)
1559                         {
1560                             copy_rvec(x[ad[i]], xtemp);
1561                         }
1562                         pbc_correct_gem(x[ad[i]], box, hbox);
1563                     }
1564                     for (m = DIM-1; m >= 0; m--)
1565                     {
1566                         if (TRUE || !hb->bGem)
1567                         {
1568                             /* put atom in the box */
1569                             while (x[ad[i]][m] < 0)
1570                             {
1571                                 rvec_inc(x[ad[i]], box[m]);
1572                             }
1573                             while (x[ad[i]][m] >= box[m][m])
1574                             {
1575                                 rvec_dec(x[ad[i]], box[m]);
1576                             }
1577                         }
1578                         /* determine grid index of atom */
1579                         grididx[m] = x[ad[i]][m]*invdelta[m];
1580                         grididx[m] = (grididx[m]+ngrid[m]) % ngrid[m];
1581                     }
1582                     if (hb->bGem)
1583                     {
1584                         copy_rvec(xtemp, x[ad[i]]); /* copy back */
1585                     }
1586                     gx = grididx[XX];
1587                     gy = grididx[YY];
1588                     gz = grididx[ZZ];
1589                     range_check(gx, 0, ngrid[XX]);
1590                     range_check(gy, 0, ngrid[YY]);
1591                     range_check(gz, 0, ngrid[ZZ]);
1592                     DBB(gx);
1593                     DBB(gy);
1594                     DBB(gz);
1595                     /* add atom to grid cell */
1596                     if (bAcc)
1597                     {
1598                         newgrid = &(grid[gz][gy][gx].a[gr]);
1599                     }
1600                     else
1601                     {
1602                         newgrid = &(grid[gz][gy][gx].d[gr]);
1603                     }
1604                     if (newgrid->nr >= newgrid->maxnr)
1605                     {
1606                         newgrid->maxnr += 10;
1607                         DBB(newgrid->maxnr);
1608                         srenew(newgrid->atoms, newgrid->maxnr);
1609                     }
1610                     DBB(newgrid->nr);
1611                     newgrid->atoms[newgrid->nr] = ad[i];
1612                     newgrid->nr++;
1613                 }
1614             }
1615         }
1616     }
1617 }
1618
1619 static void count_da_grid(ivec ngrid, t_gridcell ***grid, t_icell danr)
1620 {
1621     int gr, xi, yi, zi;
1622
1623     for (gr = 0; (gr < grNR); gr++)
1624     {
1625         danr[gr] = 0;
1626         for (zi = 0; zi < ngrid[ZZ]; zi++)
1627         {
1628             for (yi = 0; yi < ngrid[YY]; yi++)
1629             {
1630                 for (xi = 0; xi < ngrid[XX]; xi++)
1631                 {
1632                     danr[gr] += grid[zi][yi][xi].d[gr].nr;
1633                 }
1634             }
1635         }
1636     }
1637 }
1638
1639 /* The grid loop.
1640  * Without a box, the grid is 1x1x1, so all loops are 1 long.
1641  * With a rectangular box (bTric==FALSE) all loops are 3 long.
1642  * With a triclinic box all loops are 3 long, except when a cell is
1643  * located next to one of the box edges which is not parallel to the
1644  * x/y-plane, in that case all cells in a line or layer are searched.
1645  * This could be implemented slightly more efficient, but the code
1646  * would get much more complicated.
1647  */
1648 static gmx_inline gmx_bool grid_loop_begin(int n, int x, gmx_bool bTric, gmx_bool bEdge)
1649 {
1650     return ((n == 1) ? x : bTric && bEdge ? 0     : (x-1));
1651 }
1652 static gmx_inline gmx_bool grid_loop_end(int n, int x, gmx_bool bTric, gmx_bool bEdge)
1653 {
1654     return ((n == 1) ? x : bTric && bEdge ? (n-1) : (x+1));
1655 }
1656 static gmx_inline int grid_mod(int j, int n)
1657 {
1658     return (j+n) % (n);
1659 }
1660
1661 static void dump_grid(FILE *fp, ivec ngrid, t_gridcell ***grid)
1662 {
1663     int gr, x, y, z, sum[grNR];
1664
1665     fprintf(fp, "grid %dx%dx%d\n", ngrid[XX], ngrid[YY], ngrid[ZZ]);
1666     for (gr = 0; gr < grNR; gr++)
1667     {
1668         sum[gr] = 0;
1669         fprintf(fp, "GROUP %d (%s)\n", gr, grpnames[gr]);
1670         for (z = 0; z < ngrid[ZZ]; z += 2)
1671         {
1672             fprintf(fp, "Z=%d,%d\n", z, z+1);
1673             for (y = 0; y < ngrid[YY]; y++)
1674             {
1675                 for (x = 0; x < ngrid[XX]; x++)
1676                 {
1677                     fprintf(fp, "%3d", grid[x][y][z].d[gr].nr);
1678                     sum[gr] += grid[z][y][x].d[gr].nr;
1679                     fprintf(fp, "%3d", grid[x][y][z].a[gr].nr);
1680                     sum[gr] += grid[z][y][x].a[gr].nr;
1681
1682                 }
1683                 fprintf(fp, " | ");
1684                 if ( (z+1) < ngrid[ZZ])
1685                 {
1686                     for (x = 0; x < ngrid[XX]; x++)
1687                     {
1688                         fprintf(fp, "%3d", grid[z+1][y][x].d[gr].nr);
1689                         sum[gr] += grid[z+1][y][x].d[gr].nr;
1690                         fprintf(fp, "%3d", grid[z+1][y][x].a[gr].nr);
1691                         sum[gr] += grid[z+1][y][x].a[gr].nr;
1692                     }
1693                 }
1694                 fprintf(fp, "\n");
1695             }
1696         }
1697     }
1698     fprintf(fp, "TOTALS:");
1699     for (gr = 0; gr < grNR; gr++)
1700     {
1701         fprintf(fp, " %d=%d", gr, sum[gr]);
1702     }
1703     fprintf(fp, "\n");
1704 }
1705
1706 /* New GMX record! 5 * in a row. Congratulations!
1707  * Sorry, only four left.
1708  */
1709 static void free_grid(ivec ngrid, t_gridcell ****grid)
1710 {
1711     int           y, z;
1712     t_gridcell ***g = *grid;
1713
1714     for (z = 0; z < ngrid[ZZ]; z++)
1715     {
1716         for (y = 0; y < ngrid[YY]; y++)
1717         {
1718             sfree(g[z][y]);
1719         }
1720         sfree(g[z]);
1721     }
1722     sfree(g);
1723     g = NULL;
1724 }
1725
1726 void pbc_correct_gem(rvec dx, matrix box, rvec hbox)
1727 {
1728     int      m;
1729     gmx_bool bDone = FALSE;
1730     while (!bDone)
1731     {
1732         bDone = TRUE;
1733         for (m = DIM-1; m >= 0; m--)
1734         {
1735             if (dx[m] < -hbox[m])
1736             {
1737                 bDone = FALSE;
1738                 rvec_inc(dx, box[m]);
1739             }
1740             if (dx[m] >= hbox[m])
1741             {
1742                 bDone = FALSE;
1743                 rvec_dec(dx, box[m]);
1744             }
1745         }
1746     }
1747 }
1748
1749 /* Added argument r2cut, changed contact and implemented
1750  * use of second cut-off.
1751  * - Erik Marklund, June 29, 2006
1752  */
1753 static int is_hbond(t_hbdata *hb, int grpd, int grpa, int d, int a,
1754                     real rcut, real r2cut, real ccut,
1755                     rvec x[], gmx_bool bBox, matrix box, rvec hbox,
1756                     real *d_ha, real *ang, gmx_bool bDA, int *hhh,
1757                     gmx_bool bContact, gmx_bool bMerge, PSTYPE *p)
1758 {
1759     int      h, hh, id, ja, ihb;
1760     rvec     r_da, r_ha, r_dh, r = {0, 0, 0};
1761     ivec     ri;
1762     real     rc2, r2c2, rda2, rha2, ca;
1763     gmx_bool HAinrange = FALSE; /* If !bDA. Needed for returning hbDist in a correct way. */
1764     gmx_bool daSwap    = FALSE;
1765
1766     if (d == a)
1767     {
1768         return hbNo;
1769     }
1770
1771     if (((id = donor_index(&hb->d, grpd, d)) == NOTSET) ||
1772         ((ja = acceptor_index(&hb->a, grpa, a)) == NOTSET))
1773     {
1774         return hbNo;
1775     }
1776
1777     rc2  = rcut*rcut;
1778     r2c2 = r2cut*r2cut;
1779
1780     rvec_sub(x[d], x[a], r_da);
1781     /* Insert projection code here */
1782
1783     if (bMerge && d > a && isInterchangable(hb, d, a, grpd, grpa))
1784     {
1785         /* Then this hbond/contact will be found again, or it has already been found. */
1786         /*return hbNo;*/
1787     }
1788     if (bBox)
1789     {
1790         if (d > a && bMerge && isInterchangable(hb, d, a, grpd, grpa)) /* acceptor is also a donor and vice versa? */
1791         {                                                              /* return hbNo; */
1792             daSwap = TRUE;                                             /* If so, then their history should be filed with donor and acceptor swapped. */
1793         }
1794         if (hb->bGem)
1795         {
1796             copy_rvec(r_da, r); /* Save this for later */
1797             pbc_correct_gem(r_da, box, hbox);
1798         }
1799         else
1800         {
1801             pbc_correct_gem(r_da, box, hbox);
1802         }
1803     }
1804     rda2 = iprod(r_da, r_da);
1805
1806     if (bContact)
1807     {
1808         if (daSwap && grpa == grpd)
1809         {
1810             return hbNo;
1811         }
1812         if (rda2 <= rc2)
1813         {
1814             if (hb->bGem)
1815             {
1816                 calcBoxDistance(hb->per->P, r, ri);
1817                 *p = periodicIndex(ri, hb->per, daSwap);    /* find (or add) periodicity index. */
1818             }
1819             return hbHB;
1820         }
1821         else if (rda2 < r2c2)
1822         {
1823             return hbDist;
1824         }
1825         else
1826         {
1827             return hbNo;
1828         }
1829     }
1830     *hhh = NOTSET;
1831
1832     if (bDA && (rda2 > rc2))
1833     {
1834         return hbNo;
1835     }
1836
1837     for (h = 0; (h < hb->d.nhydro[id]); h++)
1838     {
1839         hh   = hb->d.hydro[id][h];
1840         rha2 = rc2+1;
1841         if (!bDA)
1842         {
1843             rvec_sub(x[hh], x[a], r_ha);
1844             if (bBox)
1845             {
1846                 pbc_correct_gem(r_ha, box, hbox);
1847             }
1848             rha2 = iprod(r_ha, r_ha);
1849         }
1850
1851         if (hb->bGem)
1852         {
1853             calcBoxDistance(hb->per->P, r, ri);
1854             *p = periodicIndex(ri, hb->per, daSwap);    /* find periodicity index. */
1855         }
1856
1857         if (bDA || (!bDA && (rha2 <= rc2)))
1858         {
1859             rvec_sub(x[d], x[hh], r_dh);
1860             if (bBox)
1861             {
1862                 pbc_correct_gem(r_dh, box, hbox);
1863             }
1864
1865             if (!bDA)
1866             {
1867                 HAinrange = TRUE;
1868             }
1869             ca = cos_angle(r_dh, r_da);
1870             /* if angle is smaller, cos is larger */
1871             if (ca >= ccut)
1872             {
1873                 *hhh  = hh;
1874                 *d_ha = sqrt(bDA ? rda2 : rha2);
1875                 *ang  = acos(ca);
1876                 return hbHB;
1877             }
1878         }
1879     }
1880     if (bDA || (!bDA && HAinrange))
1881     {
1882         return hbDist;
1883     }
1884     else
1885     {
1886         return hbNo;
1887     }
1888 }
1889
1890 /* Fixed previously undiscovered bug in the merge
1891    code, where the last frame of each hbond disappears.
1892    - Erik Marklund, June 1, 2006 */
1893 /* Added the following arguments:
1894  *   ptmp[] - temporary periodicity hisory
1895  *   a1     - identity of first acceptor/donor
1896  *   a2     - identity of second acceptor/donor
1897  * - Erik Marklund, FEB 20 2010 */
1898
1899 /* Merging is now done on the fly, so do_merge is most likely obsolete now.
1900  * Will do some more testing before removing the function entirely.
1901  * - Erik Marklund, MAY 10 2010 */
1902 static void do_merge(t_hbdata *hb, int ntmp,
1903                      unsigned int htmp[], unsigned int gtmp[], PSTYPE ptmp[],
1904                      t_hbond *hb0, t_hbond *hb1, int a1, int a2)
1905 {
1906     /* Here we need to make sure we're treating periodicity in
1907      * the right way for the geminate recombination kinetics. */
1908
1909     int       m, mm, n00, n01, nn0, nnframes;
1910     PSTYPE    pm;
1911     t_pShift *pShift;
1912
1913     /* Decide where to start from when merging */
1914     n00      = hb0->n0;
1915     n01      = hb1->n0;
1916     nn0      = min(n00, n01);
1917     nnframes = max(n00 + hb0->nframes, n01 + hb1->nframes) - nn0;
1918     /* Initiate tmp arrays */
1919     for (m = 0; (m < ntmp); m++)
1920     {
1921         htmp[m] = 0;
1922         gtmp[m] = 0;
1923         ptmp[m] = 0;
1924     }
1925     /* Fill tmp arrays with values due to first HB */
1926     /* Once again '<' had to be replaced with '<='
1927        to catch the last frame in which the hbond
1928        appears.
1929        - Erik Marklund, June 1, 2006 */
1930     for (m = 0; (m <= hb0->nframes); m++)
1931     {
1932         mm       = m+n00-nn0;
1933         htmp[mm] = is_hb(hb0->h[0], m);
1934         if (hb->bGem)
1935         {
1936             pm = getPshift(hb->per->pHist[a1][a2], m+hb0->n0);
1937             if (pm > hb->per->nper)
1938             {
1939                 gmx_fatal(FARGS, "Illegal shift!");
1940             }
1941             else
1942             {
1943                 ptmp[mm] = pm; /*hb->per->pHist[a1][a2][m];*/
1944             }
1945         }
1946     }
1947     /* If we're doing geminate recompbination we usually don't need the distances.
1948      * Let's save some memory and time. */
1949     if (TRUE || !hb->bGem || hb->per->gemtype == gemAD)
1950     {
1951         for (m = 0; (m <= hb0->nframes); m++)
1952         {
1953             mm       = m+n00-nn0;
1954             gtmp[mm] = is_hb(hb0->g[0], m);
1955         }
1956     }
1957     /* Next HB */
1958     for (m = 0; (m <= hb1->nframes); m++)
1959     {
1960         mm       = m+n01-nn0;
1961         htmp[mm] = htmp[mm] || is_hb(hb1->h[0], m);
1962         gtmp[mm] = gtmp[mm] || is_hb(hb1->g[0], m);
1963         if (hb->bGem /* && ptmp[mm] != 0 */)
1964         {
1965
1966             /* If this hbond has been seen before with donor and acceptor swapped,
1967              * then we need to find the mirrored (*-1) periodicity vector to truely
1968              * merge the hbond history. */
1969             pm = findMirror(getPshift(hb->per->pHist[a2][a1], m+hb1->n0), hb->per->p2i, hb->per->nper);
1970             /* Store index of mirror */
1971             if (pm > hb->per->nper)
1972             {
1973                 gmx_fatal(FARGS, "Illegal shift!");
1974             }
1975             ptmp[mm] = pm;
1976         }
1977     }
1978     /* Reallocate target array */
1979     if (nnframes > hb0->maxframes)
1980     {
1981         srenew(hb0->h[0], 4+nnframes/hb->wordlen);
1982         srenew(hb0->g[0], 4+nnframes/hb->wordlen);
1983     }
1984     if (NULL != hb->per->pHist)
1985     {
1986         clearPshift(&(hb->per->pHist[a1][a2]));
1987     }
1988
1989     /* Copy temp array to target array */
1990     for (m = 0; (m <= nnframes); m++)
1991     {
1992         _set_hb(hb0->h[0], m, htmp[m]);
1993         _set_hb(hb0->g[0], m, gtmp[m]);
1994         if (hb->bGem)
1995         {
1996             addPshift(&(hb->per->pHist[a1][a2]), ptmp[m], m+nn0);
1997         }
1998     }
1999
2000     /* Set scalar variables */
2001     hb0->n0        = nn0;
2002     hb0->maxframes = nnframes;
2003 }
2004
2005 /* Added argument bContact for nicer output.
2006  * Erik Marklund, June 29, 2006
2007  */
2008 static void merge_hb(t_hbdata *hb, gmx_bool bTwo, gmx_bool bContact)
2009 {
2010     int           i, inrnew, indnew, j, ii, jj, m, id, ia, grp, ogrp, ntmp;
2011     unsigned int *htmp, *gtmp;
2012     PSTYPE       *ptmp;
2013     t_hbond      *hb0, *hb1;
2014
2015     inrnew = hb->nrhb;
2016     indnew = hb->nrdist;
2017
2018     /* Check whether donors are also acceptors */
2019     printf("Merging hbonds with Acceptor and Donor swapped\n");
2020
2021     ntmp = 2*hb->max_frames;
2022     snew(gtmp, ntmp);
2023     snew(htmp, ntmp);
2024     snew(ptmp, ntmp);
2025     for (i = 0; (i < hb->d.nrd); i++)
2026     {
2027         fprintf(stderr, "\r%d/%d", i+1, hb->d.nrd);
2028         id = hb->d.don[i];
2029         ii = hb->a.aptr[id];
2030         for (j = 0; (j < hb->a.nra); j++)
2031         {
2032             ia = hb->a.acc[j];
2033             jj = hb->d.dptr[ia];
2034             if ((id != ia) && (ii != NOTSET) && (jj != NOTSET) &&
2035                 (!bTwo || (bTwo && (hb->d.grp[i] != hb->a.grp[j]))))
2036             {
2037                 hb0 = hb->hbmap[i][j];
2038                 hb1 = hb->hbmap[jj][ii];
2039                 if (hb0 && hb1 && ISHB(hb0->history[0]) && ISHB(hb1->history[0]))
2040                 {
2041                     do_merge(hb, ntmp, htmp, gtmp, ptmp, hb0, hb1, i, j);
2042                     if (ISHB(hb1->history[0]))
2043                     {
2044                         inrnew--;
2045                     }
2046                     else if (ISDIST(hb1->history[0]))
2047                     {
2048                         indnew--;
2049                     }
2050                     else
2051                     if (bContact)
2052                     {
2053                         gmx_incons("No contact history");
2054                     }
2055                     else
2056                     {
2057                         gmx_incons("Neither hydrogen bond nor distance");
2058                     }
2059                     sfree(hb1->h[0]);
2060                     sfree(hb1->g[0]);
2061                     if (hb->bGem)
2062                     {
2063                         clearPshift(&(hb->per->pHist[jj][ii]));
2064                     }
2065                     hb1->h[0]       = NULL;
2066                     hb1->g[0]       = NULL;
2067                     hb1->history[0] = hbNo;
2068                 }
2069             }
2070         }
2071     }
2072     fprintf(stderr, "\n");
2073     printf("- Reduced number of hbonds from %d to %d\n", hb->nrhb, inrnew);
2074     printf("- Reduced number of distances from %d to %d\n", hb->nrdist, indnew);
2075     hb->nrhb   = inrnew;
2076     hb->nrdist = indnew;
2077     sfree(gtmp);
2078     sfree(htmp);
2079     sfree(ptmp);
2080 }
2081
2082 static void do_nhb_dist(FILE *fp, t_hbdata *hb, real t)
2083 {
2084     int  i, j, k, n_bound[MAXHH], nbtot;
2085     h_id nhb;
2086
2087
2088     /* Set array to 0 */
2089     for (k = 0; (k < MAXHH); k++)
2090     {
2091         n_bound[k] = 0;
2092     }
2093     /* Loop over possible donors */
2094     for (i = 0; (i < hb->d.nrd); i++)
2095     {
2096         for (j = 0; (j < hb->d.nhydro[i]); j++)
2097         {
2098             n_bound[hb->d.nhbonds[i][j]]++;
2099         }
2100     }
2101     fprintf(fp, "%12.5e", t);
2102     nbtot = 0;
2103     for (k = 0; (k < MAXHH); k++)
2104     {
2105         fprintf(fp, "  %8d", n_bound[k]);
2106         nbtot += n_bound[k]*k;
2107     }
2108     fprintf(fp, "  %8d\n", nbtot);
2109 }
2110
2111 /* Added argument bContact in do_hblife(...). Also
2112  * added support for -contact in function body.
2113  * - Erik Marklund, May 31, 2006 */
2114 /* Changed the contact code slightly.
2115  * - Erik Marklund, June 29, 2006
2116  */
2117 static void do_hblife(const char *fn, t_hbdata *hb, gmx_bool bMerge, gmx_bool bContact,
2118                       const output_env_t oenv)
2119 {
2120     FILE          *fp;
2121     const char    *leg[] = { "p(t)", "t p(t)" };
2122     int           *histo;
2123     int            i, j, j0, k, m, nh, ihb, ohb, nhydro, ndump = 0;
2124     int            nframes = hb->nframes;
2125     unsigned int **h;
2126     real           t, x1, dt;
2127     double         sum, integral;
2128     t_hbond       *hbh;
2129
2130     snew(h, hb->maxhydro);
2131     snew(histo, nframes+1);
2132     /* Total number of hbonds analyzed here */
2133     for (i = 0; (i < hb->d.nrd); i++)
2134     {
2135         for (k = 0; (k < hb->a.nra); k++)
2136         {
2137             hbh = hb->hbmap[i][k];
2138             if (hbh)
2139             {
2140                 if (bMerge)
2141                 {
2142                     if (hbh->h[0])
2143                     {
2144                         h[0]   = hbh->h[0];
2145                         nhydro = 1;
2146                     }
2147                     else
2148                     {
2149                         nhydro = 0;
2150                     }
2151                 }
2152                 else
2153                 {
2154                     nhydro = 0;
2155                     for (m = 0; (m < hb->maxhydro); m++)
2156                     {
2157                         if (hbh->h[m])
2158                         {
2159                             h[nhydro++] = bContact ? hbh->g[m] : hbh->h[m];
2160                         }
2161                     }
2162                 }
2163                 for (nh = 0; (nh < nhydro); nh++)
2164                 {
2165                     ohb = 0;
2166                     j0  = 0;
2167
2168                     /* Changed '<' into '<=' below, just like I
2169                        did in the hbm-output-loop in the main code.
2170                        - Erik Marklund, May 31, 2006
2171                      */
2172                     for (j = 0; (j <= hbh->nframes); j++)
2173                     {
2174                         ihb      = is_hb(h[nh], j);
2175                         if (debug && (ndump < 10))
2176                         {
2177                             fprintf(debug, "%5d  %5d\n", j, ihb);
2178                         }
2179                         if (ihb != ohb)
2180                         {
2181                             if (ihb)
2182                             {
2183                                 j0 = j;
2184                             }
2185                             else
2186                             {
2187                                 histo[j-j0]++;
2188                             }
2189                             ohb = ihb;
2190                         }
2191                     }
2192                     ndump++;
2193                 }
2194             }
2195         }
2196     }
2197     fprintf(stderr, "\n");
2198     if (bContact)
2199     {
2200         fp = xvgropen(fn, "Uninterrupted contact lifetime", output_env_get_xvgr_tlabel(oenv), "()", oenv);
2201     }
2202     else
2203     {
2204         fp = xvgropen(fn, "Uninterrupted hydrogen bond lifetime", output_env_get_xvgr_tlabel(oenv), "()",
2205                       oenv);
2206     }
2207
2208     xvgr_legend(fp, asize(leg), leg, oenv);
2209     j0 = nframes-1;
2210     while ((j0 > 0) && (histo[j0] == 0))
2211     {
2212         j0--;
2213     }
2214     sum = 0;
2215     for (i = 0; (i <= j0); i++)
2216     {
2217         sum += histo[i];
2218     }
2219     dt       = hb->time[1]-hb->time[0];
2220     sum      = dt*sum;
2221     integral = 0;
2222     for (i = 1; (i <= j0); i++)
2223     {
2224         t  = hb->time[i] - hb->time[0] - 0.5*dt;
2225         x1 = t*histo[i]/sum;
2226         fprintf(fp, "%8.3f  %10.3e  %10.3e\n", t, histo[i]/sum, x1);
2227         integral += x1;
2228     }
2229     integral *= dt;
2230     gmx_ffclose(fp);
2231     printf("%s lifetime = %.2f ps\n", bContact ? "Contact" : "HB", integral);
2232     printf("Note that the lifetime obtained in this manner is close to useless\n");
2233     printf("Use the -ac option instead and check the Forward lifetime\n");
2234     please_cite(stdout, "Spoel2006b");
2235     sfree(h);
2236     sfree(histo);
2237 }
2238
2239 /* Changed argument bMerge into oneHB to handle contacts properly.
2240  * - Erik Marklund, June 29, 2006
2241  */
2242 static void dump_ac(t_hbdata *hb, gmx_bool oneHB, int nDump)
2243 {
2244     FILE     *fp;
2245     int       i, j, k, m, nd, ihb, idist;
2246     int       nframes = hb->nframes;
2247     gmx_bool  bPrint;
2248     t_hbond  *hbh;
2249
2250     if (nDump <= 0)
2251     {
2252         return;
2253     }
2254     fp = gmx_ffopen("debug-ac.xvg", "w");
2255     for (j = 0; (j < nframes); j++)
2256     {
2257         fprintf(fp, "%10.3f", hb->time[j]);
2258         for (i = nd = 0; (i < hb->d.nrd) && (nd < nDump); i++)
2259         {
2260             for (k = 0; (k < hb->a.nra) && (nd < nDump); k++)
2261             {
2262                 bPrint = FALSE;
2263                 ihb    = idist = 0;
2264                 hbh    = hb->hbmap[i][k];
2265                 if (oneHB)
2266                 {
2267                     if (hbh->h[0])
2268                     {
2269                         ihb    = is_hb(hbh->h[0], j);
2270                         idist  = is_hb(hbh->g[0], j);
2271                         bPrint = TRUE;
2272                     }
2273                 }
2274                 else
2275                 {
2276                     for (m = 0; (m < hb->maxhydro) && !ihb; m++)
2277                     {
2278                         ihb   = ihb   || ((hbh->h[m]) && is_hb(hbh->h[m], j));
2279                         idist = idist || ((hbh->g[m]) && is_hb(hbh->g[m], j));
2280                     }
2281                     /* This is not correct! */
2282                     /* What isn't correct? -Erik M */
2283                     bPrint = TRUE;
2284                 }
2285                 if (bPrint)
2286                 {
2287                     fprintf(fp, "  %1d-%1d", ihb, idist);
2288                     nd++;
2289                 }
2290             }
2291         }
2292         fprintf(fp, "\n");
2293     }
2294     gmx_ffclose(fp);
2295 }
2296
2297 static real calc_dg(real tau, real temp)
2298 {
2299     real kbt;
2300
2301     kbt = BOLTZ*temp;
2302     if (tau <= 0)
2303     {
2304         return -666;
2305     }
2306     else
2307     {
2308         return kbt*log(kbt*tau/PLANCK);
2309     }
2310 }
2311
2312 typedef struct {
2313     int   n0, n1, nparams, ndelta;
2314     real  kkk[2];
2315     real *t, *ct, *nt, *kt, *sigma_ct, *sigma_nt, *sigma_kt;
2316 } t_luzar;
2317
2318 static real compute_weighted_rates(int n, real t[], real ct[], real nt[],
2319                                    real kt[], real sigma_ct[], real sigma_nt[],
2320                                    real sigma_kt[], real *k, real *kp,
2321                                    real *sigma_k, real *sigma_kp,
2322                                    real fit_start)
2323 {
2324 #define NK 10
2325     int      i, j;
2326     t_luzar  tl;
2327     real     kkk = 0, kkp = 0, kk2 = 0, kp2 = 0, chi2;
2328
2329     *sigma_k  = 0;
2330     *sigma_kp = 0;
2331
2332     for (i = 0; (i < n); i++)
2333     {
2334         if (t[i] >= fit_start)
2335         {
2336             break;
2337         }
2338     }
2339     tl.n0       = i;
2340     tl.n1       = n;
2341     tl.nparams  = 2;
2342     tl.ndelta   = 1;
2343     tl.t        = t;
2344     tl.ct       = ct;
2345     tl.nt       = nt;
2346     tl.kt       = kt;
2347     tl.sigma_ct = sigma_ct;
2348     tl.sigma_nt = sigma_nt;
2349     tl.sigma_kt = sigma_kt;
2350     tl.kkk[0]   = *k;
2351     tl.kkk[1]   = *kp;
2352
2353     chi2      = 0; /*optimize_luzar_parameters(debug, &tl, 1000, 1e-3); */
2354     *k        = tl.kkk[0];
2355     *kp       = tl.kkk[1] = *kp;
2356     tl.ndelta = NK;
2357     for (j = 0; (j < NK); j++)
2358     {
2359         /* (void) optimize_luzar_parameters(debug, &tl, 1000, 1e-3); */
2360         kkk += tl.kkk[0];
2361         kkp += tl.kkk[1];
2362         kk2 += sqr(tl.kkk[0]);
2363         kp2 += sqr(tl.kkk[1]);
2364         tl.n0++;
2365     }
2366     *sigma_k  = sqrt(kk2/NK - sqr(kkk/NK));
2367     *sigma_kp = sqrt(kp2/NK - sqr(kkp/NK));
2368
2369     return chi2;
2370 }
2371
2372 static void smooth_tail(int n, real t[], real c[], real sigma_c[], real start,
2373                         const output_env_t oenv)
2374 {
2375     FILE *fp;
2376     real  e_1, fitparm[4];
2377     int   i;
2378
2379     e_1 = exp(-1);
2380     for (i = 0; (i < n); i++)
2381     {
2382         if (c[i] < e_1)
2383         {
2384             break;
2385         }
2386     }
2387     if (i < n)
2388     {
2389         fitparm[0] = t[i];
2390     }
2391     else
2392     {
2393         fitparm[0] = 10;
2394     }
2395     fitparm[1] = 0.95;
2396     do_lmfit(n, c, sigma_c, 0, t, start, t[n-1], oenv, bDebugMode(), effnEXP2, fitparm, 0);
2397 }
2398
2399 void analyse_corr(int n, real t[], real ct[], real nt[], real kt[],
2400                   real sigma_ct[], real sigma_nt[], real sigma_kt[],
2401                   real fit_start, real temp, real smooth_tail_start,
2402                   const output_env_t oenv)
2403 {
2404     int        i0, i;
2405     real       k = 1, kp = 1, kow = 1;
2406     real       Q = 0, chi22, chi2, dg, dgp, tau_hb, dtau, tau_rlx, e_1, dt, sigma_k, sigma_kp, ddg;
2407     double     tmp, sn2 = 0, sc2 = 0, sk2 = 0, scn = 0, sck = 0, snk = 0;
2408     gmx_bool   bError = (sigma_ct != NULL) && (sigma_nt != NULL) && (sigma_kt != NULL);
2409
2410     if (smooth_tail_start >= 0)
2411     {
2412         smooth_tail(n, t, ct, sigma_ct, smooth_tail_start, oenv);
2413         smooth_tail(n, t, nt, sigma_nt, smooth_tail_start, oenv);
2414         smooth_tail(n, t, kt, sigma_kt, smooth_tail_start, oenv);
2415     }
2416     for (i0 = 0; (i0 < n-2) && ((t[i0]-t[0]) < fit_start); i0++)
2417     {
2418         ;
2419     }
2420     if (i0 < n-2)
2421     {
2422         for (i = i0; (i < n); i++)
2423         {
2424             sc2 += sqr(ct[i]);
2425             sn2 += sqr(nt[i]);
2426             sk2 += sqr(kt[i]);
2427             sck += ct[i]*kt[i];
2428             snk += nt[i]*kt[i];
2429             scn += ct[i]*nt[i];
2430         }
2431         printf("Hydrogen bond thermodynamics at T = %g K\n", temp);
2432         tmp = (sn2*sc2-sqr(scn));
2433         if ((tmp > 0) && (sn2 > 0))
2434         {
2435             k    = (sn2*sck-scn*snk)/tmp;
2436             kp   = (k*scn-snk)/sn2;
2437             if (bError)
2438             {
2439                 chi2 = 0;
2440                 for (i = i0; (i < n); i++)
2441                 {
2442                     chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
2443                 }
2444                 chi22 = compute_weighted_rates(n, t, ct, nt, kt, sigma_ct, sigma_nt,
2445                                                sigma_kt, &k, &kp,
2446                                                &sigma_k, &sigma_kp, fit_start);
2447                 Q   = 0; /* quality_of_fit(chi2, 2);*/
2448                 ddg = BOLTZ*temp*sigma_k/k;
2449                 printf("Fitting paramaters chi^2 = %10g, Quality of fit = %10g\n",
2450                        chi2, Q);
2451                 printf("The Rate and Delta G are followed by an error estimate\n");
2452                 printf("----------------------------------------------------------\n"
2453                        "Type      Rate (1/ps)  Sigma Time (ps)  DG (kJ/mol)  Sigma\n");
2454                 printf("Forward    %10.3f %6.2f   %8.3f  %10.3f %6.2f\n",
2455                        k, sigma_k, 1/k, calc_dg(1/k, temp), ddg);
2456                 ddg = BOLTZ*temp*sigma_kp/kp;
2457                 printf("Backward   %10.3f %6.2f   %8.3f  %10.3f %6.2f\n",
2458                        kp, sigma_kp, 1/kp, calc_dg(1/kp, temp), ddg);
2459             }
2460             else
2461             {
2462                 chi2 = 0;
2463                 for (i = i0; (i < n); i++)
2464                 {
2465                     chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
2466                 }
2467                 printf("Fitting parameters chi^2 = %10g\nQ = %10g\n",
2468                        chi2, Q);
2469                 printf("--------------------------------------------------\n"
2470                        "Type      Rate (1/ps) Time (ps)  DG (kJ/mol)  Chi^2\n");
2471                 printf("Forward    %10.3f   %8.3f  %10.3f  %10g\n",
2472                        k, 1/k, calc_dg(1/k, temp), chi2);
2473                 printf("Backward   %10.3f   %8.3f  %10.3f\n",
2474                        kp, 1/kp, calc_dg(1/kp, temp));
2475             }
2476         }
2477         if (sc2 > 0)
2478         {
2479             kow  = 2*sck/sc2;
2480             printf("One-way    %10.3f   %s%8.3f  %10.3f\n",
2481                    kow, bError ? "       " : "", 1/kow, calc_dg(1/kow, temp));
2482         }
2483         else
2484         {
2485             printf(" - Numerical problems computing HB thermodynamics:\n"
2486                    "sc2 = %g  sn2 = %g  sk2 = %g sck = %g snk = %g scn = %g\n",
2487                    sc2, sn2, sk2, sck, snk, scn);
2488         }
2489         /* Determine integral of the correlation function */
2490         tau_hb = evaluate_integral(n, t, ct, NULL, (t[n-1]-t[0])/2, &dtau);
2491         printf("Integral   %10.3f   %s%8.3f  %10.3f\n", 1/tau_hb,
2492                bError ? "       " : "", tau_hb, calc_dg(tau_hb, temp));
2493         e_1 = exp(-1);
2494         for (i = 0; (i < n-2); i++)
2495         {
2496             if ((ct[i] > e_1) && (ct[i+1] <= e_1))
2497             {
2498                 break;
2499             }
2500         }
2501         if (i < n-2)
2502         {
2503             /* Determine tau_relax from linear interpolation */
2504             tau_rlx = t[i]-t[0] + (e_1-ct[i])*(t[i+1]-t[i])/(ct[i+1]-ct[i]);
2505             printf("Relaxation %10.3f   %8.3f  %s%10.3f\n", 1/tau_rlx,
2506                    tau_rlx, bError ? "       " : "",
2507                    calc_dg(tau_rlx, temp));
2508         }
2509     }
2510     else
2511     {
2512         printf("Correlation functions too short to compute thermodynamics\n");
2513     }
2514 }
2515
2516 void compute_derivative(int nn, real x[], real y[], real dydx[])
2517 {
2518     int j;
2519
2520     /* Compute k(t) = dc(t)/dt */
2521     for (j = 1; (j < nn-1); j++)
2522     {
2523         dydx[j] = (y[j+1]-y[j-1])/(x[j+1]-x[j-1]);
2524     }
2525     /* Extrapolate endpoints */
2526     dydx[0]    = 2*dydx[1]   -  dydx[2];
2527     dydx[nn-1] = 2*dydx[nn-2] - dydx[nn-3];
2528 }
2529
2530 static void parallel_print(int *data, int nThreads)
2531 {
2532     /* This prints the donors on which each tread is currently working. */
2533     int i;
2534
2535     fprintf(stderr, "\r");
2536     for (i = 0; i < nThreads; i++)
2537     {
2538         fprintf(stderr, "%-7i", data[i]);
2539     }
2540 }
2541
2542 static void normalizeACF(real *ct, real *gt, int nhb, int len)
2543 {
2544     real ct_fac, gt_fac = 0;
2545     int  i;
2546
2547     /* Xu and Berne use the same normalization constant */
2548
2549     ct_fac = 1.0/ct[0];
2550     if (nhb != 0)
2551     {
2552         gt_fac = 1.0/(real)nhb;
2553     }
2554
2555     printf("Normalization for c(t) = %g for gh(t) = %g\n", ct_fac, gt_fac);
2556     for (i = 0; i < len; i++)
2557     {
2558         ct[i] *= ct_fac;
2559         if (gt != NULL)
2560         {
2561             gt[i] *= gt_fac;
2562         }
2563     }
2564 }
2565
2566 /* Added argument bContact in do_hbac(...). Also
2567  * added support for -contact in the actual code.
2568  * - Erik Marklund, May 31, 2006 */
2569 /* Changed contact code and added argument R2
2570  * - Erik Marklund, June 29, 2006
2571  */
2572 static void do_hbac(const char *fn, t_hbdata *hb,
2573                     int nDump, gmx_bool bMerge, gmx_bool bContact, real fit_start,
2574                     real temp, gmx_bool R2, real smooth_tail_start, const output_env_t oenv,
2575                     const char *gemType, int nThreads,
2576                     const int NN, const gmx_bool bBallistic, const gmx_bool bGemFit)
2577 {
2578     FILE          *fp;
2579     int            i, j, k, m, n, o, nd, ihb, idist, n2, nn, iter, nSets;
2580     const char    *legNN[]   = {
2581         "Ac(t)",
2582         "Ac'(t)"
2583     };
2584     static char  **legGem;
2585
2586     const char    *legLuzar[] = {
2587         "Ac\\sfin sys\\v{}\\z{}(t)",
2588         "Ac(t)",
2589         "Cc\\scontact,hb\\v{}\\z{}(t)",
2590         "-dAc\\sfs\\v{}\\z{}/dt"
2591     };
2592     gmx_bool       bNorm = FALSE, bOMP = FALSE;
2593     double         nhb   = 0;
2594     int            nhbi  = 0;
2595     real          *rhbex = NULL, *ht, *gt, *ght, *dght, *kt;
2596     real          *ct, *p_ct, tail, tail2, dtail, ct_fac, ght_fac, *cct;
2597     const real     tol     = 1e-3;
2598     int            nframes = hb->nframes, nf;
2599     unsigned int **h       = NULL, **g = NULL;
2600     int            nh, nhbonds, nhydro, ngh;
2601     t_hbond       *hbh;
2602     PSTYPE         p, *pfound = NULL, np;
2603     t_pShift      *pHist;
2604     int           *ptimes   = NULL, *poff = NULL, anhb, n0, mMax = INT_MIN;
2605     real         **rHbExGem = NULL;
2606     gmx_bool       c;
2607     int            acType;
2608     t_E           *E;
2609     double        *ctdouble, *timedouble, *fittedct;
2610     double         fittolerance = 0.1;
2611     int           *dondata      = NULL, thisThread;
2612
2613     enum {
2614         AC_NONE, AC_NN, AC_GEM, AC_LUZAR
2615     };
2616
2617 #ifdef GMX_OPENMP
2618     bOMP = TRUE;
2619 #else
2620     bOMP = FALSE;
2621 #endif
2622
2623     printf("Doing autocorrelation ");
2624
2625     /* Decide what kind of ACF calculations to do. */
2626     if (NN > NN_NONE && NN < NN_NR)
2627     {
2628 #ifdef HAVE_NN_LOOPS
2629         acType = AC_NN;
2630         printf("using the energy estimate.\n");
2631 #else
2632         acType = AC_NONE;
2633         printf("Can't do the NN-loop. Yet.\n");
2634 #endif
2635     }
2636     else if (hb->bGem)
2637     {
2638         acType = AC_GEM;
2639         printf("according to the reversible geminate recombination model by Omer Markowitch.\n");
2640
2641         nSets = 1 + (bBallistic ? 1 : 0) + (bGemFit ? 1 : 0);
2642         snew(legGem, nSets);
2643         for (i = 0; i < nSets; i++)
2644         {
2645             snew(legGem[i], 128);
2646         }
2647         sprintf(legGem[0], "Ac\\s%s\\v{}\\z{}(t)", gemType);
2648         if (bBallistic)
2649         {
2650             sprintf(legGem[1], "Ac'(t)");
2651         }
2652         if (bGemFit)
2653         {
2654             sprintf(legGem[(bBallistic ? 3 : 2)], "Ac\\s%s,fit\\v{}\\z{}(t)", gemType);
2655         }
2656
2657     }
2658     else
2659     {
2660         acType = AC_LUZAR;
2661         printf("according to the theory of Luzar and Chandler.\n");
2662     }
2663     fflush(stdout);
2664
2665     /* build hbexist matrix in reals for autocorr */
2666     /* Allocate memory for computing ACF (rhbex) and aggregating the ACF (ct) */
2667     n2 = 1;
2668     while (n2 < nframes)
2669     {
2670         n2 *= 2;
2671     }
2672
2673     nn = nframes/2;
2674
2675     if (acType != AC_NN || bOMP)
2676     {
2677         snew(h, hb->maxhydro);
2678         snew(g, hb->maxhydro);
2679     }
2680
2681     /* Dump hbonds for debugging */
2682     dump_ac(hb, bMerge || bContact, nDump);
2683
2684     /* Total number of hbonds analyzed here */
2685     nhbonds = 0;
2686     ngh     = 0;
2687     anhb    = 0;
2688
2689     if (acType != AC_LUZAR && bOMP)
2690     {
2691         nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, gmx_omp_get_max_threads());
2692
2693         gmx_omp_set_num_threads(nThreads);
2694         snew(dondata, nThreads);
2695         for (i = 0; i < nThreads; i++)
2696         {
2697             dondata[i] = -1;
2698         }
2699         printf("ACF calculations parallelized with OpenMP using %i threads.\n"
2700                "Expect close to linear scaling over this donor-loop.\n", nThreads);
2701         fflush(stdout);
2702         fprintf(stderr, "Donors: [thread no]\n");
2703         {
2704             char tmpstr[7];
2705             for (i = 0; i < nThreads; i++)
2706             {
2707                 snprintf(tmpstr, 7, "[%i]", i);
2708                 fprintf(stderr, "%-7s", tmpstr);
2709             }
2710         }
2711         fprintf(stderr, "\n");
2712     }
2713
2714
2715     /* Build the ACF according to acType */
2716     switch (acType)
2717     {
2718
2719         case AC_NN:
2720 #ifdef HAVE_NN_LOOPS
2721             /* Here we're using the estimated energy for the hydrogen bonds. */
2722             snew(ct, nn);
2723
2724 #pragma omp parallel \
2725             private(i, j, k, nh, E, rhbex, thisThread) \
2726             default(shared)
2727             {
2728 #pragma omp barrier
2729                 thisThread = gmx_omp_get_thread_num();
2730                 rhbex      = NULL;
2731
2732                 snew(rhbex, n2);
2733                 memset(rhbex, 0, n2*sizeof(real)); /* Trust no-one, not even malloc()! */
2734
2735 #pragma omp barrier
2736 #pragma omp for schedule (dynamic)
2737                 for (i = 0; i < hb->d.nrd; i++) /* loop over donors */
2738                 {
2739                     if (bOMP)
2740                     {
2741 #pragma omp critical
2742                         {
2743                             dondata[thisThread] = i;
2744                             parallel_print(dondata, nThreads);
2745                         }
2746                     }
2747                     else
2748                     {
2749                         fprintf(stderr, "\r %i", i);
2750                     }
2751
2752                     for (j = 0; j < hb->a.nra; j++)              /* loop over acceptors */
2753                     {
2754                         for (nh = 0; nh < hb->d.nhydro[i]; nh++) /* loop over donors' hydrogens */
2755                         {
2756                             E = hb->hbE.E[i][j][nh];
2757                             if (E != NULL)
2758                             {
2759                                 for (k = 0; k < nframes; k++)
2760                                 {
2761                                     if (E[k] != NONSENSE_E)
2762                                     {
2763                                         rhbex[k] = (real)E[k];
2764                                     }
2765                                 }
2766
2767                                 low_do_autocorr(NULL, oenv, NULL, nframes, 1, -1, &(rhbex), hb->time[1]-hb->time[0],
2768                                                 eacNormal, 1, FALSE, bNorm, FALSE, 0, -1, 0, 1);
2769 #pragma omp critical
2770                                 {
2771                                     for (k = 0; (k < nn); k++)
2772                                     {
2773                                         ct[k] += rhbex[k];
2774                                     }
2775                                 }
2776                             }
2777                         } /* k loop */
2778                     }     /* j loop */
2779                 }         /* i loop */
2780                 sfree(rhbex);
2781 #pragma omp barrier
2782             }
2783
2784             if (bOMP)
2785             {
2786                 sfree(dondata);
2787             }
2788             normalizeACF(ct, NULL, 0, nn);
2789             snew(ctdouble, nn);
2790             snew(timedouble, nn);
2791             for (j = 0; j < nn; j++)
2792             {
2793                 timedouble[j] = (double)(hb->time[j]);
2794                 ctdouble[j]   = (double)(ct[j]);
2795             }
2796
2797             /* Remove ballistic term */
2798             /* Ballistic component removal and fitting to the reversible geminate recombination model
2799              * will be taken out for the time being. First of all, one can remove the ballistic
2800              * component with g_analyze afterwards. Secondly, and more importantly, there are still
2801              * problems with the robustness of the fitting to the model. More work is needed.
2802              * A third reason is that we're currently using gsl for this and wish to reduce dependence
2803              * on external libraries. There are Levenberg-Marquardt and nsimplex solvers that come with
2804              * a BSD-licence that can do the job.
2805              *
2806              * - Erik Marklund, June 18 2010.
2807              */
2808 /*         if (params->ballistic/params->tDelta >= params->nExpFit*2+1) */
2809 /*             takeAwayBallistic(ctdouble, timedouble, nn, params->ballistic, params->nExpFit, params->bDt); */
2810 /*         else */
2811 /*             printf("\nNumber of data points is less than the number of parameters to fit\n." */
2812 /*                    "The system is underdetermined, hence no ballistic term can be found.\n\n"); */
2813
2814             fp = xvgropen(fn, "Hydrogen Bond Autocorrelation", output_env_get_xvgr_tlabel(oenv), "C(t)");
2815             xvgr_legend(fp, asize(legNN), legNN);
2816
2817             for (j = 0; (j < nn); j++)
2818             {
2819                 fprintf(fp, "%10g  %10g %10g\n",
2820                         hb->time[j]-hb->time[0],
2821                         ct[j],
2822                         ctdouble[j]);
2823             }
2824             xvgrclose(fp);
2825             sfree(ct);
2826             sfree(ctdouble);
2827             sfree(timedouble);
2828 #endif             /* HAVE_NN_LOOPS */
2829             break; /* case AC_NN */
2830
2831         case AC_GEM:
2832             snew(ct, 2*n2);
2833             memset(ct, 0, 2*n2*sizeof(real));
2834 #ifndef GMX_OPENMP
2835             fprintf(stderr, "Donor:\n");
2836 #define __ACDATA ct
2837 #else
2838 #define __ACDATA p_ct
2839 #endif
2840
2841 #pragma omp parallel \
2842             private(i, k, nh, hbh, pHist, h, g, n0, nf, np, j, m, \
2843             pfound, poff, rHbExGem, p, ihb, mMax, \
2844             thisThread, p_ct) \
2845             default(shared)
2846             { /* ##########  THE START OF THE ENORMOUS PARALLELIZED BLOCK!  ########## */
2847                 h          = NULL;
2848                 g          = NULL;
2849                 thisThread = gmx_omp_get_thread_num();
2850                 snew(h, hb->maxhydro);
2851                 snew(g, hb->maxhydro);
2852                 mMax     = INT_MIN;
2853                 rHbExGem = NULL;
2854                 poff     = NULL;
2855                 pfound   = NULL;
2856                 p_ct     = NULL;
2857                 snew(p_ct, 2*n2);
2858                 memset(p_ct, 0, 2*n2*sizeof(real));
2859
2860                 /* I'm using a chunk size of 1, since I expect      \
2861                  * the overhead to be really small compared         \
2862                  * to the actual calculations                       \ */
2863 #pragma omp for schedule(dynamic,1) nowait
2864                 for (i = 0; i < hb->d.nrd; i++)
2865                 {
2866
2867                     if (bOMP)
2868                     {
2869 #pragma omp critical
2870                         {
2871                             dondata[thisThread] = i;
2872                             parallel_print(dondata, nThreads);
2873                         }
2874                     }
2875                     else
2876                     {
2877                         fprintf(stderr, "\r %i", i);
2878                     }
2879                     for (k = 0; k < hb->a.nra; k++)
2880                     {
2881                         for (nh = 0; nh < ((bMerge || bContact) ? 1 : hb->d.nhydro[i]); nh++)
2882                         {
2883                             hbh = hb->hbmap[i][k];
2884                             if (hbh)
2885                             {
2886                                 /* Note that if hb->per->gemtype==gemDD, then distances will be stored in
2887                                  * hb->hbmap[d][a].h array anyway, because the contact flag will be set.
2888                                  * hence, it's only with the gemAD mode that hb->hbmap[d][a].g will be used. */
2889                                 pHist = &(hb->per->pHist[i][k]);
2890                                 if (ISHB(hbh->history[nh]) && pHist->len != 0)
2891                                 {
2892
2893                                     {
2894                                         h[nh] = hbh->h[nh];
2895                                         g[nh] = hb->per->gemtype == gemAD ? hbh->g[nh] : NULL;
2896                                     }
2897                                     n0 = hbh->n0;
2898                                     nf = hbh->nframes;
2899                                     /* count the number of periodic shifts encountered and store
2900                                      * them in separate arrays. */
2901                                     np = 0;
2902                                     for (j = 0; j < pHist->len; j++)
2903                                     {
2904                                         p = pHist->p[j];
2905                                         for (m = 0; m <= np; m++)
2906                                         {
2907                                             if (m == np) /* p not recognized in list. Add it and set up new array. */
2908                                             {
2909                                                 np++;
2910                                                 if (np > hb->per->nper)
2911                                                 {
2912                                                     gmx_fatal(FARGS, "Too many pshifts. Something's utterly wrong here.");
2913                                                 }
2914                                                 if (m >= mMax) /* Extend the arrays.
2915                                                                 * Doing it like this, using mMax to keep track of the sizes,
2916                                                                 * eleviates the need for freeing and re-allocating the arrays
2917                                                                 * when taking on the next donor-acceptor pair */
2918                                                 {
2919                                                     mMax = m;
2920                                                     srenew(pfound, np);   /* The list of found periodic shifts. */
2921                                                     srenew(rHbExGem, np); /* The hb existence functions (-aver_hb). */
2922                                                     snew(rHbExGem[m], 2*n2);
2923                                                     srenew(poff, np);
2924                                                 }
2925
2926                                                 {
2927                                                     if (rHbExGem != NULL && rHbExGem[m] != NULL)
2928                                                     {
2929                                                         /* This must be done, as this array was most likey
2930                                                          * used to store stuff in some previous iteration. */
2931                                                         memset(rHbExGem[m], 0, (sizeof(real)) * (2*n2));
2932                                                     }
2933                                                     else
2934                                                     {
2935                                                         fprintf(stderr, "rHbExGem not initialized! m = %i\n", m);
2936                                                     }
2937                                                 }
2938                                                 pfound[m] = p;
2939                                                 poff[m]   = -1;
2940
2941                                                 break;
2942                                             } /* m==np */
2943                                             if (p == pfound[m])
2944                                             {
2945                                                 break;
2946                                             }
2947                                         } /* m: Loop over found shifts */
2948                                     }     /* j: Loop over shifts */
2949
2950                                     /* Now unpack and disentangle the existence funtions. */
2951                                     for (j = 0; j < nf; j++)
2952                                     {
2953                                         /* i:       donor,
2954                                          * k:       acceptor
2955                                          * nh:      hydrogen
2956                                          * j:       time
2957                                          * p:       periodic shift
2958                                          * pfound:  list of periodic shifts found for this pair.
2959                                          * poff:    list of frame offsets; that is, the first
2960                                          *          frame a hbond has a particular periodic shift. */
2961                                         p = getPshift(*pHist, j+n0);
2962                                         if (p != -1)
2963                                         {
2964                                             for (m = 0; m < np; m++)
2965                                             {
2966                                                 if (pfound[m] == p)
2967                                                 {
2968                                                     break;
2969                                                 }
2970                                                 if (m == (np-1))
2971                                                 {
2972                                                     gmx_fatal(FARGS, "Shift not found, but must be there.");
2973                                                 }
2974                                             }
2975
2976                                             ihb = is_hb(h[nh], j) || ((hb->per->gemtype != gemAD || j == 0) ? FALSE : is_hb(g[nh], j));
2977                                             if (ihb)
2978                                             {
2979                                                 if (poff[m] == -1)
2980                                                 {
2981                                                     poff[m] = j; /* Here's where the first hbond with shift p is,
2982                                                                   * relative to the start of h[0].*/
2983                                                 }
2984                                                 if (j < poff[m])
2985                                                 {
2986                                                     gmx_fatal(FARGS, "j<poff[m]");
2987                                                 }
2988                                                 rHbExGem[m][j-poff[m]] += 1;
2989                                             }
2990                                         }
2991                                     }
2992
2993                                     /* Now, build ac. */
2994                                     for (m = 0; m < np; m++)
2995                                     {
2996                                         if (rHbExGem[m][0] > 0  && n0+poff[m] < nn /*  && m==0 */)
2997                                         {
2998                                             low_do_autocorr(NULL, oenv, NULL, nframes, 1, -1, &(rHbExGem[m]), hb->time[1]-hb->time[0],
2999                                                             eacNormal, 1, FALSE, bNorm, FALSE, 0, -1, 0);
3000                                             for (j = 0; (j < nn); j++)
3001                                             {
3002                                                 __ACDATA[j] += rHbExGem[m][j];
3003                                             }
3004                                         }
3005                                     } /* Building of ac. */
3006                                 }     /* if (ISHB(...*/
3007                             }         /* if (hbh) */
3008                         }             /* hydrogen loop */
3009                     }                 /* acceptor loop */
3010                 }                     /* donor loop */
3011
3012                 for (m = 0; m <= mMax; m++)
3013                 {
3014                     sfree(rHbExGem[m]);
3015                 }
3016                 sfree(pfound);
3017                 sfree(poff);
3018                 sfree(rHbExGem);
3019
3020                 sfree(h);
3021                 sfree(g);
3022
3023                 if (bOMP)
3024                 {
3025 #pragma omp critical
3026                     {
3027                         for (i = 0; i < nn; i++)
3028                         {
3029                             ct[i] += p_ct[i];
3030                         }
3031                     }
3032                     sfree(p_ct);
3033                 }
3034
3035             } /* ########## THE END OF THE ENORMOUS PARALLELIZED BLOCK ########## */
3036             if (bOMP)
3037             {
3038                 sfree(dondata);
3039             }
3040
3041             normalizeACF(ct, NULL, 0, nn);
3042
3043             fprintf(stderr, "\n\nACF successfully calculated.\n");
3044
3045             /* Use this part to fit to geminate recombination - JCP 129, 84505 (2008) */
3046
3047             snew(ctdouble, nn);
3048             snew(timedouble, nn);
3049             snew(fittedct, nn);
3050
3051             for (j = 0; j < nn; j++)
3052             {
3053                 timedouble[j] = (double)(hb->time[j]);
3054                 ctdouble[j]   = (double)(ct[j]);
3055             }
3056
3057             /* Remove ballistic term */
3058             /* Ballistic component removal and fitting to the reversible geminate recombination model
3059              * will be taken out for the time being. First of all, one can remove the ballistic
3060              * component with g_analyze afterwards. Secondly, and more importantly, there are still
3061              * problems with the robustness of the fitting to the model. More work is needed.
3062              * A third reason is that we're currently using gsl for this and wish to reduce dependence
3063              * on external libraries. There are Levenberg-Marquardt and nsimplex solvers that come with
3064              * a BSD-licence that can do the job.
3065              *
3066              * - Erik Marklund, June 18 2010.
3067              */
3068 /*         if (bBallistic) { */
3069 /*             if (params->ballistic/params->tDelta >= params->nExpFit*2+1) */
3070 /*                 takeAwayBallistic(ctdouble, timedouble, nn, params->ballistic, params->nExpFit, params->bDt); */
3071 /*             else */
3072 /*                 printf("\nNumber of data points is less than the number of parameters to fit\n." */
3073 /*                        "The system is underdetermined, hence no ballistic term can be found.\n\n"); */
3074 /*         } */
3075 /*         if (bGemFit) */
3076 /*             fitGemRecomb(ctdouble, timedouble, &fittedct, nn, params); */
3077
3078
3079             if (bContact)
3080             {
3081                 fp = xvgropen(fn, "Contact Autocorrelation", output_env_get_xvgr_tlabel(oenv), "C(t)", oenv);
3082             }
3083             else
3084             {
3085                 fp = xvgropen(fn, "Hydrogen Bond Autocorrelation", output_env_get_xvgr_tlabel(oenv), "C(t)", oenv);
3086             }
3087             xvgr_legend(fp, asize(legGem), (const char**)legGem, oenv);
3088
3089             for (j = 0; (j < nn); j++)
3090             {
3091                 fprintf(fp, "%10g  %10g", hb->time[j]-hb->time[0], ct[j]);
3092                 if (bBallistic)
3093                 {
3094                     fprintf(fp, "  %10g", ctdouble[j]);
3095                 }
3096                 if (bGemFit)
3097                 {
3098                     fprintf(fp, "  %10g", fittedct[j]);
3099                 }
3100                 fprintf(fp, "\n");
3101             }
3102             xvgrclose(fp);
3103
3104             sfree(ctdouble);
3105             sfree(timedouble);
3106             sfree(fittedct);
3107             sfree(ct);
3108
3109             break; /* case AC_GEM */
3110
3111         case AC_LUZAR:
3112             snew(rhbex, 2*n2);
3113             snew(ct, 2*n2);
3114             snew(gt, 2*n2);
3115             snew(ht, 2*n2);
3116             snew(ght, 2*n2);
3117             snew(dght, 2*n2);
3118
3119             snew(kt, nn);
3120             snew(cct, nn);
3121
3122             for (i = 0; (i < hb->d.nrd); i++)
3123             {
3124                 for (k = 0; (k < hb->a.nra); k++)
3125                 {
3126                     nhydro = 0;
3127                     hbh    = hb->hbmap[i][k];
3128
3129                     if (hbh)
3130                     {
3131                         if (bMerge || bContact)
3132                         {
3133                             if (ISHB(hbh->history[0]))
3134                             {
3135                                 h[0]   = hbh->h[0];
3136                                 g[0]   = hbh->g[0];
3137                                 nhydro = 1;
3138                             }
3139                         }
3140                         else
3141                         {
3142                             for (m = 0; (m < hb->maxhydro); m++)
3143                             {
3144                                 if (bContact ? ISDIST(hbh->history[m]) : ISHB(hbh->history[m]))
3145                                 {
3146                                     g[nhydro] = hbh->g[m];
3147                                     h[nhydro] = hbh->h[m];
3148                                     nhydro++;
3149                                 }
3150                             }
3151                         }
3152
3153                         nf = hbh->nframes;
3154                         for (nh = 0; (nh < nhydro); nh++)
3155                         {
3156                             int nrint = bContact ? hb->nrdist : hb->nrhb;
3157                             if ((((nhbonds+1) % 10) == 0) || (nhbonds+1 == nrint))
3158                             {
3159                                 fprintf(stderr, "\rACF %d/%d", nhbonds+1, nrint);
3160                             }
3161                             nhbonds++;
3162                             for (j = 0; (j < nframes); j++)
3163                             {
3164                                 /* Changed '<' into '<=' below, just like I did in
3165                                    the hbm-output-loop in the gmx_hbond() block.
3166                                    - Erik Marklund, May 31, 2006 */
3167                                 if (j <= nf)
3168                                 {
3169                                     ihb   = is_hb(h[nh], j);
3170                                     idist = is_hb(g[nh], j);
3171                                 }
3172                                 else
3173                                 {
3174                                     ihb = idist = 0;
3175                                 }
3176                                 rhbex[j] = ihb;
3177                                 /* For contacts: if a second cut-off is provided, use it,
3178                                  * otherwise use g(t) = 1-h(t) */
3179                                 if (!R2 && bContact)
3180                                 {
3181                                     gt[j]  = 1-ihb;
3182                                 }
3183                                 else
3184                                 {
3185                                     gt[j]  = idist*(1-ihb);
3186                                 }
3187                                 ht[j]    = rhbex[j];
3188                                 nhb     += ihb;
3189                             }
3190
3191
3192                             /* The autocorrelation function is normalized after summation only */
3193                             low_do_autocorr(NULL, oenv, NULL, nframes, 1, -1, &rhbex, hb->time[1]-hb->time[0],
3194                                             eacNormal, 1, FALSE, bNorm, FALSE, 0, -1, 0);
3195
3196                             /* Cross correlation analysis for thermodynamics */
3197                             for (j = nframes; (j < n2); j++)
3198                             {
3199                                 ht[j] = 0;
3200                                 gt[j] = 0;
3201                             }
3202
3203                             cross_corr(n2, ht, gt, dght);
3204
3205                             for (j = 0; (j < nn); j++)
3206                             {
3207                                 ct[j]  += rhbex[j];
3208                                 ght[j] += dght[j];
3209                             }
3210                         }
3211                     }
3212                 }
3213             }
3214             fprintf(stderr, "\n");
3215             sfree(h);
3216             sfree(g);
3217             normalizeACF(ct, ght, nhb, nn);
3218
3219             /* Determine tail value for statistics */
3220             tail  = 0;
3221             tail2 = 0;
3222             for (j = nn/2; (j < nn); j++)
3223             {
3224                 tail  += ct[j];
3225                 tail2 += ct[j]*ct[j];
3226             }
3227             tail  /= (nn - nn/2);
3228             tail2 /= (nn - nn/2);
3229             dtail  = sqrt(tail2-tail*tail);
3230
3231             /* Check whether the ACF is long enough */
3232             if (dtail > tol)
3233             {
3234                 printf("\nWARNING: Correlation function is probably not long enough\n"
3235                        "because the standard deviation in the tail of C(t) > %g\n"
3236                        "Tail value (average C(t) over second half of acf): %g +/- %g\n",
3237                        tol, tail, dtail);
3238             }
3239             for (j = 0; (j < nn); j++)
3240             {
3241                 cct[j] = ct[j];
3242                 ct[j]  = (cct[j]-tail)/(1-tail);
3243             }
3244             /* Compute negative derivative k(t) = -dc(t)/dt */
3245             compute_derivative(nn, hb->time, ct, kt);
3246             for (j = 0; (j < nn); j++)
3247             {
3248                 kt[j] = -kt[j];
3249             }
3250
3251
3252             if (bContact)
3253             {
3254                 fp = xvgropen(fn, "Contact Autocorrelation", output_env_get_xvgr_tlabel(oenv), "C(t)", oenv);
3255             }
3256             else
3257             {
3258                 fp = xvgropen(fn, "Hydrogen Bond Autocorrelation", output_env_get_xvgr_tlabel(oenv), "C(t)", oenv);
3259             }
3260             xvgr_legend(fp, asize(legLuzar), legLuzar, oenv);
3261
3262
3263             for (j = 0; (j < nn); j++)
3264             {
3265                 fprintf(fp, "%10g  %10g  %10g  %10g  %10g\n",
3266                         hb->time[j]-hb->time[0], ct[j], cct[j], ght[j], kt[j]);
3267             }
3268             gmx_ffclose(fp);
3269
3270             analyse_corr(nn, hb->time, ct, ght, kt, NULL, NULL, NULL,
3271                          fit_start, temp, smooth_tail_start, oenv);
3272
3273             do_view(oenv, fn, NULL);
3274             sfree(rhbex);
3275             sfree(ct);
3276             sfree(gt);
3277             sfree(ht);
3278             sfree(ght);
3279             sfree(dght);
3280             sfree(cct);
3281             sfree(kt);
3282             /* sfree(h); */
3283 /*         sfree(g); */
3284
3285             break; /* case AC_LUZAR */
3286
3287         default:
3288             gmx_fatal(FARGS, "Unrecognized type of ACF-calulation. acType = %i.", acType);
3289     } /* switch (acType) */
3290 }
3291
3292 static void init_hbframe(t_hbdata *hb, int nframes, real t)
3293 {
3294     int i, j, m;
3295
3296     hb->time[nframes]   = t;
3297     hb->nhb[nframes]    = 0;
3298     hb->ndist[nframes]  = 0;
3299     for (i = 0; (i < max_hx); i++)
3300     {
3301         hb->nhx[nframes][i] = 0;
3302     }
3303     /* Loop invalidated */
3304     if (hb->bHBmap && 0)
3305     {
3306         for (i = 0; (i < hb->d.nrd); i++)
3307         {
3308             for (j = 0; (j < hb->a.nra); j++)
3309             {
3310                 for (m = 0; (m < hb->maxhydro); m++)
3311                 {
3312                     if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[m])
3313                     {
3314                         set_hb(hb, i, m, j, nframes, HB_NO);
3315                     }
3316                 }
3317             }
3318         }
3319     }
3320     /*set_hb(hb->hbmap[i][j]->h[m],nframes-hb->hbmap[i][j]->n0,HB_NO);*/
3321 }
3322
3323 static void analyse_donor_props(const char *fn, t_hbdata *hb, int nframes, real t,
3324                                 const output_env_t oenv)
3325 {
3326     static FILE *fp    = NULL;
3327     const char  *leg[] = { "Nbound", "Nfree" };
3328     int          i, j, k, nbound, nb, nhtot;
3329
3330     if (!fn)
3331     {
3332         return;
3333     }
3334     if (!fp)
3335     {
3336         fp = xvgropen(fn, "Donor properties", output_env_get_xvgr_tlabel(oenv), "Number", oenv);
3337         xvgr_legend(fp, asize(leg), leg, oenv);
3338     }
3339     nbound = 0;
3340     nhtot  = 0;
3341     for (i = 0; (i < hb->d.nrd); i++)
3342     {
3343         for (k = 0; (k < hb->d.nhydro[i]); k++)
3344         {
3345             nb = 0;
3346             nhtot++;
3347             for (j = 0; (j < hb->a.nra) && (nb == 0); j++)
3348             {
3349                 if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[k] &&
3350                     is_hb(hb->hbmap[i][j]->h[k], nframes))
3351                 {
3352                     nb = 1;
3353                 }
3354             }
3355             nbound += nb;
3356         }
3357     }
3358     fprintf(fp, "%10.3e  %6d  %6d\n", t, nbound, nhtot-nbound);
3359 }
3360
3361 static void dump_hbmap(t_hbdata *hb,
3362                        int nfile, t_filenm fnm[], gmx_bool bTwo,
3363                        gmx_bool bContact, int isize[], int *index[], char *grpnames[],
3364                        t_atoms *atoms)
3365 {
3366     FILE    *fp, *fplog;
3367     int      ddd, hhh, aaa, i, j, k, m, grp;
3368     char     ds[32], hs[32], as[32];
3369     gmx_bool first;
3370
3371     fp = opt2FILE("-hbn", nfile, fnm, "w");
3372     if (opt2bSet("-g", nfile, fnm))
3373     {
3374         fplog = gmx_ffopen(opt2fn("-g", nfile, fnm), "w");
3375         fprintf(fplog, "# %10s  %12s  %12s\n", "Donor", "Hydrogen", "Acceptor");
3376     }
3377     else
3378     {
3379         fplog = NULL;
3380     }
3381     for (grp = gr0; grp <= (bTwo ? gr1 : gr0); grp++)
3382     {
3383         fprintf(fp, "[ %s ]", grpnames[grp]);
3384         for (i = 0; i < isize[grp]; i++)
3385         {
3386             fprintf(fp, (i%15) ? " " : "\n");
3387             fprintf(fp, " %4u", index[grp][i]+1);
3388         }
3389         fprintf(fp, "\n");
3390         /*
3391            Added -contact support below.
3392            - Erik Marklund, May 29, 2006
3393          */
3394         if (!bContact)
3395         {
3396             fprintf(fp, "[ donors_hydrogens_%s ]\n", grpnames[grp]);
3397             for (i = 0; (i < hb->d.nrd); i++)
3398             {
3399                 if (hb->d.grp[i] == grp)
3400                 {
3401                     for (j = 0; (j < hb->d.nhydro[i]); j++)
3402                     {
3403                         fprintf(fp, " %4u %4u", hb->d.don[i]+1,
3404                                 hb->d.hydro[i][j]+1);
3405                     }
3406                     fprintf(fp, "\n");
3407                 }
3408             }
3409             first = TRUE;
3410             fprintf(fp, "[ acceptors_%s ]", grpnames[grp]);
3411             for (i = 0; (i < hb->a.nra); i++)
3412             {
3413                 if (hb->a.grp[i] == grp)
3414                 {
3415                     fprintf(fp, (i%15 && !first) ? " " : "\n");
3416                     fprintf(fp, " %4u", hb->a.acc[i]+1);
3417                     first = FALSE;
3418                 }
3419             }
3420             fprintf(fp, "\n");
3421         }
3422     }
3423     if (bTwo)
3424     {
3425         fprintf(fp, bContact ? "[ contacts_%s-%s ]\n" :
3426                 "[ hbonds_%s-%s ]\n", grpnames[0], grpnames[1]);
3427     }
3428     else
3429     {
3430         fprintf(fp, bContact ? "[ contacts_%s ]" : "[ hbonds_%s ]\n", grpnames[0]);
3431     }
3432
3433     for (i = 0; (i < hb->d.nrd); i++)
3434     {
3435         ddd = hb->d.don[i];
3436         for (k = 0; (k < hb->a.nra); k++)
3437         {
3438             aaa = hb->a.acc[k];
3439             for (m = 0; (m < hb->d.nhydro[i]); m++)
3440             {
3441                 if (hb->hbmap[i][k] && ISHB(hb->hbmap[i][k]->history[m]))
3442                 {
3443                     sprintf(ds, "%s", mkatomname(atoms, ddd));
3444                     sprintf(as, "%s", mkatomname(atoms, aaa));
3445                     if (bContact)
3446                     {
3447                         fprintf(fp, " %6u %6u\n", ddd+1, aaa+1);
3448                         if (fplog)
3449                         {
3450                             fprintf(fplog, "%12s  %12s\n", ds, as);
3451                         }
3452                     }
3453                     else
3454                     {
3455                         hhh = hb->d.hydro[i][m];
3456                         sprintf(hs, "%s", mkatomname(atoms, hhh));
3457                         fprintf(fp, " %6u %6u %6u\n", ddd+1, hhh+1, aaa+1);
3458                         if (fplog)
3459                         {
3460                             fprintf(fplog, "%12s  %12s  %12s\n", ds, hs, as);
3461                         }
3462                     }
3463                 }
3464             }
3465         }
3466     }
3467     gmx_ffclose(fp);
3468     if (fplog)
3469     {
3470         gmx_ffclose(fplog);
3471     }
3472 }
3473
3474 /* sync_hbdata() updates the parallel t_hbdata p_hb using hb as template.
3475  * It mimics add_frames() and init_frame() to some extent. */
3476 static void sync_hbdata(t_hbdata *p_hb, int nframes)
3477 {
3478     int i;
3479     if (nframes >= p_hb->max_frames)
3480     {
3481         p_hb->max_frames += 4096;
3482         srenew(p_hb->nhb,   p_hb->max_frames);
3483         srenew(p_hb->ndist, p_hb->max_frames);
3484         srenew(p_hb->n_bound, p_hb->max_frames);
3485         srenew(p_hb->nhx, p_hb->max_frames);
3486         if (p_hb->bDAnr)
3487         {
3488             srenew(p_hb->danr, p_hb->max_frames);
3489         }
3490         memset(&(p_hb->nhb[nframes]),   0, sizeof(int) * (p_hb->max_frames-nframes));
3491         memset(&(p_hb->ndist[nframes]), 0, sizeof(int) * (p_hb->max_frames-nframes));
3492         p_hb->nhb[nframes]   = 0;
3493         p_hb->ndist[nframes] = 0;
3494
3495     }
3496     p_hb->nframes = nframes;
3497 /*     for (i=0;) */
3498 /*     { */
3499 /*         p_hb->nhx[nframes][i] */
3500 /*     } */
3501     memset(&(p_hb->nhx[nframes]), 0, sizeof(int)*max_hx); /* zero the helix count for this frame */
3502
3503     /* hb->per will remain constant througout the frame loop,
3504      * even though the data its members point to will change,
3505      * hence no need for re-syncing. */
3506 }
3507
3508 int gmx_hbond(int argc, char *argv[])
3509 {
3510     const char        *desc[] = {
3511         "[THISMODULE] computes and analyzes hydrogen bonds. Hydrogen bonds are",
3512         "determined based on cutoffs for the angle Hydrogen - Donor - Acceptor",
3513         "(zero is extended) and the distance Donor - Acceptor",
3514         "(or Hydrogen - Acceptor using [TT]-noda[tt]).",
3515         "OH and NH groups are regarded as donors, O is an acceptor always,",
3516         "N is an acceptor by default, but this can be switched using",
3517         "[TT]-nitacc[tt]. Dummy hydrogen atoms are assumed to be connected",
3518         "to the first preceding non-hydrogen atom.[PAR]",
3519
3520         "You need to specify two groups for analysis, which must be either",
3521         "identical or non-overlapping. All hydrogen bonds between the two",
3522         "groups are analyzed.[PAR]",
3523
3524         "If you set [TT]-shell[tt], you will be asked for an additional index group",
3525         "which should contain exactly one atom. In this case, only hydrogen",
3526         "bonds between atoms within the shell distance from the one atom are",
3527         "considered.[PAR]",
3528
3529         "With option -ac, rate constants for hydrogen bonding can be derived with the model of Luzar and Chandler",
3530         "(Nature 394, 1996; J. Chem. Phys. 113:23, 2000) or that of Markovitz and Agmon (J. Chem. Phys 129, 2008).",
3531         "If contact kinetics are analyzed by using the -contact option, then",
3532         "n(t) can be defined as either all pairs that are not within contact distance r at time t",
3533         "(corresponding to leaving the -r2 option at the default value 0) or all pairs that",
3534         "are within distance r2 (corresponding to setting a second cut-off value with option -r2).",
3535         "See mentioned literature for more details and definitions."
3536         "[PAR]",
3537
3538         /*    "It is also possible to analyse specific hydrogen bonds with",
3539               "[TT]-sel[tt]. This index file must contain a group of atom triplets",
3540               "Donor Hydrogen Acceptor, in the following way:[PAR]",
3541          */
3542         "[TT]",
3543         "[ selected ][BR]",
3544         "     20    21    24[BR]",
3545         "     25    26    29[BR]",
3546         "      1     3     6[BR]",
3547         "[tt][BR]",
3548         "Note that the triplets need not be on separate lines.",
3549         "Each atom triplet specifies a hydrogen bond to be analyzed,",
3550         "note also that no check is made for the types of atoms.[PAR]",
3551
3552         "[BB]Output:[bb][BR]",
3553         "[TT]-num[tt]:  number of hydrogen bonds as a function of time.[BR]",
3554         "[TT]-ac[tt]:   average over all autocorrelations of the existence",
3555         "functions (either 0 or 1) of all hydrogen bonds.[BR]",
3556         "[TT]-dist[tt]: distance distribution of all hydrogen bonds.[BR]",
3557         "[TT]-ang[tt]:  angle distribution of all hydrogen bonds.[BR]",
3558         "[TT]-hx[tt]:   the number of n-n+i hydrogen bonds as a function of time",
3559         "where n and n+i stand for residue numbers and i ranges from 0 to 6.",
3560         "This includes the n-n+3, n-n+4 and n-n+5 hydrogen bonds associated",
3561         "with helices in proteins.[BR]",
3562         "[TT]-hbn[tt]:  all selected groups, donors, hydrogens and acceptors",
3563         "for selected groups, all hydrogen bonded atoms from all groups and",
3564         "all solvent atoms involved in insertion.[BR]",
3565         "[TT]-hbm[tt]:  existence matrix for all hydrogen bonds over all",
3566         "frames, this also contains information on solvent insertion",
3567         "into hydrogen bonds. Ordering is identical to that in [TT]-hbn[tt]",
3568         "index file.[BR]",
3569         "[TT]-dan[tt]: write out the number of donors and acceptors analyzed for",
3570         "each timeframe. This is especially useful when using [TT]-shell[tt].[BR]",
3571         "[TT]-nhbdist[tt]: compute the number of HBonds per hydrogen in order to",
3572         "compare results to Raman Spectroscopy.",
3573         "[PAR]",
3574         "Note: options [TT]-ac[tt], [TT]-life[tt], [TT]-hbn[tt] and [TT]-hbm[tt]",
3575         "require an amount of memory proportional to the total numbers of donors",
3576         "times the total number of acceptors in the selected group(s)."
3577     };
3578
3579     static real        acut     = 30, abin = 1, rcut = 0.35, r2cut = 0, rbin = 0.005, rshell = -1;
3580     static real        maxnhb   = 0, fit_start = 1, fit_end = 60, temp = 298.15, smooth_tail_start = -1, D = -1;
3581     static gmx_bool    bNitAcc  = TRUE, bDA = TRUE, bMerge = TRUE;
3582     static int         nDump    = 0, nFitPoints = 100;
3583     static int         nThreads = 0, nBalExp = 4;
3584
3585     static gmx_bool    bContact     = FALSE, bBallistic = FALSE, bGemFit = FALSE;
3586     static real        logAfterTime = 10, gemBallistic = 0.2; /* ps */
3587     static const char *NNtype[]     = {NULL, "none", "binary", "oneOverR3", "dipole", NULL};
3588
3589     /* options */
3590     t_pargs     pa [] = {
3591         { "-a",    FALSE,  etREAL, {&acut},
3592           "Cutoff angle (degrees, Hydrogen - Donor - Acceptor)" },
3593         { "-r",    FALSE,  etREAL, {&rcut},
3594           "Cutoff radius (nm, X - Acceptor, see next option)" },
3595         { "-da",   FALSE,  etBOOL, {&bDA},
3596           "Use distance Donor-Acceptor (if TRUE) or Hydrogen-Acceptor (FALSE)" },
3597         { "-r2",   FALSE,  etREAL, {&r2cut},
3598           "Second cutoff radius. Mainly useful with [TT]-contact[tt] and [TT]-ac[tt]"},
3599         { "-abin", FALSE,  etREAL, {&abin},
3600           "Binwidth angle distribution (degrees)" },
3601         { "-rbin", FALSE,  etREAL, {&rbin},
3602           "Binwidth distance distribution (nm)" },
3603         { "-nitacc", FALSE, etBOOL, {&bNitAcc},
3604           "Regard nitrogen atoms as acceptors" },
3605         { "-contact", FALSE, etBOOL, {&bContact},
3606           "Do not look for hydrogen bonds, but merely for contacts within the cut-off distance" },
3607         { "-shell", FALSE, etREAL, {&rshell},
3608           "when > 0, only calculate hydrogen bonds within # nm shell around "
3609           "one particle" },
3610         { "-fitstart", FALSE, etREAL, {&fit_start},
3611           "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. With [TT]-gemfit[tt] we suggest [TT]-fitstart 0[tt]" },
3612         { "-fitend", FALSE, etREAL, {&fit_end},
3613           "Time (ps) to which to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation (only with [TT]-gemfit[tt])" },
3614         { "-temp",  FALSE, etREAL, {&temp},
3615           "Temperature (K) for computing the Gibbs energy corresponding to HB breaking and reforming" },
3616         { "-smooth", FALSE, etREAL, {&smooth_tail_start},
3617           "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/[GRK]tau[grk])" },
3618         { "-dump",  FALSE, etINT, {&nDump},
3619           "Dump the first N hydrogen bond ACFs in a single [TT].xvg[tt] file for debugging" },
3620         { "-max_hb", FALSE, etREAL, {&maxnhb},
3621           "Theoretical maximum number of hydrogen bonds used for normalizing HB autocorrelation function. Can be useful in case the program estimates it wrongly" },
3622         { "-merge", FALSE, etBOOL, {&bMerge},
3623           "H-bonds between the same donor and acceptor, but with different hydrogen are treated as a single H-bond. Mainly important for the ACF." },
3624         { "-geminate", FALSE, etENUM, {gemType},
3625           "HIDDENUse reversible geminate recombination for the kinetics/thermodynamics calclations. See Markovitch et al., J. Chem. Phys 129, 084505 (2008) for details."},
3626         { "-diff", FALSE, etREAL, {&D},
3627           "HIDDENDffusion coefficient to use in the reversible geminate recombination kinetic model. If negative, then it will be fitted to the ACF along with ka and kd."},
3628 #ifdef GMX_OPENMP
3629         { "-nthreads", FALSE, etINT, {&nThreads},
3630           "Number of threads used for the parallel loop over autocorrelations. nThreads <= 0 means maximum number of threads. Requires linking with OpenMP. The number of threads is limited by the number of cores (before OpenMP v.3 ) or environment variable OMP_THREAD_LIMIT (OpenMP v.3)"},
3631 #endif
3632     };
3633     const char *bugs[] = {
3634         "The option [TT]-sel[tt] that used to work on selected hbonds is out of order, and therefore not available for the time being."
3635     };
3636     t_filenm    fnm[] = {
3637         { efTRX, "-f",   NULL,     ffREAD  },
3638         { efTPX, NULL,   NULL,     ffREAD  },
3639         { efNDX, NULL,   NULL,     ffOPTRD },
3640         /*    { efNDX, "-sel", "select", ffOPTRD },*/
3641         { efXVG, "-num", "hbnum",  ffWRITE },
3642         { efLOG, "-g",   "hbond",  ffOPTWR },
3643         { efXVG, "-ac",  "hbac",   ffOPTWR },
3644         { efXVG, "-dist", "hbdist", ffOPTWR },
3645         { efXVG, "-ang", "hbang",  ffOPTWR },
3646         { efXVG, "-hx",  "hbhelix", ffOPTWR },
3647         { efNDX, "-hbn", "hbond",  ffOPTWR },
3648         { efXPM, "-hbm", "hbmap",  ffOPTWR },
3649         { efXVG, "-don", "donor",  ffOPTWR },
3650         { efXVG, "-dan", "danum",  ffOPTWR },
3651         { efXVG, "-life", "hblife", ffOPTWR },
3652         { efXVG, "-nhbdist", "nhbdist", ffOPTWR }
3653
3654     };
3655 #define NFILE asize(fnm)
3656
3657     char                  hbmap [HB_NR] = { ' ',    'o',      '-',       '*' };
3658     const char           *hbdesc[HB_NR] = { "None", "Present", "Inserted", "Present & Inserted" };
3659     t_rgb                 hbrgb [HB_NR] = { {1, 1, 1}, {1, 0, 0},   {0, 0, 1},    {1, 0, 1} };
3660
3661     t_trxstatus          *status;
3662     int                   trrStatus = 1;
3663     t_topology            top;
3664     t_inputrec            ir;
3665     t_pargs              *ppa;
3666     int                   npargs, natoms, nframes = 0, shatom;
3667     int                  *isize;
3668     char                **grpnames;
3669     atom_id             **index;
3670     rvec                 *x, hbox;
3671     matrix                box;
3672     real                  t, ccut, dist = 0.0, ang = 0.0;
3673     double                max_nhb, aver_nhb, aver_dist;
3674     int                   h = 0, i = 0, j, k = 0, l, start, end, id, ja, ogrp, nsel;
3675     int                   xi, yi, zi, ai;
3676     int                   xj, yj, zj, aj, xjj, yjj, zjj;
3677     int                   xk, yk, zk, ak, xkk, ykk, zkk;
3678     gmx_bool              bSelected, bHBmap, bStop, bTwo, was, bBox, bTric;
3679     int                  *adist, *rdist, *aptr, *rprt;
3680     int                   grp, nabin, nrbin, bin, resdist, ihb;
3681     char                **leg;
3682     t_hbdata             *hb, *hbptr;
3683     FILE                 *fp, *fpins = NULL, *fpnhb = NULL;
3684     t_gridcell         ***grid;
3685     t_ncell              *icell, *jcell, *kcell;
3686     ivec                  ngrid;
3687     unsigned char        *datable;
3688     output_env_t          oenv;
3689     int                   gemmode, NN;
3690     PSTYPE                peri = 0;
3691     t_E                   E;
3692     int                   ii, jj, hh, actual_nThreads;
3693     int                   threadNr = 0;
3694     gmx_bool              bGem, bNN, bParallel;
3695     t_gemParams          *params = NULL;
3696     gmx_bool              bEdge_yjj, bEdge_xjj, bOMP;
3697
3698     t_hbdata            **p_hb    = NULL;                   /* one per thread, then merge after the frame loop */
3699     int                 **p_adist = NULL, **p_rdist = NULL; /* a histogram for each thread. */
3700
3701 #ifdef GMX_OPENMP
3702     bOMP = TRUE;
3703 #else
3704     bOMP = FALSE;
3705 #endif
3706
3707     npargs = asize(pa);
3708     ppa    = add_acf_pargs(&npargs, pa);
3709
3710     if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE, NFILE, fnm, npargs,
3711                            ppa, asize(desc), desc, asize(bugs), bugs, &oenv))
3712     {
3713         return 0;
3714     }
3715
3716     /* NN-loop? If so, what estimator to use ?*/
3717     NN = 1;
3718     /* Outcommented for now DvdS 2010-07-13
3719        while (NN < NN_NR && gmx_strcasecmp(NNtype[0], NNtype[NN])!=0)
3720         NN++;
3721        if (NN == NN_NR)
3722         gmx_fatal(FARGS, "Invalid NN-loop type.");
3723      */
3724     bNN = FALSE;
3725     for (i = 2; bNN == FALSE && i < NN_NR; i++)
3726     {
3727         bNN = bNN || NN == i;
3728     }
3729
3730     if (NN > NN_NONE && bMerge)
3731     {
3732         bMerge = FALSE;
3733     }
3734
3735     /* geminate recombination? If so, which flavor? */
3736     gemmode = 1;
3737     while (gemmode < gemNR && gmx_strcasecmp(gemType[0], gemType[gemmode]) != 0)
3738     {
3739         gemmode++;
3740     }
3741     if (gemmode == gemNR)
3742     {
3743         gmx_fatal(FARGS, "Invalid recombination type.");
3744     }
3745
3746     bGem = FALSE;
3747     for (i = 2; bGem == FALSE && i < gemNR; i++)
3748     {
3749         bGem = bGem || gemmode == i;
3750     }
3751
3752     if (bGem)
3753     {
3754         printf("Geminate recombination: %s\n", gemType[gemmode]);
3755         if (bContact)
3756         {
3757             if (gemmode != gemDD)
3758             {
3759                 printf("Turning off -contact option...\n");
3760                 bContact = FALSE;
3761             }
3762         }
3763         else
3764         {
3765             if (gemmode == gemDD)
3766             {
3767                 printf("Turning on -contact option...\n");
3768                 bContact = TRUE;
3769             }
3770         }
3771         if (bMerge)
3772         {
3773             if (gemmode == gemAA)
3774             {
3775                 printf("Turning off -merge option...\n");
3776                 bMerge = FALSE;
3777             }
3778         }
3779         else
3780         {
3781             if (gemmode != gemAA)
3782             {
3783                 printf("Turning on -merge option...\n");
3784                 bMerge = TRUE;
3785             }
3786         }
3787     }
3788
3789     /* process input */
3790     bSelected = FALSE;
3791     ccut      = cos(acut*DEG2RAD);
3792
3793     if (bContact)
3794     {
3795         if (bSelected)
3796         {
3797             gmx_fatal(FARGS, "Can not analyze selected contacts.");
3798         }
3799         if (!bDA)
3800         {
3801             gmx_fatal(FARGS, "Can not analyze contact between H and A: turn off -noda");
3802         }
3803     }
3804
3805     /* Initiate main data structure! */
3806     bHBmap = (opt2bSet("-ac", NFILE, fnm) ||
3807               opt2bSet("-life", NFILE, fnm) ||
3808               opt2bSet("-hbn", NFILE, fnm) ||
3809               opt2bSet("-hbm", NFILE, fnm) ||
3810               bGem);
3811
3812     if (opt2bSet("-nhbdist", NFILE, fnm))
3813     {
3814         const char *leg[MAXHH+1] = { "0 HBs", "1 HB", "2 HBs", "3 HBs", "Total" };
3815         fpnhb = xvgropen(opt2fn("-nhbdist", NFILE, fnm),
3816                          "Number of donor-H with N HBs", output_env_get_xvgr_tlabel(oenv), "N", oenv);
3817         xvgr_legend(fpnhb, asize(leg), leg, oenv);
3818     }
3819
3820     hb = mk_hbdata(bHBmap, opt2bSet("-dan", NFILE, fnm), bMerge || bContact, bGem, gemmode);
3821
3822     /* get topology */
3823     read_tpx_top(ftp2fn(efTPX, NFILE, fnm), &ir, box, &natoms, NULL, NULL, NULL, &top);
3824
3825     snew(grpnames, grNR);
3826     snew(index, grNR);
3827     snew(isize, grNR);
3828     /* Make Donor-Acceptor table */
3829     snew(datable, top.atoms.nr);
3830     gen_datable(index[0], isize[0], datable, top.atoms.nr);
3831
3832     if (bSelected)
3833     {
3834         /* analyze selected hydrogen bonds */
3835         printf("Select group with selected atoms:\n");
3836         get_index(&(top.atoms), opt2fn("-sel", NFILE, fnm),
3837                   1, &nsel, index, grpnames);
3838         if (nsel % 3)
3839         {
3840             gmx_fatal(FARGS, "Number of atoms in group '%s' not a multiple of 3\n"
3841                       "and therefore cannot contain triplets of "
3842                       "Donor-Hydrogen-Acceptor", grpnames[0]);
3843         }
3844         bTwo = FALSE;
3845
3846         for (i = 0; (i < nsel); i += 3)
3847         {
3848             int dd = index[0][i];
3849             int aa = index[0][i+2];
3850             /* int */ hh = index[0][i+1];
3851             add_dh (&hb->d, dd, hh, i, datable);
3852             add_acc(&hb->a, aa, i);
3853             /* Should this be here ? */
3854             snew(hb->d.dptr, top.atoms.nr);
3855             snew(hb->a.aptr, top.atoms.nr);
3856             add_hbond(hb, dd, aa, hh, gr0, gr0, 0, bMerge, 0, bContact, peri);
3857         }
3858         printf("Analyzing %d selected hydrogen bonds from '%s'\n",
3859                isize[0], grpnames[0]);
3860     }
3861     else
3862     {
3863         /* analyze all hydrogen bonds: get group(s) */
3864         printf("Specify 2 groups to analyze:\n");
3865         get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm),
3866                   2, isize, index, grpnames);
3867
3868         /* check if we have two identical or two non-overlapping groups */
3869         bTwo = isize[0] != isize[1];
3870         for (i = 0; (i < isize[0]) && !bTwo; i++)
3871         {
3872             bTwo = index[0][i] != index[1][i];
3873         }
3874         if (bTwo)
3875         {
3876             printf("Checking for overlap in atoms between %s and %s\n",
3877                    grpnames[0], grpnames[1]);
3878             for (i = 0; i < isize[1]; i++)
3879             {
3880                 if (ISINGRP(datable[index[1][i]]))
3881                 {
3882                     gmx_fatal(FARGS, "Partial overlap between groups '%s' and '%s'",
3883                               grpnames[0], grpnames[1]);
3884                 }
3885             }
3886             /*
3887                printf("Checking for overlap in atoms between %s and %s\n",
3888                grpnames[0],grpnames[1]);
3889                for (i=0; i<isize[0]; i++)
3890                for (j=0; j<isize[1]; j++)
3891                if (index[0][i] == index[1][j])
3892                gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
3893                grpnames[0],grpnames[1]);
3894              */
3895         }
3896         if (bTwo)
3897         {
3898             printf("Calculating %s "
3899                    "between %s (%d atoms) and %s (%d atoms)\n",
3900                    bContact ? "contacts" : "hydrogen bonds",
3901                    grpnames[0], isize[0], grpnames[1], isize[1]);
3902         }
3903         else
3904         {
3905             fprintf(stderr, "Calculating %s in %s (%d atoms)\n",
3906                     bContact ? "contacts" : "hydrogen bonds", grpnames[0], isize[0]);
3907         }
3908     }
3909     sfree(datable);
3910
3911     /* search donors and acceptors in groups */
3912     snew(datable, top.atoms.nr);
3913     for (i = 0; (i < grNR); i++)
3914     {
3915         if ( ((i == gr0) && !bSelected ) ||
3916              ((i == gr1) && bTwo ))
3917         {
3918             gen_datable(index[i], isize[i], datable, top.atoms.nr);
3919             if (bContact)
3920             {
3921                 search_acceptors(&top, isize[i], index[i], &hb->a, i,
3922                                  bNitAcc, TRUE, (bTwo && (i == gr0)) || !bTwo, datable);
3923                 search_donors   (&top, isize[i], index[i], &hb->d, i,
3924                                  TRUE, (bTwo && (i == gr1)) || !bTwo, datable);
3925             }
3926             else
3927             {
3928                 search_acceptors(&top, isize[i], index[i], &hb->a, i, bNitAcc, FALSE, TRUE, datable);
3929                 search_donors   (&top, isize[i], index[i], &hb->d, i, FALSE, TRUE, datable);
3930             }
3931             if (bTwo)
3932             {
3933                 clear_datable_grp(datable, top.atoms.nr);
3934             }
3935         }
3936     }
3937     sfree(datable);
3938     printf("Found %d donors and %d acceptors\n", hb->d.nrd, hb->a.nra);
3939     /*if (bSelected)
3940        snew(donors[gr0D], dons[gr0D].nrd);*/
3941
3942     if (bHBmap)
3943     {
3944         printf("Making hbmap structure...");
3945         /* Generate hbond data structure */
3946         mk_hbmap(hb);
3947         printf("done.\n");
3948     }
3949
3950 #ifdef HAVE_NN_LOOPS
3951     if (bNN)
3952     {
3953         mk_hbEmap(hb, 0);
3954     }
3955 #endif
3956
3957     if (bGem)
3958     {
3959         printf("Making per structure...");
3960         /* Generate hbond data structure */
3961         mk_per(hb);
3962         printf("done.\n");
3963     }
3964
3965     /* check input */
3966     bStop = FALSE;
3967     if (hb->d.nrd + hb->a.nra == 0)
3968     {
3969         printf("No Donors or Acceptors found\n");
3970         bStop = TRUE;
3971     }
3972     if (!bStop)
3973     {
3974         if (hb->d.nrd == 0)
3975         {
3976             printf("No Donors found\n");
3977             bStop = TRUE;
3978         }
3979         if (hb->a.nra == 0)
3980         {
3981             printf("No Acceptors found\n");
3982             bStop = TRUE;
3983         }
3984     }
3985     if (bStop)
3986     {
3987         gmx_fatal(FARGS, "Nothing to be done");
3988     }
3989
3990     shatom = 0;
3991     if (rshell > 0)
3992     {
3993         int      shisz;
3994         atom_id *shidx;
3995         char    *shgrpnm;
3996         /* get index group with atom for shell */
3997         do
3998         {
3999             printf("Select atom for shell (1 atom):\n");
4000             get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm),
4001                       1, &shisz, &shidx, &shgrpnm);
4002             if (shisz != 1)
4003             {
4004                 printf("group contains %d atoms, should be 1 (one)\n", shisz);
4005             }
4006         }
4007         while (shisz != 1);
4008         shatom = shidx[0];
4009         printf("Will calculate hydrogen bonds within a shell "
4010                "of %g nm around atom %i\n", rshell, shatom+1);
4011     }
4012
4013     /* Analyze trajectory */
4014     natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
4015     if (natoms > top.atoms.nr)
4016     {
4017         gmx_fatal(FARGS, "Topology (%d atoms) does not match trajectory (%d atoms)",
4018                   top.atoms.nr, natoms);
4019     }
4020
4021     bBox  = ir.ePBC != epbcNONE;
4022     grid  = init_grid(bBox, box, (rcut > r2cut) ? rcut : r2cut, ngrid);
4023     nabin = acut/abin;
4024     nrbin = rcut/rbin;
4025     snew(adist, nabin+1);
4026     snew(rdist, nrbin+1);
4027
4028     if (bGem && !bBox)
4029     {
4030         gmx_fatal(FARGS, "Can't do geminate recombination without periodic box.");
4031     }
4032
4033     bParallel = FALSE;
4034
4035 #ifndef GMX_OPENMP
4036 #define __ADIST adist
4037 #define __RDIST rdist
4038 #define __HBDATA hb
4039 #else /* GMX_OPENMP ================================================== \
4040        * Set up the OpenMP stuff,                                       |
4041        * like the number of threads and such                            |
4042        * Also start the parallel loop.                                  |
4043        */
4044 #define __ADIST p_adist[threadNr]
4045 #define __RDIST p_rdist[threadNr]
4046 #define __HBDATA p_hb[threadNr]
4047 #endif
4048     if (bOMP)
4049     {
4050         bParallel = !bSelected;
4051
4052         if (bParallel)
4053         {
4054             actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, gmx_omp_get_max_threads());
4055
4056             gmx_omp_set_num_threads(actual_nThreads);
4057             printf("Frame loop parallelized with OpenMP using %i threads.\n", actual_nThreads);
4058             fflush(stdout);
4059         }
4060         else
4061         {
4062             actual_nThreads = 1;
4063         }
4064
4065         snew(p_hb,    actual_nThreads);
4066         snew(p_adist, actual_nThreads);
4067         snew(p_rdist, actual_nThreads);
4068         for (i = 0; i < actual_nThreads; i++)
4069         {
4070             snew(p_hb[i], 1);
4071             snew(p_adist[i], nabin+1);
4072             snew(p_rdist[i], nrbin+1);
4073
4074             p_hb[i]->max_frames = 0;
4075             p_hb[i]->nhb        = NULL;
4076             p_hb[i]->ndist      = NULL;
4077             p_hb[i]->n_bound    = NULL;
4078             p_hb[i]->time       = NULL;
4079             p_hb[i]->nhx        = NULL;
4080
4081             p_hb[i]->bHBmap     = hb->bHBmap;
4082             p_hb[i]->bDAnr      = hb->bDAnr;
4083             p_hb[i]->bGem       = hb->bGem;
4084             p_hb[i]->wordlen    = hb->wordlen;
4085             p_hb[i]->nframes    = hb->nframes;
4086             p_hb[i]->maxhydro   = hb->maxhydro;
4087             p_hb[i]->danr       = hb->danr;
4088             p_hb[i]->d          = hb->d;
4089             p_hb[i]->a          = hb->a;
4090             p_hb[i]->hbmap      = hb->hbmap;
4091             p_hb[i]->time       = hb->time; /* This may need re-syncing at every frame. */
4092             p_hb[i]->per        = hb->per;
4093
4094 #ifdef HAVE_NN_LOOPS
4095             p_hb[i]->hbE = hb->hbE;
4096 #endif
4097
4098             p_hb[i]->nrhb   = 0;
4099             p_hb[i]->nrdist = 0;
4100         }
4101     }
4102
4103     /* Make a thread pool here,
4104      * instead of forking anew at every frame. */
4105
4106 #pragma omp parallel \
4107     firstprivate(i) \
4108     private(j, h, ii, jj, hh, E, \
4109     xi, yi, zi, xj, yj, zj, threadNr, \
4110     dist, ang, peri, icell, jcell, \
4111     grp, ogrp, ai, aj, xjj, yjj, zjj, \
4112     xk, yk, zk, ihb, id,  resdist, \
4113     xkk, ykk, zkk, kcell, ak, k, bTric, \
4114     bEdge_xjj, bEdge_yjj) \
4115     default(shared)
4116     {    /* Start of parallel region */
4117         threadNr = gmx_omp_get_thread_num();
4118
4119         do
4120         {
4121
4122             bTric = bBox && TRICLINIC(box);
4123
4124             if (bOMP)
4125             {
4126                 sync_hbdata(p_hb[threadNr], nframes);
4127             }
4128 #pragma omp single
4129             {
4130                 build_grid(hb, x, x[shatom], bBox, box, hbox, (rcut > r2cut) ? rcut : r2cut,
4131                            rshell, ngrid, grid);
4132                 reset_nhbonds(&(hb->d));
4133
4134                 if (debug && bDebug)
4135                 {
4136                     dump_grid(debug, ngrid, grid);
4137                 }
4138
4139                 add_frames(hb, nframes);
4140                 init_hbframe(hb, nframes, output_env_conv_time(oenv, t));
4141
4142                 if (hb->bDAnr)
4143                 {
4144                     count_da_grid(ngrid, grid, hb->danr[nframes]);
4145                 }
4146             } /* omp single */
4147
4148             if (bOMP)
4149             {
4150                 p_hb[threadNr]->time = hb->time; /* This pointer may have changed. */
4151             }
4152
4153             if (bNN)
4154             {
4155 #ifdef HAVE_NN_LOOPS /* Unlock this feature when testing */
4156                 /* Loop over all atom pairs and estimate interaction energy */
4157
4158 #pragma omp single
4159                 {
4160                     addFramesNN(hb, nframes);
4161                 }
4162
4163 #pragma omp barrier
4164 #pragma omp for schedule(dynamic)
4165                 for (i = 0; i < hb->d.nrd; i++)
4166                 {
4167                     for (j = 0; j < hb->a.nra; j++)
4168                     {
4169                         for (h = 0;
4170                              h < (bContact ? 1 : hb->d.nhydro[i]);
4171                              h++)
4172                         {
4173                             if (i == hb->d.nrd || j == hb->a.nra)
4174                             {
4175                                 gmx_fatal(FARGS, "out of bounds");
4176                             }
4177
4178                             /* Get the real atom ids */
4179                             ii = hb->d.don[i];
4180                             jj = hb->a.acc[j];
4181                             hh = hb->d.hydro[i][h];
4182
4183                             /* Estimate the energy from the geometry */
4184                             E = calcHbEnergy(ii, jj, hh, x, NN, box, hbox, &(hb->d));
4185                             /* Store the energy */
4186                             storeHbEnergy(hb, i, j, h, E, nframes);
4187                         }
4188                     }
4189                 }
4190 #endif        /* HAVE_NN_LOOPS */
4191             } /* if (bNN)*/
4192             else
4193             {
4194                 if (bSelected)
4195                 {
4196
4197 #pragma omp single
4198                     {
4199                         /* Do not parallelize this just yet. */
4200                         /* int ii; */
4201                         for (ii = 0; (ii < nsel); ii++)
4202                         {
4203                             int dd = index[0][i];
4204                             int aa = index[0][i+2];
4205                             /* int */ hh = index[0][i+1];
4206                             ihb          = is_hbond(hb, ii, ii, dd, aa, rcut, r2cut, ccut, x, bBox, box,
4207                                                     hbox, &dist, &ang, bDA, &h, bContact, bMerge, &peri);
4208
4209                             if (ihb)
4210                             {
4211                                 /* add to index if not already there */
4212                                 /* Add a hbond */
4213                                 add_hbond(hb, dd, aa, hh, ii, ii, nframes, bMerge, ihb, bContact, peri);
4214                             }
4215                         }
4216                     } /* omp single */
4217                 }     /* if (bSelected) */
4218                 else
4219                 {
4220
4221 #pragma omp single
4222                     {
4223                         if (bGem)
4224                         {
4225                             calcBoxProjection(box, hb->per->P);
4226                         }
4227
4228                         /* loop over all gridcells (xi,yi,zi)      */
4229                         /* Removed confusing macro, DvdS 27/12/98  */
4230
4231                     }
4232                     /* The outer grid loop will have to do for now. */
4233 #pragma omp for schedule(dynamic)
4234                     for (xi = 0; xi < ngrid[XX]; xi++)
4235                     {
4236                         for (yi = 0; (yi < ngrid[YY]); yi++)
4237                         {
4238                             for (zi = 0; (zi < ngrid[ZZ]); zi++)
4239                             {
4240
4241                                 /* loop over donor groups gr0 (always) and gr1 (if necessary) */
4242                                 for (grp = gr0; (grp <= (bTwo ? gr1 : gr0)); grp++)
4243                                 {
4244                                     icell = &(grid[zi][yi][xi].d[grp]);
4245
4246                                     if (bTwo)
4247                                     {
4248                                         ogrp = 1-grp;
4249                                     }
4250                                     else
4251                                     {
4252                                         ogrp = grp;
4253                                     }
4254
4255                                     /* loop over all hydrogen atoms from group (grp)
4256                                      * in this gridcell (icell)
4257                                      */
4258                                     for (ai = 0; (ai < icell->nr); ai++)
4259                                     {
4260                                         i  = icell->atoms[ai];
4261
4262                                         /* loop over all adjacent gridcells (xj,yj,zj) */
4263                                         for (zjj = grid_loop_begin(ngrid[ZZ], zi, bTric, FALSE);
4264                                              zjj <= grid_loop_end(ngrid[ZZ], zi, bTric, FALSE);
4265                                              zjj++)
4266                                         {
4267                                             zj        = grid_mod(zjj, ngrid[ZZ]);
4268                                             bEdge_yjj = (zj == 0) || (zj == ngrid[ZZ] - 1);
4269                                             for (yjj = grid_loop_begin(ngrid[YY], yi, bTric, bEdge_yjj);
4270                                                  yjj <= grid_loop_end(ngrid[YY], yi, bTric, bEdge_yjj);
4271                                                  yjj++)
4272                                             {
4273                                                 yj        = grid_mod(yjj, ngrid[YY]);
4274                                                 bEdge_xjj =
4275                                                     (yj == 0) || (yj == ngrid[YY] - 1) ||
4276                                                     (zj == 0) || (zj == ngrid[ZZ] - 1);
4277                                                 for (xjj = grid_loop_begin(ngrid[XX], xi, bTric, bEdge_xjj);
4278                                                      xjj <= grid_loop_end(ngrid[XX], xi, bTric, bEdge_xjj);
4279                                                      xjj++)
4280                                                 {
4281                                                     xj    = grid_mod(xjj, ngrid[XX]);
4282                                                     jcell = &(grid[zj][yj][xj].a[ogrp]);
4283                                                     /* loop over acceptor atoms from other group (ogrp)
4284                                                      * in this adjacent gridcell (jcell)
4285                                                      */
4286                                                     for (aj = 0; (aj < jcell->nr); aj++)
4287                                                     {
4288                                                         j = jcell->atoms[aj];
4289
4290                                                         /* check if this once was a h-bond */
4291                                                         peri = -1;
4292                                                         ihb  = is_hbond(__HBDATA, grp, ogrp, i, j, rcut, r2cut, ccut, x, bBox, box,
4293                                                                         hbox, &dist, &ang, bDA, &h, bContact, bMerge, &peri);
4294
4295                                                         if (ihb)
4296                                                         {
4297                                                             /* add to index if not already there */
4298                                                             /* Add a hbond */
4299                                                             add_hbond(__HBDATA, i, j, h, grp, ogrp, nframes, bMerge, ihb, bContact, peri);
4300
4301                                                             /* make angle and distance distributions */
4302                                                             if (ihb == hbHB && !bContact)
4303                                                             {
4304                                                                 if (dist > rcut)
4305                                                                 {
4306                                                                     gmx_fatal(FARGS, "distance is higher than what is allowed for an hbond: %f", dist);
4307                                                                 }
4308                                                                 ang *= RAD2DEG;
4309                                                                 __ADIST[(int)( ang/abin)]++;
4310                                                                 __RDIST[(int)(dist/rbin)]++;
4311                                                                 if (!bTwo)
4312                                                                 {
4313                                                                     int id, ia;
4314                                                                     if ((id = donor_index(&hb->d, grp, i)) == NOTSET)
4315                                                                     {
4316                                                                         gmx_fatal(FARGS, "Invalid donor %d", i);
4317                                                                     }
4318                                                                     if ((ia = acceptor_index(&hb->a, ogrp, j)) == NOTSET)
4319                                                                     {
4320                                                                         gmx_fatal(FARGS, "Invalid acceptor %d", j);
4321                                                                     }
4322                                                                     resdist = abs(top.atoms.atom[i].resind-
4323                                                                                   top.atoms.atom[j].resind);
4324                                                                     if (resdist >= max_hx)
4325                                                                     {
4326                                                                         resdist = max_hx-1;
4327                                                                     }
4328                                                                     __HBDATA->nhx[nframes][resdist]++;
4329                                                                 }
4330                                                             }
4331
4332                                                         }
4333                                                     } /* for aj  */
4334                                                 }     /* for xjj */
4335                                             }         /* for yjj */
4336                                         }             /* for zjj */
4337                                     }                 /* for ai  */
4338                                 }                     /* for grp */
4339                             }                         /* for xi,yi,zi */
4340                         }
4341                     }
4342                 } /* if (bSelected) {...} else */
4343
4344
4345                 /* Better wait for all threads to finnish using x[] before updating it. */
4346                 k = nframes;
4347 #pragma omp barrier
4348 #pragma omp critical
4349                 {
4350                     /* Sum up histograms and counts from p_hb[] into hb */
4351                     if (bOMP)
4352                     {
4353                         hb->nhb[k]   += p_hb[threadNr]->nhb[k];
4354                         hb->ndist[k] += p_hb[threadNr]->ndist[k];
4355                         for (j = 0; j < max_hx; j++)
4356                         {
4357                             hb->nhx[k][j]  += p_hb[threadNr]->nhx[k][j];
4358                         }
4359                     }
4360                 }
4361
4362                 /* Here are a handful of single constructs
4363                  * to share the workload a bit. The most
4364                  * important one is of course the last one,
4365                  * where there's a potential bottleneck in form
4366                  * of slow I/O.                    */
4367 #pragma omp barrier
4368 #pragma omp single
4369                 {
4370                     if (hb != NULL)
4371                     {
4372                         analyse_donor_props(opt2fn_null("-don", NFILE, fnm), hb, k, t, oenv);
4373                     }
4374                 }
4375
4376 #pragma omp single
4377                 {
4378                     if (fpnhb)
4379                     {
4380                         do_nhb_dist(fpnhb, hb, t);
4381                     }
4382                 }
4383             } /* if (bNN) {...} else  +   */
4384
4385 #pragma omp single
4386             {
4387                 trrStatus = (read_next_x(oenv, status, &t, x, box));
4388                 nframes++;
4389             }
4390
4391 #pragma omp barrier
4392         }
4393         while (trrStatus);
4394
4395         if (bOMP)
4396         {
4397 #pragma omp critical
4398             {
4399                 hb->nrhb   += p_hb[threadNr]->nrhb;
4400                 hb->nrdist += p_hb[threadNr]->nrdist;
4401             }
4402             /* Free parallel datastructures */
4403             sfree(p_hb[threadNr]->nhb);
4404             sfree(p_hb[threadNr]->ndist);
4405             sfree(p_hb[threadNr]->nhx);
4406
4407 #pragma omp for
4408             for (i = 0; i < nabin; i++)
4409             {
4410                 for (j = 0; j < actual_nThreads; j++)
4411                 {
4412
4413                     adist[i] += p_adist[j][i];
4414                 }
4415             }
4416 #pragma omp for
4417             for (i = 0; i <= nrbin; i++)
4418             {
4419                 for (j = 0; j < actual_nThreads; j++)
4420                 {
4421                     rdist[i] += p_rdist[j][i];
4422                 }
4423             }
4424
4425             sfree(p_adist[threadNr]);
4426             sfree(p_rdist[threadNr]);
4427         }
4428     } /* End of parallel region */
4429     if (bOMP)
4430     {
4431         sfree(p_adist);
4432         sfree(p_rdist);
4433     }
4434
4435     if (nframes < 2 && (opt2bSet("-ac", NFILE, fnm) || opt2bSet("-life", NFILE, fnm)))
4436     {
4437         gmx_fatal(FARGS, "Cannot calculate autocorrelation of life times with less than two frames");
4438     }
4439
4440     free_grid(ngrid, &grid);
4441
4442     close_trj(status);
4443     if (fpnhb)
4444     {
4445         gmx_ffclose(fpnhb);
4446     }
4447
4448     /* Compute maximum possible number of different hbonds */
4449     if (maxnhb > 0)
4450     {
4451         max_nhb = maxnhb;
4452     }
4453     else
4454     {
4455         max_nhb = 0.5*(hb->d.nrd*hb->a.nra);
4456     }
4457     /* Added support for -contact below.
4458      * - Erik Marklund, May 29-31, 2006 */
4459     /* Changed contact code.
4460      * - Erik Marklund, June 29, 2006 */
4461     if (bHBmap && !bNN)
4462     {
4463         if (hb->nrhb == 0)
4464         {
4465             printf("No %s found!!\n", bContact ? "contacts" : "hydrogen bonds");
4466         }
4467         else
4468         {
4469             printf("Found %d different %s in trajectory\n"
4470                    "Found %d different atom-pairs within %s distance\n",
4471                    hb->nrhb, bContact ? "contacts" : "hydrogen bonds",
4472                    hb->nrdist, (r2cut > 0) ? "second cut-off" : "hydrogen bonding");
4473
4474             /*Control the pHist.*/
4475
4476             if (bMerge)
4477             {
4478                 merge_hb(hb, bTwo, bContact);
4479             }
4480
4481             if (opt2bSet("-hbn", NFILE, fnm))
4482             {
4483                 dump_hbmap(hb, NFILE, fnm, bTwo, bContact, isize, index, grpnames, &top.atoms);
4484             }
4485
4486             /* Moved the call to merge_hb() to a line BEFORE dump_hbmap
4487              * to make the -hbn and -hmb output match eachother.
4488              * - Erik Marklund, May 30, 2006 */
4489         }
4490     }
4491     /* Print out number of hbonds and distances */
4492     aver_nhb  = 0;
4493     aver_dist = 0;
4494     fp        = xvgropen(opt2fn("-num", NFILE, fnm), bContact ? "Contacts" :
4495                          "Hydrogen Bonds", output_env_get_xvgr_tlabel(oenv), "Number", oenv);
4496     snew(leg, 2);
4497     snew(leg[0], STRLEN);
4498     snew(leg[1], STRLEN);
4499     sprintf(leg[0], "%s", bContact ? "Contacts" : "Hydrogen bonds");
4500     sprintf(leg[1], "Pairs within %g nm", (r2cut > 0) ? r2cut : rcut);
4501     xvgr_legend(fp, 2, (const char**)leg, oenv);
4502     sfree(leg[1]);
4503     sfree(leg[0]);
4504     sfree(leg);
4505     for (i = 0; (i < nframes); i++)
4506     {
4507         fprintf(fp, "%10g  %10d  %10d\n", hb->time[i], hb->nhb[i], hb->ndist[i]);
4508         aver_nhb  += hb->nhb[i];
4509         aver_dist += hb->ndist[i];
4510     }
4511     gmx_ffclose(fp);
4512     aver_nhb  /= nframes;
4513     aver_dist /= nframes;
4514     /* Print HB distance distribution */
4515     if (opt2bSet("-dist", NFILE, fnm))
4516     {
4517         long sum;
4518
4519         sum = 0;
4520         for (i = 0; i < nrbin; i++)
4521         {
4522             sum += rdist[i];
4523         }
4524
4525         fp = xvgropen(opt2fn("-dist", NFILE, fnm),
4526                       "Hydrogen Bond Distribution",
4527                       bDA ?
4528                       "Donor - Acceptor Distance (nm)" :
4529                       "Hydrogen - Acceptor Distance (nm)", "", oenv);
4530         for (i = 0; i < nrbin; i++)
4531         {
4532             fprintf(fp, "%10g %10g\n", (i+0.5)*rbin, rdist[i]/(rbin*(real)sum));
4533         }
4534         gmx_ffclose(fp);
4535     }
4536
4537     /* Print HB angle distribution */
4538     if (opt2bSet("-ang", NFILE, fnm))
4539     {
4540         long sum;
4541
4542         sum = 0;
4543         for (i = 0; i < nabin; i++)
4544         {
4545             sum += adist[i];
4546         }
4547
4548         fp = xvgropen(opt2fn("-ang", NFILE, fnm),
4549                       "Hydrogen Bond Distribution",
4550                       "Hydrogen - Donor - Acceptor Angle (\\SO\\N)", "", oenv);
4551         for (i = 0; i < nabin; i++)
4552         {
4553             fprintf(fp, "%10g %10g\n", (i+0.5)*abin, adist[i]/(abin*(real)sum));
4554         }
4555         gmx_ffclose(fp);
4556     }
4557
4558     /* Print HB in alpha-helix */
4559     if (opt2bSet("-hx", NFILE, fnm))
4560     {
4561         fp = xvgropen(opt2fn("-hx", NFILE, fnm),
4562                       "Hydrogen Bonds", output_env_get_xvgr_tlabel(oenv), "Count", oenv);
4563         xvgr_legend(fp, NRHXTYPES, hxtypenames, oenv);
4564         for (i = 0; i < nframes; i++)
4565         {
4566             fprintf(fp, "%10g", hb->time[i]);
4567             for (j = 0; j < max_hx; j++)
4568             {
4569                 fprintf(fp, " %6d", hb->nhx[i][j]);
4570             }
4571             fprintf(fp, "\n");
4572         }
4573         gmx_ffclose(fp);
4574     }
4575     if (!bNN)
4576     {
4577         printf("Average number of %s per timeframe %.3f out of %g possible\n",
4578                bContact ? "contacts" : "hbonds",
4579                bContact ? aver_dist : aver_nhb, max_nhb);
4580     }
4581
4582     /* Do Autocorrelation etc. */
4583     if (hb->bHBmap)
4584     {
4585         /*
4586            Added support for -contact in ac and hbm calculations below.
4587            - Erik Marklund, May 29, 2006
4588          */
4589         ivec itmp;
4590         rvec rtmp;
4591         if (opt2bSet("-ac", NFILE, fnm) || opt2bSet("-life", NFILE, fnm))
4592         {
4593             please_cite(stdout, "Spoel2006b");
4594         }
4595         if (opt2bSet("-ac", NFILE, fnm))
4596         {
4597             char *gemstring = NULL;
4598
4599             if (bGem || bNN)
4600             {
4601                 params = init_gemParams(rcut, D, hb->time, hb->nframes/2, nFitPoints, fit_start, fit_end,
4602                                         gemBallistic, nBalExp);
4603                 if (params == NULL)
4604                 {
4605                     gmx_fatal(FARGS, "Could not initiate t_gemParams params.");
4606                 }
4607             }
4608             gemstring = gmx_strdup(gemType[hb->per->gemtype]);
4609             do_hbac(opt2fn("-ac", NFILE, fnm), hb, nDump,
4610                     bMerge, bContact, fit_start, temp, r2cut > 0, smooth_tail_start, oenv,
4611                     gemstring, nThreads, NN, bBallistic, bGemFit);
4612         }
4613         if (opt2bSet("-life", NFILE, fnm))
4614         {
4615             do_hblife(opt2fn("-life", NFILE, fnm), hb, bMerge, bContact, oenv);
4616         }
4617         if (opt2bSet("-hbm", NFILE, fnm))
4618         {
4619             t_matrix mat;
4620             int      id, ia, hh, x, y;
4621             mat.flags = mat.y0 = 0;
4622
4623             if ((nframes > 0) && (hb->nrhb > 0))
4624             {
4625                 mat.nx = nframes;
4626                 mat.ny = hb->nrhb;
4627
4628                 snew(mat.matrix, mat.nx);
4629                 for (x = 0; (x < mat.nx); x++)
4630                 {
4631                     snew(mat.matrix[x], mat.ny);
4632                 }
4633                 y = 0;
4634                 for (id = 0; (id < hb->d.nrd); id++)
4635                 {
4636                     for (ia = 0; (ia < hb->a.nra); ia++)
4637                     {
4638                         for (hh = 0; (hh < hb->maxhydro); hh++)
4639                         {
4640                             if (hb->hbmap[id][ia])
4641                             {
4642                                 if (ISHB(hb->hbmap[id][ia]->history[hh]))
4643                                 {
4644                                     /* Changed '<' into '<=' in the for-statement below.
4645                                      * It fixed the previously undiscovered bug that caused
4646                                      * the last occurance of an hbond/contact to not be
4647                                      * set in mat.matrix. Have a look at any old -hbm-output
4648                                      * and you will notice that the last column is allways empty.
4649                                      * - Erik Marklund May 30, 2006
4650                                      */
4651                                     for (x = 0; (x <= hb->hbmap[id][ia]->nframes); x++)
4652                                     {
4653                                         int nn0 = hb->hbmap[id][ia]->n0;
4654                                         range_check(y, 0, mat.ny);
4655                                         mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh], x);
4656                                     }
4657                                     y++;
4658                                 }
4659                             }
4660                         }
4661                     }
4662                 }
4663                 mat.axis_x = hb->time;
4664                 snew(mat.axis_y, mat.ny);
4665                 for (j = 0; j < mat.ny; j++)
4666                 {
4667                     mat.axis_y[j] = j;
4668                 }
4669                 sprintf(mat.title, bContact ? "Contact Existence Map" :
4670                         "Hydrogen Bond Existence Map");
4671                 sprintf(mat.legend, bContact ? "Contacts" : "Hydrogen Bonds");
4672                 sprintf(mat.label_x, "%s", output_env_get_xvgr_tlabel(oenv));
4673                 sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
4674                 mat.bDiscrete = TRUE;
4675                 mat.nmap      = 2;
4676                 snew(mat.map, mat.nmap);
4677                 for (i = 0; i < mat.nmap; i++)
4678                 {
4679                     mat.map[i].code.c1 = hbmap[i];
4680                     mat.map[i].desc    = hbdesc[i];
4681                     mat.map[i].rgb     = hbrgb[i];
4682                 }
4683                 fp = opt2FILE("-hbm", NFILE, fnm, "w");
4684                 write_xpm_m(fp, mat);
4685                 gmx_ffclose(fp);
4686                 for (x = 0; x < mat.nx; x++)
4687                 {
4688                     sfree(mat.matrix[x]);
4689                 }
4690                 sfree(mat.axis_y);
4691                 sfree(mat.matrix);
4692                 sfree(mat.map);
4693             }
4694             else
4695             {
4696                 fprintf(stderr, "No hydrogen bonds/contacts found. No hydrogen bond map will be printed.\n");
4697             }
4698         }
4699     }
4700
4701     if (bGem)
4702     {
4703         fprintf(stderr, "There were %i periodic shifts\n", hb->per->nper);
4704         fprintf(stderr, "Freeing pHist for all donors...\n");
4705         for (i = 0; i < hb->d.nrd; i++)
4706         {
4707             fprintf(stderr, "\r%i", i);
4708             if (hb->per->pHist[i] != NULL)
4709             {
4710                 for (j = 0; j < hb->a.nra; j++)
4711                 {
4712                     clearPshift(&(hb->per->pHist[i][j]));
4713                 }
4714                 sfree(hb->per->pHist[i]);
4715             }
4716         }
4717         sfree(hb->per->pHist);
4718         sfree(hb->per->p2i);
4719         sfree(hb->per);
4720         fprintf(stderr, "...done.\n");
4721     }
4722
4723 #ifdef HAVE_NN_LOOPS
4724     if (bNN)
4725     {
4726         free_hbEmap(hb);
4727     }
4728 #endif
4729
4730     if (hb->bDAnr)
4731     {
4732         int    i, j, nleg;
4733         char **legnames;
4734         char   buf[STRLEN];
4735
4736 #define USE_THIS_GROUP(j) ( (j == gr0) || (bTwo && (j == gr1)) )
4737
4738         fp = xvgropen(opt2fn("-dan", NFILE, fnm),
4739                       "Donors and Acceptors", output_env_get_xvgr_tlabel(oenv), "Count", oenv);
4740         nleg = (bTwo ? 2 : 1)*2;
4741         snew(legnames, nleg);
4742         i = 0;
4743         for (j = 0; j < grNR; j++)
4744         {
4745             if (USE_THIS_GROUP(j) )
4746             {
4747                 sprintf(buf, "Donors %s", grpnames[j]);
4748                 legnames[i++] = gmx_strdup(buf);
4749                 sprintf(buf, "Acceptors %s", grpnames[j]);
4750                 legnames[i++] = gmx_strdup(buf);
4751             }
4752         }
4753         if (i != nleg)
4754         {
4755             gmx_incons("number of legend entries");
4756         }
4757         xvgr_legend(fp, nleg, (const char**)legnames, oenv);
4758         for (i = 0; i < nframes; i++)
4759         {
4760             fprintf(fp, "%10g", hb->time[i]);
4761             for (j = 0; (j < grNR); j++)
4762             {
4763                 if (USE_THIS_GROUP(j) )
4764                 {
4765                     fprintf(fp, " %6d", hb->danr[i][j]);
4766                 }
4767             }
4768             fprintf(fp, "\n");
4769         }
4770         gmx_ffclose(fp);
4771     }
4772
4773     return 0;
4774 }