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