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