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