示例#1
0
static int low_lsq_y_ax_b(int n, real *xr, double *xd, real yr[],
                          real *a, real *b, real *r, real *chi2)
{
    gmx_stats_t lsq = gmx_stats_init();
    int         ok;

    for (int i = 0; (i < n); i++)
    {
        double pt;

        if (xd != NULL)
        {
            pt = xd[i];
        }
        else if (xr != NULL)
        {
            pt = xr[i];
        }
        else
        {
            gmx_incons("Either xd or xr has to be non-NULL in low_lsq_y_ax_b()");
        }

        if ((ok = gmx_stats_add_point(lsq, pt, yr[i], 0, 0)) != estatsOK)
        {
            gmx_stats_free(lsq);
            return ok;
        }
    }
    ok = gmx_stats_get_ab(lsq, elsqWEIGHT_NONE, a, b, NULL, NULL, chi2, r);
    gmx_stats_free(lsq);

    return ok;
}
示例#2
0
static void horizontal()
{
    gmx_rng_t   rng;
    gmx_stats_t straight;
    int         i, ok, n = 1000;
    real        y, a, b, da, db, aver, sigma, error, chi2, R, *xh, *yh;
    FILE       *fp;

    rng      = gmx_rng_init(13);
    straight = gmx_stats_init();
    for (i = 0; (i < n); i++)
    {
        y = gmx_rng_uniform_real(rng);
        if ((ok = gmx_stats_add_point(straight, i, y, 0, 0)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
    }
    /* Horizontal test */
    if ((ok = gmx_stats_get_ase(straight, &aver, &sigma, &error)) != estatsOK)
    {
        fprintf(stderr, "%s\n", gmx_stats_message(ok));
    }
    fp = fopen("straight.xvg", "w");
    if ((ok = gmx_stats_dump_xy(straight, fp)) != estatsOK)
    {
        fprintf(stderr, "%s\n", gmx_stats_message(ok));
    }
    fclose(fp);
    printf("Horizontal line: average %g, sigma %g, error %g\n", aver, sigma, error);
    if ((ok = gmx_stats_done(straight)) != estatsOK)
    {
        fprintf(stderr, "%s\n", gmx_stats_message(ok));
    }
}
示例#3
0
static int low_lsq_y_ax_b(int n, real *xr, double *xd, real yr[],
                          real *a, real *b, real *r, real *chi2)
{
    int         i, ok;
    gmx_stats_t lsq;

    lsq = gmx_stats_init();
    for (i = 0; (i < n); i++)
    {
        if ((ok = gmx_stats_add_point(lsq, (NULL != xd) ? xd[i] : xr[i], yr[i], 0, 0))
            != estatsOK)
        {
            return ok;
        }
    }
    if ((ok = gmx_stats_get_ab(lsq, elsqWEIGHT_NONE, a, b, NULL, NULL, chi2, r)) != estatsOK)
    {
        return ok;
    }

    return estatsOK;
    /*
       double x,y,yx,xx,yy,sx,sy,chi2;

       yx=xx=yy=sx=sy=0.0;
       for (i=0; i<n; i++) {
       if (xd != NULL) {
       x = xd[i];
       } else {
       x = xr[i];
       }
       y =   yr[i];

       yx += y*x;
       xx += x*x;
       yy += y*y;
       sx += x;
       sy += y;
       }
     * a = (n*yx-sy*sx)/(n*xx-sx*sx);
     * b = (sy-(*a)*sx)/n;
     * r = sqrt((xx-sx*sx)/(yy-sy*sy));

       chi2 = 0;
       if (xd != NULL) {
       for(i=0; i<n; i++)
       chi2 += dsqr(yr[i] - ((*a)*xd[i] + (*b)));
       } else {
       for(i=0; i<n; i++)
       chi2 += dsqr(yr[i] - ((*a)*xr[i] + (*b)));
       }

       if (n > 2)
       return sqrt(chi2/(n-2));
       else
       return 0;
     */
}
示例#4
0
static void clust_stat(FILE *fp, int start, int end, t_pdbfile *pdbf[])
{
    int         i;
    gmx_stats_t ed, ef;
    real        aver, sigma;

    ed = gmx_stats_init();
    ef = gmx_stats_init();
    for (i = start; (i < end); i++)
    {
        gmx_stats_add_point(ed, i-start, pdbf[i]->edocked, 0, 0);
        gmx_stats_add_point(ef, i-start, pdbf[i]->efree, 0, 0);
    }
    gmx_stats_get_ase(ed, &aver, &sigma, NULL);
    fprintf(fp, "  <%12s> = %8.3f (+/- %6.3f)\n", etitles[FALSE], aver, sigma);
    gmx_stats_get_ase(ef, &aver, &sigma, NULL);
    fprintf(fp, "  <%12s> = %8.3f (+/- %6.3f)\n", etitles[TRUE], aver, sigma);
    gmx_stats_free(ed);
    gmx_stats_free(ef);
}
示例#5
0
static void line()
{
    gmx_rng_t   rng;
    gmx_stats_t line;
    int         i, dy, ok, n = 1000;
    real        y, a, b, da, db, aver, sigma, error, chi2, R, rfit;
    const real  a0 = 0.23, b0 = 2.7;
    FILE       *fp;

    for (dy = 0; (dy < 2); dy++)
    {
        rng      = gmx_rng_init(13);
        line     = gmx_stats_init();
        for (i = 0; (i < n); i++)
        {
            y = a0*i+b0+50*(gmx_rng_uniform_real(rng)-0.5);
            if ((ok = gmx_stats_add_point(line, i, y, 0, dy*0.1)) != estatsOK)
            {
                fprintf(stderr, "%s\n", gmx_stats_message(ok));
            }
        }
        /* Line with slope test */
        if ((ok = gmx_stats_get_ab(line, elsqWEIGHT_NONE, &a, &b, &da, &db, &chi2, &rfit)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        if ((ok = gmx_stats_get_corr_coeff(line, &R)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        if (dy == 0)
        {
            fp = fopen("line0.xvg", "w");
        }
        else
        {
            fp = fopen("line1.xvg", "w");
        }
        if ((ok = gmx_stats_dump_xy(line, fp)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        fclose(fp);
        printf("Line with eqn. y = %gx + %g with noise%s\n", a0, b0,
               (dy == 0) ? "" : " and uncertainties");
        printf("Found: a = %g +/- %g, b = %g +/- %g\n", a, da, b, db);
        if ((ok = gmx_stats_done(line)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        gmx_rng_destroy(rng);
    }
}
示例#6
0
/* Old convenience functions, should be merged with the core
   statistics above. */
int lsq_y_ax(int n, real x[], real y[], real *a)
{
    gmx_stats_t lsq = gmx_stats_init();
    int         ok;
    real        da, chi2, Rfit;

    gmx_stats_add_points(lsq, n, x, y, 0, 0);
    ok = gmx_stats_get_a(lsq, elsqWEIGHT_NONE, a, &da, &chi2, &Rfit);
    gmx_stats_free(lsq);

    return ok;
}
示例#7
0
static void histogram()
{
    gmx_rng_t   rng;
    gmx_stats_t camel;
    int         i, ok, n = 1000, norm;
    real        y, a, b, da, db, aver, sigma, error, chi2, R, *xh, *yh;
    const real  a0 = 0.23, b0 = 2.7;
    FILE       *fp;
    char        fn[256];

    for (norm = 0; (norm < 2); norm++)
    {
        rng      = gmx_rng_init(13);
        camel    = gmx_stats_init();
        for (i = 0; (i < n); i++)
        {
            y = sqr(gmx_rng_uniform_real(rng));
            if ((ok = gmx_stats_add_point(camel, i, y+1, 0, 0)) != estatsOK)
            {
                fprintf(stderr, "%s\n", gmx_stats_message(ok));
            }
            y = sqr(gmx_rng_uniform_real(rng));
            if ((ok = gmx_stats_add_point(camel, i+0.5, y+2, 0, 0)) != estatsOK)
            {
                fprintf(stderr, "%s\n", gmx_stats_message(ok));
            }
        }
        /* Histogram test */
        if ((ok = gmx_stats_make_histogram(camel, 0, 101, norm, &xh, &yh)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        sprintf(fn, "histo%d-data.xvg", norm);
        fp = fopen(fn, "w");
        gmx_stats_dump_xy(camel, fp);
        fclose(fp);
        sprintf(fn, "histo%d.xvg", norm);
        fp = fopen(fn, "w");
        for (i = 0; (i < 101); i++)
        {
            fprintf(fp, "%12g  %12g\n", xh[i], yh[i]);
        }
        fclose(fp);
        sfree(xh);
        sfree(yh);
    }
}
示例#8
0
int lsq_y_ax_b_error(int n, real x[], real y[], real dy[],
                     real *a, real *b, real *da, real *db,
                     real *r, real *chi2)
{
    gmx_stats_t lsq = gmx_stats_init();
    int         ok;

    for (int i = 0; (i < n); i++)
    {
        ok = gmx_stats_add_point(lsq, x[i], y[i], 0, dy[i]);
        if (ok != estatsOK)
        {
            gmx_stats_free(lsq);
            return ok;
        }
    }
    ok = gmx_stats_get_ab(lsq, elsqWEIGHT_Y, a, b, da, db, chi2, r);
    gmx_stats_free(lsq);

    return ok;
}
示例#9
0
/* Old convenience functions, should be merged with the core
   statistics above. */
int lsq_y_ax(int n, real x[], real y[], real *a)
{
    gmx_stats_t lsq = gmx_stats_init();
    int         ok;
    real        da, chi2, Rfit;

    gmx_stats_add_points(lsq, n, x, y, 0, 0);
    if ((ok = gmx_stats_get_a(lsq, elsqWEIGHT_NONE, a, &da, &chi2, &Rfit)) != estatsOK)
    {
        return ok;
    }

    /*  int    i;
        double xx,yx;

        yx=xx=0.0;
        for (i=0; i<n; i++) {
        yx+=y[i]*x[i];
        xx+=x[i]*x[i];
        }
     * a=yx/xx;
     */
    return estatsOK;
}
示例#10
0
/* this is the main loop for the correlation type functions
 * fx and nx are file pointers to things like read_first_x and
 * read_next_x
 */
int corr_loop(t_corr *curr, const char *fn, t_topology *top, int ePBC,
              gmx_bool bMol, int gnx[], atom_id *index[],
              t_calc_func *calc1, gmx_bool bTen, int *gnx_com, atom_id *index_com[],
              real dt, real t_pdb, rvec **x_pdb, matrix box_pdb,
              const output_env_t oenv)
{
    rvec            *x[2];  /* the coordinates to read */
    rvec            *xa[2]; /* the coordinates to calculate displacements for */
    rvec             com = {0};
    real             t, t_prev = 0;
    int              natoms, i, j, cur = 0, maxframes = 0;
    t_trxstatus     *status;
#define        prev (1-cur)
    matrix           box;
    gmx_bool         bFirst;
    gmx_rmpbc_t      gpbc = NULL;

    natoms = read_first_x(oenv, &status, fn, &curr->t0, &(x[cur]), box);
#ifdef DEBUG
    fprintf(stderr, "Read %d atoms for first frame\n", natoms);
#endif
    if ((gnx_com != NULL) && natoms < top->atoms.nr)
    {
        fprintf(stderr, "WARNING: The trajectory only contains part of the system (%d of %d atoms) and therefore the COM motion of only this part of the system will be removed\n", natoms, top->atoms.nr);
    }

    snew(x[prev], natoms);

    if (bMol)
    {
        curr->ncoords = curr->nmol;
        snew(xa[0], curr->ncoords);
        snew(xa[1], curr->ncoords);
    }
    else
    {
        curr->ncoords = natoms;
        xa[0]         = x[0];
        xa[1]         = x[1];
    }

    bFirst = TRUE;
    t      = curr->t0;
    if (x_pdb)
    {
        *x_pdb = NULL;
    }

    if (bMol)
    {
        gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
    }

    /* the loop over all frames */
    do
    {
        if (x_pdb && ((bFirst && t_pdb < t) ||
                      (!bFirst &&
                       t_pdb > t - 0.5*(t - t_prev) &&
                       t_pdb < t + 0.5*(t - t_prev))))
        {
            if (*x_pdb == NULL)
            {
                snew(*x_pdb, natoms);
            }
            for (i = 0; i < natoms; i++)
            {
                copy_rvec(x[cur][i], (*x_pdb)[i]);
            }
            copy_mat(box, box_pdb);
        }


        /* check whether we've reached a restart point */
        if (bRmod(t, curr->t0, dt))
        {
            curr->nrestart++;

            srenew(curr->x0, curr->nrestart);
            snew(curr->x0[curr->nrestart-1], curr->ncoords);
            srenew(curr->com, curr->nrestart);
            srenew(curr->n_offs, curr->nrestart);
            srenew(curr->lsq, curr->nrestart);
            snew(curr->lsq[curr->nrestart-1], curr->nmol);
            for (i = 0; i < curr->nmol; i++)
            {
                curr->lsq[curr->nrestart-1][i]  = gmx_stats_init();
            }

            if (debug)
            {
                fprintf(debug, "Extended data structures because of new restart %d\n",
                        curr->nrestart);
            }
        }
        /* create or extend the frame-based arrays */
        if (curr->nframes >= maxframes-1)
        {
            if (maxframes == 0)
            {
                for (i = 0; (i < curr->ngrp); i++)
                {
                    curr->ndata[i] = NULL;
                    curr->data[i]  = NULL;
                    if (bTen)
                    {
                        curr->datam[i] = NULL;
                    }
                }
                curr->time = NULL;
            }
            maxframes += 10;
            for (i = 0; (i < curr->ngrp); i++)
            {
                srenew(curr->ndata[i], maxframes);
                srenew(curr->data[i], maxframes);
                if (bTen)
                {
                    srenew(curr->datam[i], maxframes);
                }
                for (j = maxframes-10; j < maxframes; j++)
                {
                    curr->ndata[i][j] = 0;
                    curr->data[i][j]  = 0;
                    if (bTen)
                    {
                        clear_mat(curr->datam[i][j]);
                    }
                }
            }
            srenew(curr->time, maxframes);
        }

        /* set the time */
        curr->time[curr->nframes] = t - curr->t0;

        /* for the first frame, the previous frame is a copy of the first frame */
        if (bFirst)
        {
            std::memcpy(xa[prev], xa[cur], curr->ncoords*sizeof(xa[prev][0]));
            bFirst = FALSE;
        }

        /* make the molecules whole */
        if (bMol)
        {
            gmx_rmpbc(gpbc, natoms, box, x[cur]);
        }

        /* calculate the molecules' centers of masses and put them into xa */
        if (bMol)
        {
            calc_mol_com(gnx[0], index[0], &top->mols, &top->atoms, x[cur], xa[cur]);
        }

        /* first remove the periodic boundary condition crossings */
        for (i = 0; i < curr->ngrp; i++)
        {
            prep_data(bMol, gnx[i], index[i], xa[cur], xa[prev], box);
        }

        /* calculate the center of mass */
        if (gnx_com)
        {
            prep_data(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box);
            calc_com(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box,
                     &top->atoms, com);
        }

        /* loop over all groups in index file */
        for (i = 0; (i < curr->ngrp); i++)
        {
            /* calculate something useful, like mean square displacements */
            calc_corr(curr, i, gnx[i], index[i], xa[cur], (gnx_com != NULL), com,
                      calc1, bTen);
        }
        cur    = prev;
        t_prev = t;

        curr->nframes++;
    }
    while (read_next_x(oenv, status, &t, x[cur], box));
    fprintf(stderr, "\nUsed %d restart points spaced %g %s over %g %s\n\n",
            curr->nrestart,
            output_env_conv_time(oenv, dt), output_env_get_time_unit(oenv),
            output_env_conv_time(oenv, curr->time[curr->nframes-1]),
            output_env_get_time_unit(oenv) );

    if (bMol)
    {
        gmx_rmpbc_done(gpbc);
    }

    close_trj(status);

    return natoms;
}
示例#11
0
void printmol(t_corr *curr, const char *fn,
              const char *fn_pdb, int *molindex, t_topology *top,
              rvec *x, int ePBC, matrix box, const output_env_t oenv)
{
#define NDIST 100
    FILE       *out;
    gmx_stats_t lsq1;
    int         i, j;
    real        a, b, D, Dav, D2av, VarD, sqrtD, sqrtD_max, scale;
    t_pdbinfo  *pdbinfo = NULL;
    int        *mol2a   = NULL;

    out = xvgropen(fn, "Diffusion Coefficients / Molecule", "Molecule", "D", oenv);

    if (fn_pdb)
    {
        if (top->atoms.pdbinfo == NULL)
        {
            snew(top->atoms.pdbinfo, top->atoms.nr);
        }
        pdbinfo = top->atoms.pdbinfo;
        mol2a   = top->mols.index;
    }

    Dav       = D2av = 0;
    sqrtD_max = 0;
    for (i = 0; (i < curr->nmol); i++)
    {
        lsq1 = gmx_stats_init();
        for (j = 0; (j < curr->nrestart); j++)
        {
            real xx, yy, dx, dy;

            while (gmx_stats_get_point(curr->lsq[j][i], &xx, &yy, &dx, &dy, 0) == estatsOK)
            {
                gmx_stats_add_point(lsq1, xx, yy, dx, dy);
            }
        }
        gmx_stats_get_ab(lsq1, elsqWEIGHT_NONE, &a, &b, NULL, NULL, NULL, NULL);
        gmx_stats_done(lsq1);
        sfree(lsq1);
        D     = a*FACTOR/curr->dim_factor;
        if (D < 0)
        {
            D   = 0;
        }
        Dav  += D;
        D2av += sqr(D);
        fprintf(out, "%10d  %10g\n", i, D);
        if (pdbinfo)
        {
            sqrtD = std::sqrt(D);
            if (sqrtD > sqrtD_max)
            {
                sqrtD_max = sqrtD;
            }
            for (j = mol2a[molindex[i]]; j < mol2a[molindex[i]+1]; j++)
            {
                pdbinfo[j].bfac = sqrtD;
            }
        }
    }
    xvgrclose(out);
    do_view(oenv, fn, "-graphtype bar");

    /* Compute variance, stddev and error */
    Dav  /= curr->nmol;
    D2av /= curr->nmol;
    VarD  = D2av - sqr(Dav);
    printf("<D> = %.4f Std. Dev. = %.4f Error = %.4f\n",
           Dav, std::sqrt(VarD), std::sqrt(VarD/curr->nmol));

    if (fn_pdb && x)
    {
        scale = 1;
        while (scale*sqrtD_max > 10)
        {
            scale *= 0.1;
        }
        while (scale*sqrtD_max < 0.1)
        {
            scale *= 10;
        }
        GMX_RELEASE_ASSERT(pdbinfo != NULL, "Internal error - pdbinfo not set for PDB input");
        for (i = 0; i < top->atoms.nr; i++)
        {
            pdbinfo[i].bfac *= scale;
        }
        write_sto_conf(fn_pdb, "molecular MSD", &top->atoms, x, NULL, ePBC, box);
    }
}
示例#12
0
int lsq_y_ax_b_error(int n, real x[], real y[], real dy[],
                     real *a, real *b, real *da, real *db,
                     real *r, real *chi2)
{
    gmx_stats_t lsq;
    int         i, ok;

    lsq = gmx_stats_init();
    for (i = 0; (i < n); i++)
    {
        if ((ok = gmx_stats_add_point(lsq, x[i], y[i], 0, dy[i])) != estatsOK)
        {
            return ok;
        }
    }
    if ((ok = gmx_stats_get_ab(lsq, elsqWEIGHT_Y, a, b, da, db, chi2, r)) != estatsOK)
    {
        return ok;
    }
    if ((ok = gmx_stats_done(lsq)) != estatsOK)
    {
        return ok;
    }
    sfree(lsq);

    return estatsOK;
    /*
       double sxy,sxx,syy,sx,sy,w,s_2,dx2,dy2,mins;

       sxy=sxx=syy=sx=sy=w=0.0;
       mins = dy[0];
       for(i=1; (i<n); i++)
       mins = min(mins,dy[i]);
       if (mins <= 0)
       gmx_fatal(FARGS,"Zero or negative weigths in linear regression analysis");

       for (i=0; i<n; i++) {
       s_2  = dsqr(1.0/dy[i]);
       sxx += s_2*dsqr(x[i]);
       sxy += s_2*y[i]*x[i];
       syy += s_2*dsqr(y[i]);
       sx  += s_2*x[i];
       sy  += s_2*y[i];
       w   += s_2;
       }
       sxx = sxx/w;
       sxy = sxy/w;
       syy = syy/w;
       sx  = sx/w;
       sy  = sy/w;
       dx2 = (sxx-sx*sx);
       dy2 = (syy-sy*sy);
     * a=(sxy-sy*sx)/dx2;
     * b=(sy-(*a)*sx);

     * chi2=0;
       for(i=0; i<n; i++)
     * chi2+=dsqr((y[i]-((*a)*x[i]+(*b)))/dy[i]);
     * chi2 = *chi2/w;

     * da = sqrt(*chi2/((n-2)*dx2));
     * db = *da*sqrt(sxx);
     * r  = *a*sqrt(dx2/dy2);

       if (debug)
       fprintf(debug,"sx = %g, sy = %g, sxy = %g, sxx = %g, w = %g\n"
       "chi2 = %g, dx2 = %g\n",
       sx,sy,sxy,sxx,w,*chi2,dx2);

       if (n > 2)
     * chi2 = sqrt(*chi2/(n-2));
       else
     * chi2 = 0;
     */
}
示例#13
0
static void do_bonds(FILE *log, const char *fn, const char *fbond,
                     const char *fdist, int gnx, atom_id index[],
                     real blen, real tol, gmx_bool bAver,
                     t_topology *top, int ePBC, gmx_bool bAverDist,
                     const output_env_t oenv)
{
#define MAXTAB 1000
    FILE       *out, *outd = NULL;
    int        *btab = NULL;
    real        b0   = 0, b1, db = 0;
    real        bond, bav;
    gmx_stats_t b_one = NULL, *b_all = NULL;
    /*real   mean, mean2, sqrdev2, sigma2;
       int    counter;*/
    rvec        *x;
    rvec         dx;
    t_trxstatus *status;
    int          natoms;
    matrix       box;
    real         t, fac;
    int          bind, i, nframes, i0, i1;
    t_pbc        pbc;
    int          N;
    real         aver, sigma, error;

    if (!bAver)
    {
        snew(b_all, gnx/2);
        for (i = 0; (i < gnx/2); i++)
        {
            b_all[i] = gmx_stats_init();
        }
    }
    else
    {
        b_one = gmx_stats_init();
        snew(btab, MAXTAB+1);
    }

    natoms = read_first_x(oenv, &status, fn, &t, &x, box);
    if (natoms == 0)
    {
        gmx_fatal(FARGS, "No atoms in trajectory!");
    }

    if (fdist)
    {
        outd = xvgropen(fdist, bAverDist ? "Average distance" : "Distances",
                        "Time (ps)", "Distance (nm)", oenv);
        if (!bAverDist)
        {
            make_dist_leg(outd, gnx, index, &(top->atoms), oenv);
        }
    }

    nframes = 0;
    do
    {
        set_pbc(&pbc, ePBC, box);
        if (fdist)
        {
            fprintf(outd, " %8.4f", t);
        }
        nframes++; /* count frames */
        bav = 0.0;
        for (i = 0; (i < gnx); i += 2)
        {
            pbc_dx(&pbc, x[index[i]], x[index[i+1]], dx);
            bond   = norm(dx);
            if (bAverDist)
            {
                bav += bond;
            }
            else if (fdist)
            {
                fprintf(outd, " %.3f", bond);
            }
            if (bAver)
            {
                gmx_stats_add_point(b_one, t, bond, 0, 0);
                if (db == 0)
                {
                    if (blen == -1)
                    {
                        b0 = 0;
                        b1 = 0.2;
                        db = (b1-b0)/MAXTAB;
                    }
                    else
                    {
                        b0   = (1.0-tol)*blen;
                        b1   = (1.0+tol)*blen;
                        db   = (2.0*(b1-b0))/MAXTAB;
                    }
                }
                bind = (int)((bond-b0)/db+0.5);
                if ((bind >= 0) && (bind <= MAXTAB))
                {
                    btab[bind]++;
                }
                else
                {
                    /*
                       printf("bond: %4d-%4d bond=%10.5e, dx=(%10.5e,%10.5e,%10.5e)\n",
                       index[i],index[i+1],bond,dx[XX],dx[YY],dx[ZZ]);
                     */
                }
            }
            else
            {
                gmx_stats_add_point(b_all[i/2], t, bond, 0, 0);
            }
        }
        if (bAverDist)
        {
            fprintf(outd, " %.5f", bav*2.0/gnx);
        }
        if (fdist)
        {
            fprintf(outd, "\n");
        }
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);

    if (fdist)
    {
        ffclose(outd);
    }

    /*
       mean = mean / counter;
       mean2 = mean2 / counter;
       sqrdev2 = (mean2 - mean*mean);
       sigma2 = sqrdev2*counter / (counter - 1);
     */
    /* For definitions see "Weet wat je meet" */
    if (bAver)
    {
        printf("\n");
        gmx_stats_get_npoints(b_one, &N);
        printf("Total number of samples               : %d\n", N);
        gmx_stats_get_ase(b_one, &aver, &sigma, &error);
        printf("Mean                                  : %g\n", aver);
        printf("Standard deviation of the distribution: %g\n", sigma);
        printf("Standard deviation of the mean        : %g\n", error);
        gmx_stats_done(b_one);
        sfree(b_one);

        out = xvgropen(fbond, "Bond Stretching Distribution",
                       "Bond Length (nm)", "", oenv);

        for (i0 = 0; ((i0 < MAXTAB) && (btab[i0] == 0)); i0++)
        {
            ;
        }
        i0 = max(0, i0-1);
        for (i1 = MAXTAB; ((i1 > 0)      && (btab[i1] == 0)); i1--)
        {
            ;
        }
        i1 = min(MAXTAB, i1+1);

        if (i0 >= i1)
        {
            gmx_fatal(FARGS, "No distribution... (i0 = %d, i1 = %d)? ? ! ! ? !", i0, i1);
        }

        fac = 2.0/(nframes*gnx*db);
        for (i = i0; (i <= i1); i++)
        {
            fprintf(out, "%8.5f  %8.5f\n", b0+i*db, btab[i]*fac);
        }
        ffclose(out);
    }
    else
    {
        fprintf(log, "%5s  %5s  %8s  %8s\n", "i", "j", "b_aver", "sigma");
        for (i = 0; (i < gnx/2); i++)
        {
            gmx_stats_get_ase(b_all[i], &aver, &sigma, NULL);
            fprintf(log, "%5u  %5u  %8.5f  %8.5f\n", 1+index[2*i], 1+index[2*i+1],
                    aver, sigma);
            gmx_stats_done(b_all[i]);
            sfree(b_all[i]);
        }
        sfree(b_all);
    }
}
static void do_dip(t_topology *top,int ePBC,real volume,
                   const char *fn,
                   const char *out_mtot,const char *out_eps,
                   const char *out_aver, const char *dipdist,
                   const char *cosaver, const char *fndip3d,
                   const char *fnadip,  gmx_bool bPairs,
                   const char *corrtype,const char *corf,
                   gmx_bool bGkr,     const char *gkrfn,
                   gmx_bool bPhi,     int  *nlevels,  int ndegrees,
                   int  ncos,
                   const char *cmap,    real rcmax,
                   gmx_bool bQuad,    const char *quadfn,
                   gmx_bool bMU,      const char *mufn,
                   int  *gnx,     int  *molindex[],
                   real mu_max,   real mu_aver,
                   real epsilonRF,real temp,
                   int  *gkatom,  int skip,
                   gmx_bool bSlab,    int nslices,
                   const char *axtitle, const char *slabfn,
                   const output_env_t oenv)
{
    const char *leg_mtot[] = { 
        "M\\sx \\N", 
        "M\\sy \\N",
        "M\\sz \\N",
        "|M\\stot \\N|"
    };
#define NLEGMTOT asize(leg_mtot)
    const char *leg_eps[] = { 
        "epsilon",
        "G\\sk",
        "g\\sk"
    };
#define NLEGEPS asize(leg_eps)
    const char *leg_aver[] = { 
        "< |M|\\S2\\N >", 
        "< |M| >\\S2\\N",
        "< |M|\\S2\\N > - < |M| >\\S2\\N",
        "< |M| >\\S2\\N / < |M|\\S2\\N >"
    };
#define NLEGAVER asize(leg_aver)
    const char *leg_cosaver[] = {
        "\\f{4}<|cos\\f{12}q\\f{4}\\sij\\N|>",
        "RMSD cos",
        "\\f{4}<|cos\\f{12}q\\f{4}\\siX\\N|>",
        "\\f{4}<|cos\\f{12}q\\f{4}\\siY\\N|>",
        "\\f{4}<|cos\\f{12}q\\f{4}\\siZ\\N|>"
    };
#define NLEGCOSAVER asize(leg_cosaver)
    const char *leg_adip[] = {
        "<mu>",
        "Std. Dev.",
        "Error"
    };
#define NLEGADIP asize(leg_adip)

    FILE       *outdd,*outmtot,*outaver,*outeps,*caver=NULL;
    FILE       *dip3d=NULL,*adip=NULL;
    rvec       *x,*dipole=NULL,mu_t,quad,*dipsp=NULL;
    t_gkrbin   *gkrbin = NULL;
    gmx_enxnm_t *enm=NULL;
    t_enxframe *fr;
    int        nframes=1000,nre,timecheck=0,ncolour=0;
    ener_file_t fmu=NULL;
    int        i,j,k,n,m,natom=0,nmol,gnx_tot,teller,tel3;
    t_trxstatus *status;
    int        *dipole_bin,ndipbin,ibin,iVol,step,idim=-1;
    unsigned long mode;
    char       buf[STRLEN];
    real       rcut=0,t,t0,t1,dt,lambda,dd,rms_cos;
    rvec       dipaxis;
    matrix     box;
    gmx_bool   bCorr,bTotal,bCont;
    double     M_diff=0,epsilon,invtel,vol_aver;
    double     mu_ave,mu_mol,M2_ave=0,M_ave2=0,M_av[DIM],M_av2[DIM];
    double     M[3],M2[3],M4[3],Gk=0,g_k=0;
    gmx_stats_t Mx,My,Mz,Msq,Vol,*Qlsq,mulsq,muframelsq=NULL;
    ivec       iMu;
    real       **muall=NULL;
    rvec       *slab_dipoles=NULL;
    t_atom     *atom=NULL;
    t_block    *mols=NULL;
    gmx_rmpbc_t gpbc=NULL;

    gnx_tot = gnx[0];
    if (ncos > 1) {
        gnx_tot += gnx[1];
    }

    vol_aver = 0.0;
      
    iVol=-1;
    if (bMU) 
    {
        fmu = open_enx(mufn,"r");
        do_enxnms(fmu,&nre,&enm);

        /* Determine the indexes of the energy grps we need */
        for (i=0; (i<nre); i++) {
            if (strstr(enm[i].name,"Volume"))
                iVol=i;
            else if (strstr(enm[i].name,"Mu-X"))
                iMu[XX]=i;
            else if (strstr(enm[i].name,"Mu-Y"))
                iMu[YY]=i;
            else if (strstr(enm[i].name,"Mu-Z"))
                iMu[ZZ]=i;
        }
    }
    else 
    {
        atom = top->atoms.atom;
        mols = &(top->mols);
    }
  
    if ((iVol == -1) && bMU)
        printf("Using Volume from topology: %g nm^3\n",volume);

    /* Correlation stuff */ 
    bCorr  = (corrtype[0] != 'n');
    bTotal = (corrtype[0] == 't');
    if (bCorr) 
    {
        if (bTotal) 
        {
            snew(muall,1);
            snew(muall[0],nframes*DIM);
        }
        else 
        {
            snew(muall,gnx[0]);
            for(i=0; (i<gnx[0]); i++)
                snew(muall[i],nframes*DIM);
        }
    }

    /* Allocate array which contains for every molecule in a frame the
     * dipole moment.
     */
    if (!bMU)
        snew(dipole,gnx_tot);

    /* Statistics */
    snew(Qlsq,DIM);
    for(i=0; (i<DIM); i++) 
        Qlsq[i] = gmx_stats_init();
    mulsq = gmx_stats_init();
  
    /* Open all the files */
    outmtot = xvgropen(out_mtot,
                       "Total dipole moment of the simulation box vs. time",
                       "Time (ps)","Total Dipole Moment (Debye)",oenv);
    outeps  = xvgropen(out_eps,"Epsilon and Kirkwood factors",
                       "Time (ps)","",oenv);
    outaver = xvgropen(out_aver,"Total dipole moment",
                       "Time (ps)","D",oenv);
    if (bSlab) 
    {
        idim = axtitle[0] - 'X';
        if ((idim < 0) || (idim >= DIM))
            idim = axtitle[0] - 'x';
        if ((idim < 0) || (idim >= DIM))
            bSlab = FALSE;
        if (nslices < 2)
            bSlab = FALSE;
        fprintf(stderr,"axtitle = %s, nslices = %d, idim = %d\n",
                axtitle,nslices,idim);
        if (bSlab) 
        {
            snew(slab_dipoles,nslices);
            fprintf(stderr,"Doing slab analysis\n");
        }
    }
  
    if (fnadip) 
    {
        adip = xvgropen(fnadip, "Average molecular dipole","Dipole (D)","",oenv);
        xvgr_legend(adip,NLEGADIP,leg_adip, oenv);
  
    }
    if (cosaver) 
    {
        caver = xvgropen(cosaver,bPairs ? "Average pair orientation" :
                         "Average absolute dipole orientation","Time (ps)","",oenv);
        xvgr_legend(caver,NLEGCOSAVER,bPairs ? leg_cosaver : &(leg_cosaver[1]),
                    oenv);
    }
    
    if (fndip3d) 
    {
        snew(dipsp,gnx_tot);
  
        /* we need a dummy file for gnuplot */
        dip3d = (FILE *)ffopen("dummy.dat","w");
        fprintf(dip3d,"%f %f %f", 0.0,0.0,0.0);
        ffclose(dip3d);

        dip3d = (FILE *)ffopen(fndip3d,"w");
        fprintf(dip3d,"# This file was created by %s\n",Program());
        fprintf(dip3d,"# which is part of G R O M A C S:\n");
        fprintf(dip3d,"#\n");
    }
  
    /* Write legends to all the files */
    xvgr_legend(outmtot,NLEGMTOT,leg_mtot,oenv);
    xvgr_legend(outaver,NLEGAVER,leg_aver,oenv);
  
    if (bMU && (mu_aver == -1))
        xvgr_legend(outeps,NLEGEPS-2,leg_eps,oenv);
    else
        xvgr_legend(outeps,NLEGEPS,leg_eps,oenv);
    
    snew(fr,1);
    clear_rvec(mu_t);
    teller = 0;
    /* Read the first frame from energy or traj file */
    if (bMU)
        do 
        {
            bCont = read_mu_from_enx(fmu,iVol,iMu,mu_t,&volume,&t,nre,fr);
            if (bCont) 
            {  
                timecheck=check_times(t);
                if (timecheck < 0)
                    teller++;
                if ((teller % 10) == 0)
                    fprintf(stderr,"\r Skipping Frame %6d, time: %8.3f", teller, t);
            }
            else 
            {
                printf("End of %s reached\n",mufn);
                break;
            }
        } while (bCont && (timecheck < 0));
    else
        natom  = read_first_x(oenv,&status,fn,&t,&x,box);
  
    /* Calculate spacing for dipole bin (simple histogram) */
    ndipbin = 1+(mu_max/0.01);
    snew(dipole_bin, ndipbin);
    epsilon    = 0.0;
    mu_ave     = 0.0;
    for(m=0; (m<DIM); m++) 
    {
        M[m] = M2[m] = M4[m] = 0.0;
    }
  
    if (bGkr) 
    {
        /* Use 0.7 iso 0.5 to account for pressure scaling */
        /*  rcut   = 0.7*sqrt(max_cutoff2(box)); */
        rcut   = 0.7*sqrt(sqr(box[XX][XX])+sqr(box[YY][YY])+sqr(box[ZZ][ZZ]));

        gkrbin = mk_gkrbin(rcut,rcmax,bPhi,ndegrees); 
    }
    gpbc = gmx_rmpbc_init(&top->idef,ePBC,natom,box);

    /* Start while loop over frames */
    t1 = t0 = t;
    teller = 0;
    do 
    {
        if (bCorr && (teller >= nframes)) 
        {
            nframes += 1000;
            if (bTotal) 
            {
                srenew(muall[0],nframes*DIM);
            }
            else 
            {
                for(i=0; (i<gnx_tot); i++)
                    srenew(muall[i],nframes*DIM);
            }
        }
        t1 = t;

        muframelsq = gmx_stats_init();
    
        /* Initialise */
        for(m=0; (m<DIM); m++) 
            M_av2[m] = 0;
            
        if (bMU) 
        {
            /* Copy rvec into double precision local variable */
            for(m=0; (m<DIM); m++)
                M_av[m]  = mu_t[m];
        }
        else 
        {
            /* Initialise */
            for(m=0; (m<DIM); m++) 
                M_av[m] = 0;
                
            gmx_rmpbc(gpbc,natom,box,x);
      
            /* Begin loop of all molecules in frame */
            for(n=0; (n<ncos); n++) 
            {
                for(i=0; (i<gnx[n]); i++) 
                {
                    int gi,ind0,ind1;
	  
                    ind0  = mols->index[molindex[n][i]];
                    ind1  = mols->index[molindex[n][i]+1];
	  
                    mol_dip(ind0,ind1,x,atom,dipole[i]);
                    gmx_stats_add_point(mulsq,0,norm(dipole[i]),0,0);
                    gmx_stats_add_point(muframelsq,0,norm(dipole[i]),0,0);
                    if (bSlab) 
                        update_slab_dipoles(ind0,ind1,x,
                                            dipole[i],idim,nslices,slab_dipoles,box);
                    if (bQuad) 
                    {
                        mol_quad(ind0,ind1,x,atom,quad);
                        for(m=0; (m<DIM); m++)
                            gmx_stats_add_point(Qlsq[m],0,quad[m],0,0);
                    }
                    if (bCorr && !bTotal) 
                    {
                        tel3=DIM*teller;
                        muall[i][tel3+XX] = dipole[i][XX];
                        muall[i][tel3+YY] = dipole[i][YY];
                        muall[i][tel3+ZZ] = dipole[i][ZZ];
                    }
                    mu_mol = 0.0;
                    for(m=0; (m<DIM); m++) 
                    {
                        M_av[m]  += dipole[i][m];               /* M per frame */
                        mu_mol   += dipole[i][m]*dipole[i][m];  /* calc. mu for distribution */
                    }
                    mu_mol = sqrt(mu_mol);
	  
                    mu_ave += mu_mol;                         /* calc. the average mu */
	  
                    /* Update the dipole distribution */
                    ibin = (int)(ndipbin*mu_mol/mu_max + 0.5);
                    if (ibin < ndipbin)
                        dipole_bin[ibin]++;
	  
                    if (fndip3d) 
                    {
                        rvec2sprvec(dipole[i],dipsp[i]);
	    
                        if (dipsp[i][YY] > -M_PI && dipsp[i][YY] < -0.5*M_PI) {
                            if (dipsp[i][ZZ] < 0.5 * M_PI) 
                            {
                                ncolour = 1;
                            } 
                            else 
                            {
                                ncolour = 2;
                            }
                        }
                        else if (dipsp[i][YY] > -0.5*M_PI && dipsp[i][YY] < 0.0*M_PI) 
                        {
                            if (dipsp[i][ZZ] < 0.5 * M_PI) 
                            {
                                ncolour = 3;
                            } 
                            else 
                            {
                                ncolour = 4;
                            }       
                        }else if (dipsp[i][YY] > 0.0 && dipsp[i][YY] < 0.5*M_PI) {
                            if (dipsp[i][ZZ] < 0.5 * M_PI) {
                                ncolour = 5;
                            } else {
                                ncolour = 6;
                            }      
                        }
                        else if (dipsp[i][YY] > 0.5*M_PI && dipsp[i][YY] < M_PI) 
                        {
                            if (dipsp[i][ZZ] < 0.5 * M_PI) 
                            {
                                ncolour = 7;
                            } 
                            else 
                            {
                                ncolour = 8;
                            }
                        }
                        if (dip3d)
                            fprintf(dip3d,"set arrow %d from %f, %f, %f to %f, %f, %f lt %d  # %d %d\n", 
                                    i+1,
                                    x[ind0][XX],
                                    x[ind0][YY],
                                    x[ind0][ZZ],
                                    x[ind0][XX]+dipole[i][XX]/25, 
                                    x[ind0][YY]+dipole[i][YY]/25, 
                                    x[ind0][ZZ]+dipole[i][ZZ]/25, 
                                    ncolour, ind0, i);
                    }
                } /* End loop of all molecules in frame */
	
                if (dip3d) 
                {
                    fprintf(dip3d,"set title \"t = %4.3f\"\n",t);
                    fprintf(dip3d,"set xrange [0.0:%4.2f]\n",box[XX][XX]);
                    fprintf(dip3d,"set yrange [0.0:%4.2f]\n",box[YY][YY]);
                    fprintf(dip3d,"set zrange [0.0:%4.2f]\n\n",box[ZZ][ZZ]);
                    fprintf(dip3d,"splot 'dummy.dat' using 1:2:3 w vec\n");
                    fprintf(dip3d,"pause -1 'Hit return to continue'\n");
                }
            }
        }
        /* Compute square of total dipole */
        for(m=0; (m<DIM); m++)
            M_av2[m] = M_av[m]*M_av[m];
    
        if (cosaver) 
        {
            compute_avercos(gnx_tot,dipole,&dd,dipaxis,bPairs);
            rms_cos = sqrt(sqr(dipaxis[XX]-0.5)+
                           sqr(dipaxis[YY]-0.5)+
                           sqr(dipaxis[ZZ]-0.5));
            if (bPairs) 
                fprintf(caver,"%10.3e  %10.3e  %10.3e  %10.3e  %10.3e  %10.3e\n",
                        t,dd,rms_cos,dipaxis[XX],dipaxis[YY],dipaxis[ZZ]);
            else
                fprintf(caver,"%10.3e  %10.3e  %10.3e  %10.3e  %10.3e\n",
                        t,rms_cos,dipaxis[XX],dipaxis[YY],dipaxis[ZZ]);
        }
    
        if (bGkr) 
        {
            do_gkr(gkrbin,ncos,gnx,molindex,mols->index,x,dipole,ePBC,box,
                   atom,gkatom);
        }
    
        if (bTotal) 
        {
            tel3 = DIM*teller;
            muall[0][tel3+XX] = M_av[XX];
            muall[0][tel3+YY] = M_av[YY];
            muall[0][tel3+ZZ] = M_av[ZZ];
        }

        /* Write to file the total dipole moment of the box, and its components 
         * for this frame.
         */
        if ((skip == 0) || ((teller % skip) == 0))
            fprintf(outmtot,"%10g  %12.8e %12.8e %12.8e %12.8e\n",
                    t,M_av[XX],M_av[YY],M_av[ZZ],
                    sqrt(M_av2[XX]+M_av2[YY]+M_av2[ZZ]));

        for(m=0; (m<DIM); m++) 
        {
            M[m]  += M_av[m];
            M2[m] += M_av2[m];
            M4[m] += sqr(M_av2[m]);
        }
        /* Increment loop counter */
        teller++;
    
        /* Calculate for output the running averages */
        invtel  = 1.0/teller;
        M2_ave  = (M2[XX]+M2[YY]+M2[ZZ])*invtel;
        M_ave2  = invtel*(invtel*(M[XX]*M[XX] + M[YY]*M[YY] + M[ZZ]*M[ZZ]));
        M_diff  = M2_ave - M_ave2;

        /* Compute volume from box in traj, else we use the one from above */
        if (!bMU)
            volume  = det(box);
        vol_aver += volume;
    
        epsilon = calc_eps(M_diff,(vol_aver/teller),epsilonRF,temp);

        /* Calculate running average for dipole */
        if (mu_ave != 0) 
            mu_aver = (mu_ave/gnx_tot)*invtel;
    
        if ((skip == 0) || ((teller % skip) == 0)) 
        {
            /* Write to file < |M|^2 >, |< M >|^2. And the difference between 
             * the two. Here M is sum mu_i. Further write the finite system
             * Kirkwood G factor and epsilon.
             */
            fprintf(outaver,"%10g  %10.3e %10.3e %10.3e %10.3e\n",
                    t,M2_ave,M_ave2,M_diff,M_ave2/M2_ave);
      
            if (fnadip) 
            {
                real aver;
                gmx_stats_get_average(muframelsq,&aver);
                fprintf(adip, "%10g %f \n", t,aver);
            }
            /*if (dipole)
              printf("%f %f\n", norm(dipole[0]), norm(dipole[1]));
            */      
            if (!bMU || (mu_aver != -1)) 
            {
                /* Finite system Kirkwood G-factor */
                Gk = M_diff/(gnx_tot*mu_aver*mu_aver);
                /* Infinite system Kirkwood G-factor */
                if (epsilonRF == 0.0) 
                    g_k = ((2*epsilon+1)*Gk/(3*epsilon));
                else 
                    g_k = ((2*epsilonRF+epsilon)*(2*epsilon+1)*
                           Gk/(3*epsilon*(2*epsilonRF+1)));
	
                fprintf(outeps,"%10g  %10.3e %10.3e %10.3e\n",t,epsilon,Gk,g_k);

            }
            else 
                fprintf(outeps,"%10g  %12.8e\n",t,epsilon);
        }
        gmx_stats_done(muframelsq);
    
        if (bMU)
            bCont = read_mu_from_enx(fmu,iVol,iMu,mu_t,&volume,&t,nre,fr); 
        else
            bCont = read_next_x(oenv,status,&t,natom,x,box);
        timecheck=check_times(t);
    } while (bCont && (timecheck == 0) );
  
    gmx_rmpbc_done(gpbc);

    if (!bMU)
        close_trj(status);
    
    ffclose(outmtot);
    ffclose(outaver);
    ffclose(outeps);

    if (fnadip)
        ffclose(adip);

    if (cosaver)
        ffclose(caver);

    if (dip3d) {
        fprintf(dip3d,"set xrange [0.0:%4.2f]\n",box[XX][XX]);
        fprintf(dip3d,"set yrange [0.0:%4.2f]\n",box[YY][YY]);
        fprintf(dip3d,"set zrange [0.0:%4.2f]\n\n",box[ZZ][ZZ]);
        fprintf(dip3d,"splot 'dummy.dat' using 1:2:3 w vec\n");
        fprintf(dip3d,"pause -1 'Hit return to continue'\n");
        ffclose(dip3d);
    }

    if (bSlab) {
        dump_slab_dipoles(slabfn,idim,nslices,slab_dipoles,box,teller,oenv);
        sfree(slab_dipoles);
    }
  
    vol_aver /= teller;
    printf("Average volume over run is %g\n",vol_aver);
    if (bGkr) {
        print_gkrbin(gkrfn,gkrbin,gnx[0],teller,vol_aver,oenv);
        print_cmap(cmap,gkrbin,nlevels);
    }
    /* Autocorrelation function */  
    if (bCorr) {
        if (teller < 2) {
            printf("Not enough frames for autocorrelation\n");
        }
        else {
            dt=(t1 - t0)/(teller-1);
            printf("t0 %g, t %g, teller %d\n", t0,t,teller);
      
            mode = eacVector;

            if (bTotal)
                do_autocorr(corf,oenv,"Autocorrelation Function of Total Dipole",
                            teller,1,muall,dt,mode,TRUE);
            else
                do_autocorr(corf,oenv,"Dipole Autocorrelation Function",
                            teller,gnx_tot,muall,dt,
                            mode,strcmp(corrtype,"molsep"));
        }
    }
    if (!bMU) {
        real aver,sigma,error,lsq;

        gmx_stats_get_ase(mulsq,&aver,&sigma,&error);
        printf("\nDipole moment (Debye)\n");
        printf("---------------------\n");
        printf("Average  = %8.4f  Std. Dev. = %8.4f  Error = %8.4f\n",
               aver,sigma,error);
        if (bQuad) {
            rvec a,s,e;
            int mm;
            for(m=0; (m<DIM); m++)
                gmx_stats_get_ase(mulsq,&(a[m]),&(s[m]),&(e[m]));
    
            printf("\nQuadrupole moment (Debye-Ang)\n");
            printf("-----------------------------\n");
            printf("Averages  = %8.4f  %8.4f  %8.4f\n",a[XX],a[YY],a[ZZ]);
            printf("Std. Dev. = %8.4f  %8.4f  %8.4f\n",s[XX],s[YY],s[ZZ]);
            printf("Error     = %8.4f  %8.4f  %8.4f\n",e[XX],e[YY],e[ZZ]);
        }
        printf("\n");
    }
    printf("The following averages for the complete trajectory have been calculated:\n\n");
    printf(" Total < M_x > = %g Debye\n", M[XX]/teller);
    printf(" Total < M_y > = %g Debye\n", M[YY]/teller);
    printf(" Total < M_z > = %g Debye\n\n", M[ZZ]/teller);

    printf(" Total < M_x^2 > = %g Debye^2\n", M2[XX]/teller);
    printf(" Total < M_y^2 > = %g Debye^2\n", M2[YY]/teller);
    printf(" Total < M_z^2 > = %g Debye^2\n\n", M2[ZZ]/teller);

    printf(" Total < |M|^2 > = %g Debye^2\n", M2_ave);
    printf(" Total |< M >|^2 = %g Debye^2\n\n", M_ave2);

    printf(" < |M|^2 > - |< M >|^2 = %g Debye^2\n\n", M_diff);
  
    if (!bMU || (mu_aver != -1)) {
        printf("Finite system Kirkwood g factor G_k = %g\n", Gk);
        printf("Infinite system Kirkwood g factor g_k = %g\n\n", g_k);
    }
    printf("Epsilon = %g\n", epsilon);

    if (!bMU) {
        /* Write to file the dipole moment distibution during the simulation.
         */
        outdd=xvgropen(dipdist,"Dipole Moment Distribution","mu (Debye)","",oenv);
        for(i=0; (i<ndipbin); i++)
            fprintf(outdd,"%10g  %10f\n",
                    (i*mu_max)/ndipbin,dipole_bin[i]/(double)teller);
        ffclose(outdd);
        sfree(dipole_bin);
    }
    if (bGkr) 
        done_gkrbin(&gkrbin);
}