Apply clang-tidy11 to correlationfunctions
[alexxy/gromacs.git] / src / gromacs / correlationfunctions / autocorr.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
7  * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
8  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9  * and including many others, as listed in the AUTHORS file in the
10  * top-level source directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 /*! \internal \file
39  * \brief
40  * Implements function to compute many autocorrelation functions
41  *
42  * \author David van der Spoel <david.vanderspoel@icm.uu.se>
43  * \ingroup module_correlationfunctions
44  */
45 #include "gmxpre.h"
46
47 #include "autocorr.h"
48
49 #include <cmath>
50 #include <cstdio>
51 #include <cstring>
52
53 #include <algorithm>
54
55 #include "gromacs/correlationfunctions/expfit.h"
56 #include "gromacs/correlationfunctions/integrate.h"
57 #include "gromacs/correlationfunctions/manyautocorrelation.h"
58 #include "gromacs/correlationfunctions/polynomials.h"
59 #include "gromacs/fileio/xvgr.h"
60 #include "gromacs/math/functions.h"
61 #include "gromacs/math/vec.h"
62 #include "gromacs/utility/arraysize.h"
63 #include "gromacs/utility/fatalerror.h"
64 #include "gromacs/utility/futil.h"
65 #include "gromacs/utility/real.h"
66 #include "gromacs/utility/smalloc.h"
67 #include "gromacs/utility/strconvert.h"
68
69 /*! \brief Shortcut macro to select modes. */
70 #define MODE(x) ((mode & (x)) == (x))
71
72 typedef struct
73 {
74     unsigned long mode;
75     int           nrestart, nout, P, fitfn;
76     gmx_bool      bFour, bNormalize;
77     real          tbeginfit, tendfit;
78 } t_acf;
79
80 /*! \brief Global variable set true if initialization routines are called. */
81 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
82 static gmx_bool bACFinit = FALSE;
83
84 /*! \brief Data structure for storing command line variables. */
85 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
86 static t_acf acf;
87
88 enum
89 {
90     enNorm,
91     enCos,
92     enSin
93 };
94
95 /*! \brief Routine to compute ACF using FFT. */
96 static void low_do_four_core(int nframes, real c1[], real cfour[], int nCos)
97 {
98     int                            i = 0;
99     std::vector<std::vector<real>> data;
100     data.resize(1);
101     data[0].resize(nframes, 0);
102     switch (nCos)
103     {
104         case enNorm:
105             for (i = 0; (i < nframes); i++)
106             {
107                 data[0][i] = c1[i];
108             }
109             break;
110         case enCos:
111             for (i = 0; (i < nframes); i++)
112             {
113                 data[0][i] = cos(c1[i]);
114             }
115             break;
116         case enSin:
117             for (i = 0; (i < nframes); i++)
118             {
119                 data[0][i] = sin(c1[i]);
120             }
121             break;
122         default: gmx_fatal(FARGS, "nCos = %d, %s %d", nCos, __FILE__, __LINE__);
123     }
124
125     many_auto_correl(&data);
126     for (i = 0; (i < nframes); i++)
127     {
128         cfour[i] = data[0][i];
129     }
130 }
131
132 /*! \brief Routine to comput ACF without FFT. */
133 static void do_ac_core(int nframes, int nout, real corr[], real c1[], int nrestart, unsigned long mode)
134 {
135     int  j, k, j3, jk3, m, n;
136     real ccc, cth;
137     rvec xj, xk;
138
139     if (nrestart < 1)
140     {
141         printf("WARNING: setting number of restarts to 1\n");
142         nrestart = 1;
143     }
144     if (debug)
145     {
146         fprintf(debug, "Starting do_ac_core: nframes=%d, nout=%d, nrestart=%d,mode=%lu\n", nframes, nout, nrestart, mode);
147     }
148
149     for (j = 0; (j < nout); j++)
150     {
151         corr[j] = 0;
152     }
153
154     /* Loop over starting points. */
155     for (j = 0; (j < nframes); j += nrestart)
156     {
157         j3 = DIM * j;
158
159         /* Loop over the correlation length for this starting point */
160         for (k = 0; (k < nout) && (j + k < nframes); k++)
161         {
162             jk3 = DIM * (j + k);
163
164             /* Switch over possible ACF types.
165              * It might be more efficient to put the loops inside the switch,
166              * but this is more clear, and save development time!
167              */
168             if (MODE(eacNormal))
169             {
170                 corr[k] += c1[j] * c1[j + k];
171             }
172             else if (MODE(eacCos))
173             {
174                 /* Compute the cos (phi(t)-phi(t+dt)) */
175                 corr[k] += std::cos(c1[j] - c1[j + k]);
176             }
177             else if (MODE(eacIden))
178             {
179                 /* Check equality (phi(t)==phi(t+dt)) */
180                 corr[k] += (c1[j] == c1[j + k]) ? 1 : 0;
181             }
182             else if (MODE(eacP1) || MODE(eacP2) || MODE(eacP3))
183             {
184                 unsigned int mmm;
185
186                 for (m = 0; (m < DIM); m++)
187                 {
188                     xj[m] = c1[j3 + m];
189                     xk[m] = c1[jk3 + m];
190                 }
191                 cth = cos_angle(xj, xk);
192
193                 if (cth - 1.0 > 1.0e-15)
194                 {
195                     printf("j: %d, k: %d, xj:(%g,%g,%g), xk:(%g,%g,%g)\n",
196                            j,
197                            k,
198                            xj[XX],
199                            xj[YY],
200                            xj[ZZ],
201                            xk[XX],
202                            xk[YY],
203                            xk[ZZ]);
204                 }
205                 mmm = 1;
206                 if (MODE(eacP2))
207                 {
208                     mmm = 2;
209                 }
210                 else if (MODE(eacP3))
211                 {
212                     mmm = 3;
213                 }
214                 corr[k] += LegendreP(cth, mmm); /* 1.5*cth*cth-0.5; */
215             }
216             else if (MODE(eacRcross))
217             {
218                 rvec xj, xk, rr;
219                 for (m = 0; (m < DIM); m++)
220                 {
221                     xj[m] = c1[j3 + m];
222                     xk[m] = c1[jk3 + m];
223                 }
224                 cprod(xj, xk, rr);
225
226                 corr[k] += iprod(rr, rr);
227             }
228             else if (MODE(eacVector))
229             {
230                 for (m = 0; (m < DIM); m++)
231                 {
232                     xj[m] = c1[j3 + m];
233                     xk[m] = c1[jk3 + m];
234                 }
235                 ccc = iprod(xj, xk);
236
237                 corr[k] += ccc;
238             }
239             else
240             {
241                 gmx_fatal(FARGS, "\nInvalid mode (%lu) in do_ac_core", mode);
242             }
243         }
244     }
245     /* Correct for the number of points and copy results to the data array */
246     for (j = 0; (j < nout); j++)
247     {
248         n     = (nframes - j + (nrestart - 1)) / nrestart;
249         c1[j] = corr[j] / n;
250     }
251 }
252
253 /*! \brief Routine to normalize ACF, dividing by corr[0]. */
254 static void normalize_acf(int nout, real corr[])
255 {
256     int    j;
257     double c0;
258
259     if (debug)
260     {
261         fprintf(debug, "Before normalization\n");
262         for (j = 0; (j < nout); j++)
263         {
264             fprintf(debug, "%5d  %10f\n", j, corr[j]);
265         }
266     }
267
268     /* Normalisation makes that c[0] = 1.0 and that other points are scaled
269      * accordingly.
270      */
271     if (fabs(corr[0]) < 1e-5)
272     {
273         c0 = 1.0;
274     }
275     else
276     {
277         c0 = 1.0 / corr[0];
278     }
279     for (j = 0; (j < nout); j++)
280     {
281         corr[j] *= c0;
282     }
283
284     if (debug)
285     {
286         fprintf(debug, "After normalization\n");
287         for (j = 0; (j < nout); j++)
288         {
289             fprintf(debug, "%5d  %10f\n", j, corr[j]);
290         }
291     }
292 }
293
294 /*! \brief Routine that averages ACFs. */
295 static void average_acf(gmx_bool bVerbose, int n, int nitem, real** c1)
296 {
297     real c0;
298     int  i, j;
299
300     if (bVerbose)
301     {
302         printf("Averaging correlation functions\n");
303     }
304
305     for (j = 0; (j < n); j++)
306     {
307         c0 = 0;
308         for (i = 0; (i < nitem); i++)
309         {
310             c0 += c1[i][j];
311         }
312         c1[0][j] = c0 / nitem;
313     }
314 }
315
316 /*! \brief Normalize ACFs. */
317 static void norm_and_scale_vectors(int nframes, real c1[], real scale)
318 {
319     int   j, m;
320     real* rij;
321
322     for (j = 0; (j < nframes); j++)
323     {
324         rij = &(c1[j * DIM]);
325         unitv(rij, rij);
326         for (m = 0; (m < DIM); m++)
327         {
328             rij[m] *= scale;
329         }
330     }
331 }
332
333 /*! \brief Debugging */
334 static void dump_tmp(char* s, int n, real c[])
335 {
336     FILE* fp;
337     int   i;
338
339     fp = gmx_ffopen(s, "w");
340     for (i = 0; (i < n); i++)
341     {
342         fprintf(fp, "%10d  %10g\n", i, c[i]);
343     }
344     gmx_ffclose(fp);
345 }
346
347 /*! \brief High level ACF routine. */
348 static void do_four_core(unsigned long mode, int nframes, real c1[], real csum[], real ctmp[])
349 {
350     real* cfour;
351     char  buf[32];
352     real  fac;
353     int   j, m, m1;
354
355     snew(cfour, nframes);
356
357     if (MODE(eacNormal))
358     {
359         /********************************************
360          *  N O R M A L
361          ********************************************/
362         low_do_four_core(nframes, c1, csum, enNorm);
363     }
364     else if (MODE(eacCos))
365     {
366         /***************************************************
367          * C O S I N E
368          ***************************************************/
369         /* Copy the data to temp array. Since we need it twice
370          * we can't overwrite original.
371          */
372         for (j = 0; (j < nframes); j++)
373         {
374             ctmp[j] = c1[j];
375         }
376
377         /* Cosine term of AC function */
378         low_do_four_core(nframes, ctmp, cfour, enCos);
379         for (j = 0; (j < nframes); j++)
380         {
381             c1[j] = cfour[j];
382         }
383
384         /* Sine term of AC function */
385         low_do_four_core(nframes, ctmp, cfour, enSin);
386         for (j = 0; (j < nframes); j++)
387         {
388             c1[j] += cfour[j];
389             csum[j] = c1[j];
390         }
391     }
392     else if (MODE(eacP2))
393     {
394         /***************************************************
395          * Legendre polynomials
396          ***************************************************/
397         /* First normalize the vectors */
398         norm_and_scale_vectors(nframes, c1, 1.0);
399
400         /* For P2 thingies we have to do six FFT based correls
401          * First for XX^2, then for YY^2, then for ZZ^2
402          * Then we have to do XY, YZ and XZ (counting these twice)
403          * After that we sum them and normalise
404          * P2(x) = (3 * cos^2 (x) - 1)/2
405          * for unit vectors u and v we compute the cosine as the inner product
406          * cos(u,v) = uX vX + uY vY + uZ vZ
407          *
408          *        oo
409          *        /
410          * C(t) = |  (3 cos^2(u(t'),u(t'+t)) - 1)/2 dt'
411          *        /
412          *        0
413          *
414          * For ACF we need:
415          * P2(u(0),u(t)) = [3 * (uX(0) uX(t) +
416          *                       uY(0) uY(t) +
417          *                       uZ(0) uZ(t))^2 - 1]/2
418          *               = [3 * ((uX(0) uX(t))^2 +
419          *                       (uY(0) uY(t))^2 +
420          *                       (uZ(0) uZ(t))^2 +
421          *                 2(uX(0) uY(0) uX(t) uY(t)) +
422          *                 2(uX(0) uZ(0) uX(t) uZ(t)) +
423          *                 2(uY(0) uZ(0) uY(t) uZ(t))) - 1]/2
424          *
425          *               = [(3/2) * (<uX^2> + <uY^2> + <uZ^2> +
426          *                         2<uXuY> + 2<uXuZ> + 2<uYuZ>) - 0.5]
427          *
428          */
429
430         /* Because of normalization the number of -0.5 to subtract
431          * depends on the number of data points!
432          */
433         for (j = 0; (j < nframes); j++)
434         {
435             csum[j] = -0.5 * (nframes - j);
436         }
437
438         /***** DIAGONAL ELEMENTS ************/
439         for (m = 0; (m < DIM); m++)
440         {
441             /* Copy the vector data in a linear array */
442             for (j = 0; (j < nframes); j++)
443             {
444                 ctmp[j] = gmx::square(c1[DIM * j + m]);
445             }
446             if (debug)
447             {
448                 sprintf(buf, "c1diag%d.xvg", m);
449                 dump_tmp(buf, nframes, ctmp);
450             }
451
452             low_do_four_core(nframes, ctmp, cfour, enNorm);
453
454             if (debug)
455             {
456                 sprintf(buf, "c1dfout%d.xvg", m);
457                 dump_tmp(buf, nframes, cfour);
458             }
459             fac = 1.5;
460             for (j = 0; (j < nframes); j++)
461             {
462                 csum[j] += fac * (cfour[j]);
463             }
464         }
465         /******* OFF-DIAGONAL ELEMENTS **********/
466         for (m = 0; (m < DIM); m++)
467         {
468             /* Copy the vector data in a linear array */
469             m1 = (m + 1) % DIM;
470             for (j = 0; (j < nframes); j++)
471             {
472                 ctmp[j] = c1[DIM * j + m] * c1[DIM * j + m1];
473             }
474
475             if (debug)
476             {
477                 sprintf(buf, "c1off%d.xvg", m);
478                 dump_tmp(buf, nframes, ctmp);
479             }
480             low_do_four_core(nframes, ctmp, cfour, enNorm);
481             if (debug)
482             {
483                 sprintf(buf, "c1ofout%d.xvg", m);
484                 dump_tmp(buf, nframes, cfour);
485             }
486             fac = 3.0;
487             for (j = 0; (j < nframes); j++)
488             {
489                 csum[j] += fac * cfour[j];
490             }
491         }
492     }
493     else if (MODE(eacP1) || MODE(eacVector))
494     {
495         /***************************************************
496          * V E C T O R & P1
497          ***************************************************/
498         if (MODE(eacP1))
499         {
500             /* First normalize the vectors */
501             norm_and_scale_vectors(nframes, c1, 1.0);
502         }
503
504         /* For vector thingies we have to do three FFT based correls
505          * First for XX, then for YY, then for ZZ
506          * After that we sum them and normalise
507          */
508         for (j = 0; (j < nframes); j++)
509         {
510             csum[j] = 0.0;
511         }
512         for (m = 0; (m < DIM); m++)
513         {
514             /* Copy the vector data in a linear array */
515             for (j = 0; (j < nframes); j++)
516             {
517                 ctmp[j] = c1[DIM * j + m];
518             }
519             low_do_four_core(nframes, ctmp, cfour, enNorm);
520             for (j = 0; (j < nframes); j++)
521             {
522                 csum[j] += cfour[j];
523             }
524         }
525     }
526     else
527     {
528         gmx_fatal(FARGS, "\nUnknown mode in do_autocorr (%lu)", mode);
529     }
530
531     sfree(cfour);
532     for (j = 0; (j < nframes); j++)
533     {
534         c1[j] = csum[j] / static_cast<real>(nframes - j);
535     }
536 }
537
538 void low_do_autocorr(const char*             fn,
539                      const gmx_output_env_t* oenv,
540                      const char*             title,
541                      int                     nframes,
542                      int                     nitem,
543                      int                     nout,
544                      real**                  c1,
545                      real                    dt,
546                      unsigned long           mode,
547                      int                     nrestart,
548                      gmx_bool                bAver,
549                      gmx_bool                bNormalize,
550                      gmx_bool                bVerbose,
551                      real                    tbeginfit,
552                      real                    tendfit,
553                      int                     eFitFn)
554 {
555     FILE *   fp, *gp = nullptr;
556     int      i;
557     real*    csum;
558     real *   ctmp, *fit;
559     real     sum, Ct2av, Ctav;
560     gmx_bool bFour = acf.bFour;
561
562     /* Check flags and parameters */
563     nout = get_acfnout();
564     if (nout == -1)
565     {
566         nout = acf.nout = (nframes + 1) / 2;
567     }
568     else if (nout > nframes)
569     {
570         nout = nframes;
571     }
572
573     if (MODE(eacCos) && MODE(eacVector))
574     {
575         gmx_fatal(FARGS, "Incompatible options bCos && bVector (%s, %d)", __FILE__, __LINE__);
576     }
577     if ((MODE(eacP3) || MODE(eacRcross)) && bFour)
578     {
579         if (bVerbose)
580         {
581             fprintf(stderr, "Can't combine mode %lu with FFT, turning off FFT\n", mode);
582         }
583         bFour = FALSE;
584     }
585     if (MODE(eacNormal) && MODE(eacVector))
586     {
587         gmx_fatal(FARGS, "Incompatible mode bits: normal and vector (or Legendre)");
588     }
589
590     /* Print flags and parameters */
591     if (bVerbose)
592     {
593         printf("Will calculate %s of %d thingies for %d frames\n", title ? title : "autocorrelation", nitem, nframes);
594         printf("bAver = %s, bFour = %s bNormalize= %s\n",
595                gmx::boolToString(bAver),
596                gmx::boolToString(bFour),
597                gmx::boolToString(bNormalize));
598         printf("mode = %lu, dt = %g, nrestart = %d\n", mode, dt, nrestart);
599     }
600     /* Allocate temp arrays */
601     snew(csum, nframes);
602     snew(ctmp, nframes);
603
604     /* Loop over items (e.g. molecules or dihedrals)
605      * In this loop the actual correlation functions are computed, but without
606      * normalizing them.
607      */
608     for (int i = 0; i < nitem; i++)
609     {
610         if (bVerbose && (((i % 100) == 0) || (i == nitem - 1)))
611         {
612             fprintf(stderr, "\rThingie %d", i + 1);
613             fflush(stderr);
614         }
615
616         if (bFour)
617         {
618             do_four_core(mode, nframes, c1[i], csum, ctmp);
619         }
620         else
621         {
622             do_ac_core(nframes, nout, ctmp, c1[i], nrestart, mode);
623         }
624     }
625     if (bVerbose)
626     {
627         fprintf(stderr, "\n");
628     }
629     sfree(ctmp);
630     sfree(csum);
631
632     if (fn)
633     {
634         snew(fit, nout);
635         fp = xvgropen(fn, title, "Time (ps)", "C(t)", oenv);
636     }
637     else
638     {
639         fit = nullptr;
640         fp  = nullptr;
641     }
642     if (bAver)
643     {
644         if (nitem > 1)
645         {
646             average_acf(bVerbose, nframes, nitem, c1);
647         }
648
649         if (bNormalize)
650         {
651             normalize_acf(nout, c1[0]);
652         }
653
654         if (eFitFn != effnNONE)
655         {
656             fit_acf(nout, eFitFn, oenv, fn != nullptr, tbeginfit, tendfit, dt, c1[0], fit);
657             sum = print_and_integrate(fp, nout, dt, c1[0], fit, 1);
658         }
659         else
660         {
661             sum = print_and_integrate(fp, nout, dt, c1[0], nullptr, 1);
662         }
663         if (bVerbose)
664         {
665             printf("Correlation time (integral over corrfn): %g (ps)\n", sum);
666         }
667     }
668     else
669     {
670         /* Not averaging. Normalize individual ACFs */
671         Ctav = Ct2av = 0;
672         if (debug)
673         {
674             gp = xvgropen("ct-distr.xvg", "Correlation times", "item", "time (ps)", oenv);
675         }
676         for (i = 0; i < nitem; i++)
677         {
678             if (bNormalize)
679             {
680                 normalize_acf(nout, c1[i]);
681             }
682             if (eFitFn != effnNONE)
683             {
684                 fit_acf(nout, eFitFn, oenv, fn != nullptr, tbeginfit, tendfit, dt, c1[i], fit);
685                 sum = print_and_integrate(fp, nout, dt, c1[i], fit, 1);
686             }
687             else
688             {
689                 sum = print_and_integrate(fp, nout, dt, c1[i], nullptr, 1);
690                 if (debug)
691                 {
692                     fprintf(debug, "CORRelation time (integral over corrfn %d): %g (ps)\n", i, sum);
693                 }
694             }
695             Ctav += sum;
696             Ct2av += sum * sum;
697             if (debug)
698             {
699                 fprintf(gp, "%5d  %.3f\n", i, sum);
700             }
701         }
702         if (debug)
703         {
704             xvgrclose(gp);
705         }
706         if (nitem > 1)
707         {
708             Ctav /= nitem;
709             Ct2av /= nitem;
710             printf("Average correlation time %.3f Std. Dev. %.3f Error %.3f (ps)\n",
711                    Ctav,
712                    std::sqrt((Ct2av - gmx::square(Ctav))),
713                    std::sqrt((Ct2av - gmx::square(Ctav)) / (nitem - 1)));
714         }
715     }
716     if (fp)
717     {
718         xvgrclose(fp);
719     }
720     sfree(fit);
721 }
722
723 /*! \brief Legend for selecting Legendre polynomials. */
724 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
725 static const char* Leg[] = { nullptr, "0", "1", "2", "3", nullptr };
726
727 t_pargs* add_acf_pargs(int* npargs, t_pargs* pa)
728 {
729     t_pargs acfpa[] = {
730         { "-acflen",
731           FALSE,
732           etINT,
733           { &acf.nout },
734           "Length of the ACF, default is half the number of frames" },
735         { "-normalize", FALSE, etBOOL, { &acf.bNormalize }, "Normalize ACF" },
736         { "-fftcorr",
737           FALSE,
738           etBOOL,
739           { &acf.bFour },
740           "HIDDENUse fast fourier transform for correlation function" },
741         { "-nrestart",
742           FALSE,
743           etINT,
744           { &acf.nrestart },
745           "HIDDENNumber of frames between time origins for ACF when no FFT is used" },
746         { "-P", FALSE, etENUM, { Leg }, "Order of Legendre polynomial for ACF (0 indicates none)" },
747         { "-fitfn", FALSE, etENUM, { s_ffn }, "Fit function" },
748         { "-beginfit",
749           FALSE,
750           etREAL,
751           { &acf.tbeginfit },
752           "Time where to begin the exponential fit of the correlation function" },
753         { "-endfit",
754           FALSE,
755           etREAL,
756           { &acf.tendfit },
757           "Time where to end the exponential fit of the correlation function, -1 is until the "
758           "end" },
759     };
760     t_pargs* ppa;
761     int      i, npa;
762
763     npa = asize(acfpa);
764     snew(ppa, *npargs + npa);
765     for (i = 0; (i < *npargs); i++)
766     {
767         ppa[i] = pa[i];
768     }
769     for (i = 0; (i < npa); i++)
770     {
771         ppa[*npargs + i] = acfpa[i];
772     }
773     (*npargs) += npa;
774
775     acf.mode       = 0;
776     acf.nrestart   = 1;
777     acf.nout       = -1;
778     acf.P          = 0;
779     acf.fitfn      = effnEXP1;
780     acf.bFour      = TRUE;
781     acf.bNormalize = TRUE;
782     acf.tbeginfit  = 0.0;
783     acf.tendfit    = -1;
784
785     bACFinit = TRUE;
786
787     return ppa;
788 }
789
790 void do_autocorr(const char*             fn,
791                  const gmx_output_env_t* oenv,
792                  const char*             title,
793                  int                     nframes,
794                  int                     nitem,
795                  real**                  c1,
796                  real                    dt,
797                  unsigned long           mode,
798                  gmx_bool                bAver)
799 {
800     if (!bACFinit)
801     {
802         printf("ACF data structures have not been initialised. Call add_acf_pargs\n");
803     }
804
805     /* Handle enumerated types */
806     sscanf(Leg[0], "%d", &acf.P);
807     acf.fitfn = sffn2effn(s_ffn);
808
809     switch (acf.P)
810     {
811         case 1: mode = mode | eacP1; break;
812         case 2: mode = mode | eacP2; break;
813         case 3: mode = mode | eacP3; break;
814         default: break;
815     }
816
817     low_do_autocorr(fn,
818                     oenv,
819                     title,
820                     nframes,
821                     nitem,
822                     acf.nout,
823                     c1,
824                     dt,
825                     mode,
826                     acf.nrestart,
827                     bAver,
828                     acf.bNormalize,
829                     bDebugMode(),
830                     acf.tbeginfit,
831                     acf.tendfit,
832                     acf.fitfn);
833 }
834
835 int get_acfnout()
836 {
837     if (!bACFinit)
838     {
839         gmx_fatal(FARGS, "ACF data not initialized yet");
840     }
841
842     return acf.nout;
843 }
844
845 int get_acffitfn()
846 {
847     if (!bACFinit)
848     {
849         gmx_fatal(FARGS, "ACF data not initialized yet");
850     }
851
852     return sffn2effn(s_ffn);
853 }