Пример #1
0
int gmx_dielectric(int argc, char *argv[])
{
    const char  *desc[] = {
        "[THISMODULE] calculates frequency dependent dielectric constants",
        "from the autocorrelation function of the total dipole moment in",
        "your simulation. This ACF can be generated by [gmx-dipoles].",
        "The functional forms of the available functions are:[PAR]",
        "One parameter:    y = [EXP]-a[SUB]1[sub] x[exp],[BR]",
        "Two parameters:   y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp],[BR]",
        "Three parameters: y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp] + (1 - a[SUB]2[sub]) [EXP]-a[SUB]3[sub] x[exp].[BR]",
        "Start values for the fit procedure can be given on the command line.",
        "It is also possible to fix parameters at their start value, use [TT]-fix[tt]",
        "with the number of the parameter you want to fix.",
        "[PAR]",
        "Three output files are generated, the first contains the ACF,",
        "an exponential fit to it with 1, 2 or 3 parameters, and the",
        "numerical derivative of the combination data/fit.",
        "The second file contains the real and imaginary parts of the",
        "frequency-dependent dielectric constant, the last gives a plot",
        "known as the Cole-Cole plot, in which the imaginary",
        "component is plotted as a function of the real component.",
        "For a pure exponential relaxation (Debye relaxation) the latter",
        "plot should be one half of a circle."
    };
    t_filenm     fnm[] = {
        { efXVG, "-f", "dipcorr", ffREAD  },
        { efXVG, "-d", "deriv",  ffWRITE },
        { efXVG, "-o", "epsw",   ffWRITE },
        { efXVG, "-c", "cole",   ffWRITE }
    };
#define NFILE asize(fnm)
    output_env_t oenv;
    int          i, j, nx, ny, nxtail, eFitFn, nfitparm;
    real         dt, integral, fitintegral, *fitparms, fac, rffac;
    double     **yd;
    real       **y;
    const char  *legend[] = { "Correlation", "Std. Dev.", "Fit", "Combined", "Derivative" };
    static int   fix      = 0, bFour = 0, bX = 1, nsmooth = 3;
    static real  tendInt  = 5.0, tbegin = 5.0, tend = 500.0;
    static real  A        = 0.5, tau1 = 10.0, tau2 = 1.0, eps0 = 80, epsRF = 78.5, tail = 500.0;
    real         lambda;
    t_pargs      pa[] = {
        { "-fft", FALSE, etBOOL, {&bFour},
          "use fast fourier transform for correlation function" },
        { "-x1",  FALSE, etBOOL, {&bX},
          "use first column as [IT]x[it]-axis rather than first data set" },
        { "-eint", FALSE, etREAL, {&tendInt},
          "Time to end the integration of the data and start to use the fit"},
        { "-bfit", FALSE, etREAL, {&tbegin},
          "Begin time of fit" },
        { "-efit", FALSE, etREAL, {&tend},
          "End time of fit" },
        { "-tail", FALSE, etREAL, {&tail},
          "Length of function including data and tail from fit" },
        { "-A", FALSE, etREAL, {&A},
          "Start value for fit parameter A" },
        { "-tau1", FALSE, etREAL, {&tau1},
          "Start value for fit parameter [GRK]tau[grk]1" },
        { "-tau2", FALSE, etREAL, {&tau2},
          "Start value for fit parameter [GRK]tau[grk]2" },
        { "-eps0", FALSE, etREAL, {&eps0},
          "[GRK]epsilon[grk]0 of your liquid" },
        { "-epsRF", FALSE, etREAL, {&epsRF},
          "[GRK]epsilon[grk] of the reaction field used in your simulation. A value of 0 means infinity." },
        { "-fix", FALSE, etINT,  {&fix},
          "Fix parameters at their start values, A (2), tau1 (1), or tau2 (4)" },
        { "-ffn",    FALSE, etENUM, {s_ffn},
          "Fit function" },
        { "-nsmooth", FALSE, etINT, {&nsmooth},
          "Number of points for smoothing" }
    };

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }
    please_cite(stdout, "Spoel98a");
    printf("WARNING: non-polarizable models can never yield an infinite\n"
           "dielectric constant that is different from 1. This is incorrect\n"
           "in the reference given above (Spoel98a).\n\n");


    nx     = read_xvg(opt2fn("-f", NFILE, fnm), &yd, &ny);
    dt     = yd[0][1] - yd[0][0];
    nxtail = min(tail/dt, nx);

    printf("Read data set containing %d colums and %d rows\n", ny, nx);
    printf("Assuming (from data) that timestep is %g, nxtail = %d\n",
           dt, nxtail);
    snew(y, 6);
    for (i = 0; (i < ny); i++)
    {
        snew(y[i], max(nx, nxtail));
    }
    for (i = 0; (i < nx); i++)
    {
        y[0][i] = yd[0][i];
        for (j = 1; (j < ny); j++)
        {
            y[j][i] = yd[j][i];
        }
    }
    if (nxtail > nx)
    {
        for (i = nx; (i < nxtail); i++)
        {
            y[0][i] = dt*i+y[0][0];
            for (j = 1; (j < ny); j++)
            {
                y[j][i] = 0.0;
            }
        }
        nx = nxtail;
    }


    /* We have read a file WITHOUT standard deviations, so we make our own... */
    if (ny == 2)
    {
        printf("Creating standard deviation numbers ...\n");
        srenew(y, 3);
        snew(y[2], nx);

        fac = 1.0/((real)nx);
        for (i = 0; (i < nx); i++)
        {
            y[2][i] = fac;
        }
    }

    eFitFn   = sffn2effn(s_ffn);
    nfitparm = nfp_ffn[eFitFn];
    snew(fitparms, 4);
    fitparms[0] = tau1;
    if (nfitparm > 1)
    {
        fitparms[1] = A;
    }
    if (nfitparm > 2)
    {
        fitparms[2] = tau2;
    }


    snew(y[3], nx);
    snew(y[4], nx);
    snew(y[5], nx);

    integral = print_and_integrate(NULL, calc_nbegin(nx, y[0], tbegin),
                                   dt, y[1], NULL, 1);
    integral += do_lmfit(nx, y[1], y[2], dt, y[0], tbegin, tend,
                         oenv, TRUE, eFitFn, fitparms, fix);
    for (i = 0; i < nx; i++)
    {
        y[3][i] = fit_function(eFitFn, fitparms, y[0][i]);
    }

    if (epsRF == 0)
    {
        /* This means infinity! */
        lambda = 0;
        rffac  = 1;
    }
    else
    {
        lambda = (eps0 - 1.0)/(2*epsRF - 1.0);
        rffac  = (2*epsRF+eps0)/(2*epsRF+1);
    }
    printf("DATA INTEGRAL: %5.1f, tauD(old) = %5.1f ps, "
           "tau_slope = %5.1f, tau_slope,D = %5.1f ps\n",
           integral, integral*rffac, fitparms[0], fitparms[0]*rffac);

    printf("tau_D from tau1 = %8.3g , eps(Infty) = %8.3f\n",
           fitparms[0]*(1 + fitparms[1]*lambda),
           1 + ((1 - fitparms[1])*(eps0 - 1))/(1 + fitparms[1]*lambda));

    fitintegral = numerical_deriv(nx, y[0], y[1], y[3], y[4], y[5], tendInt, nsmooth);
    printf("FIT INTEGRAL (tau_M): %5.1f, tau_D = %5.1f\n",
           fitintegral, fitintegral*rffac);

    /* Now we have the negative gradient of <Phi(0) Phi(t)> */
    write_xvg(opt2fn("-d", NFILE, fnm), "Data", nx-1, 6, y, legend, oenv);

    /* Do FFT and analysis */
    do_four(opt2fn("-o", NFILE, fnm), opt2fn("-c", NFILE, fnm),
            nx-1, y[0], y[5], eps0, epsRF, oenv);

    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
    do_view(oenv, opt2fn("-c", NFILE, fnm), NULL);
    do_view(oenv, opt2fn("-d", NFILE, fnm), "-nxy");

    return 0;
}
Пример #2
0
static void do_fit(FILE *out,int n,bool bYdy,int ny,real *x0,real **val,
		   int npargs,t_pargs *ppa)
{
  real *c1=NULL,*sig=NULL,*fitparm;
  real dt=0,tendfit,tbeginfit;
  int  i,efitfn,nparm;
  
  efitfn = get_acffitfn();
  nparm  = nfp_ffn[efitfn];
  fprintf(out,"Will fit to the following function:\n");
  fprintf(out,"%s\n",longs_ffn[efitfn]);
  c1 = val[n];
  if (bYdy) {
    c1  = val[n];
    sig = val[n+1];
    fprintf(out,"Using two columns as y and sigma values\n");
  } else {
    snew(sig,ny);
  }
  if (opt2parg_bSet("-beginfit",npargs,ppa)) {
    tbeginfit = opt2parg_real("-beginfit",npargs,ppa);
  } else {
    tbeginfit = x0 ? x0[0]    : 0;
  }
  if (opt2parg_bSet("-endfit",npargs,ppa)) {
    tendfit   = opt2parg_real("-endfit",npargs,ppa);
  } else {
    tendfit   = x0 ? x0[ny-1] : (ny-1)*dt;
  }
  
  snew(fitparm,nparm);
  switch(efitfn) {
  case effnEXP1:
    fitparm[0] = 0.5;
    break;
  case effnEXP2:
    fitparm[0] = 0.5;
    fitparm[1] = c1[0];
    break;
  case effnEXP3:
    fitparm[0] = 1.0;
    fitparm[1] = 0.5*c1[0];
    fitparm[2] = 10.0;
    break;
  case effnEXP5:
    fitparm[0] = fitparm[2] = 0.5*c1[0];
    fitparm[1] = 10;
    fitparm[3] = 40;
    fitparm[4] = 0;
    break;
  case effnEXP7:
    fitparm[0] = fitparm[2] = fitparm[4] = 0.33*c1[0];
    fitparm[1] = 1;
    fitparm[3] = 10;
    fitparm[5] = 100;
    fitparm[6] = 0;
    break;
  case effnEXP9:
    fitparm[0] = fitparm[2] = fitparm[4] = fitparm[6] = 0.25*c1[0];
    fitparm[1] = 0.1;
    fitparm[3] = 1;
    fitparm[5] = 10;
    fitparm[7] = 100;
    fitparm[8] = 0;
    break;
  default:
    fprintf(out,"Warning: don't know how to initialize the parameters\n");
    for(i=0; (i<nparm); i++)
      fitparm[i] = 1;
  }
  fprintf(out,"Starting parameters:\n");
  for(i=0; (i<nparm); i++) 
    fprintf(out,"a%-2d = %12.5e\n",i+1,fitparm[i]);
  if (do_lmfit(ny,c1,sig,dt,x0,tbeginfit,tendfit,
	       bDebugMode(),efitfn,fitparm,0)) {
    for(i=0; (i<nparm); i++) 
      fprintf(out,"a%-2d = %12.5e\n",i+1,fitparm[i]);
  }
  else {
    fprintf(out,"No solution was found\n");
  }
}
Пример #3
0
static void process_tcaf(int nframes, real dt, int nkc, real **tc, rvec *kfac,
                         real rho, real wt, const char *fn_trans,
                         const char *fn_tca, const char *fn_tc,
                         const char *fn_tcf, const char *fn_cub,
                         const char *fn_vk, const gmx_output_env_t *oenv)
{
    FILE  *fp, *fp_vk, *fp_cub = NULL;
    int    nk, ntc;
    real **tcaf, **tcafc = NULL, eta, *sig;
    int    i, j, k, kc;
    int    ncorr;
    double fitparms[3];

    nk  = kset_c[nkc];
    ntc = nk*NPK;

    if (fn_trans)
    {
        fp = xvgropen(fn_trans, "Transverse Current", "Time (ps)", "TC (nm/ps)",
                      oenv);
        for (i = 0; i < nframes; i++)
        {
            fprintf(fp, "%g", i*dt);
            for (j = 0; j < ntc; j++)
            {
                fprintf(fp, " %g", tc[j][i]);
            }
            fprintf(fp, "\n");
        }
        xvgrclose(fp);
        do_view(oenv, fn_trans, "-nxy");
    }

    ncorr = (nframes+1)/2;
    if (ncorr > static_cast<int>(5*wt/dt+0.5))
    {
        ncorr = static_cast<int>(5*wt/dt+0.5)+1;
    }
    snew(tcaf, nk);
    for (k = 0; k < nk; k++)
    {
        snew(tcaf[k], ncorr);
    }
    if (fn_cub)
    {
        snew(tcafc, nkc);
        for (k = 0; k < nkc; k++)
        {
            snew(tcafc[k], ncorr);
        }
    }
    snew(sig, ncorr);
    for (i = 0; i < ncorr; i++)
    {
        sig[i] = std::exp(0.5*i*dt/wt);
    }

    low_do_autocorr(fn_tca, oenv, "Transverse Current Autocorrelation Functions",
                    nframes, ntc, ncorr, tc, dt, eacNormal,
                    1, FALSE, FALSE, FALSE, 0, 0, 0);
    do_view(oenv, fn_tca, "-nxy");

    fp = xvgropen(fn_tc, "Transverse Current Autocorrelation Functions",
                  "Time (ps)", "TCAF", oenv);
    for (i = 0; i < ncorr; i++)
    {
        kc = 0;
        fprintf(fp, "%g", i*dt);
        for (k = 0; k < nk; k++)
        {
            for (j = 0; j < NPK; j++)
            {
                tcaf[k][i] += tc[NPK*k+j][i];
            }
            if (fn_cub)
            {
                for (j = 0; j < NPK; j++)
                {
                    tcafc[kc][i] += tc[NPK*k+j][i];
                }
            }
            if (i == 0)
            {
                fprintf(fp, " %g", 1.0);
            }
            else
            {
                tcaf[k][i] /= tcaf[k][0];
                fprintf(fp, " %g", tcaf[k][i]);
            }
            if (k+1 == kset_c[kc+1])
            {
                kc++;
            }
        }
        fprintf(fp, "\n");
    }
    xvgrclose(fp);
    do_view(oenv, fn_tc, "-nxy");

    if (fn_cub)
    {
        fp_cub = xvgropen(fn_cub, "TCAFs and fits", "Time (ps)", "TCAF", oenv);
        for (kc = 0; kc < nkc; kc++)
        {
            fprintf(fp_cub, "%g %g\n", 0.0, 1.0);
            for (i = 1; i < ncorr; i++)
            {
                tcafc[kc][i] /= tcafc[kc][0];
                fprintf(fp_cub, "%g %g\n", i*dt, tcafc[kc][i]);
            }
            fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            tcafc[kc][0] = 1.0;
        }
    }

    fp_vk = xvgropen(fn_vk, "Fits", "k (nm\\S-1\\N)",
                     "\\8h\\4 (10\\S-3\\N kg m\\S-1\\N s\\S-1\\N)", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp_vk, "@    s0 symbol 2\n");
        fprintf(fp_vk, "@    s0 symbol color 1\n");
        fprintf(fp_vk, "@    s0 linestyle 0\n");
        if (fn_cub)
        {
            fprintf(fp_vk, "@    s1 symbol 3\n");
            fprintf(fp_vk, "@    s1 symbol color 2\n");
        }
    }
    fp = xvgropen(fn_tcf, "TCAF Fits", "Time (ps)", "", oenv);
    for (k = 0; k < nk; k++)
    {
        tcaf[k][0]   = 1.0;
        fitparms[0]  = 1;
        fitparms[1]  = 1;
        do_lmfit(ncorr, tcaf[k], sig, dt, 0, 0, ncorr*dt,
                 oenv, bDebugMode(), effnVAC, fitparms, 0, NULL);
        eta = 1000*fitparms[1]*rho/
            (4*fitparms[0]*PICO*norm2(kfac[k])/(NANO*NANO));
        fprintf(stdout, "k %6.3f  tau %6.3f  eta %8.5f 10^-3 kg/(m s)\n",
                norm(kfac[k]), fitparms[0], eta);
        fprintf(fp_vk, "%6.3f %g\n", norm(kfac[k]), eta);
        for (i = 0; i < ncorr; i++)
        {
            fprintf(fp, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt));
        }
        fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
    }
    xvgrclose(fp);
    do_view(oenv, fn_tcf, "-nxy");

    if (fn_cub)
    {
        fprintf(stdout, "Averaged over k-vectors:\n");
        fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        for (k = 0; k < nkc; k++)
        {
            tcafc[k][0]  = 1.0;
            fitparms[0]  = 1;
            fitparms[1]  = 1;
            do_lmfit(ncorr, tcafc[k], sig, dt, 0, 0, ncorr*dt,
                     oenv, bDebugMode(), effnVAC, fitparms, 0, NULL);
            eta = 1000*fitparms[1]*rho/
                (4*fitparms[0]*PICO*norm2(kfac[kset_c[k]])/(NANO*NANO));
            fprintf(stdout,
                    "k %6.3f  tau %6.3f  Omega %6.3f  eta %8.5f 10^-3 kg/(m s)\n",
                    norm(kfac[kset_c[k]]), fitparms[0], fitparms[1], eta);
            fprintf(fp_vk, "%6.3f %g\n", norm(kfac[kset_c[k]]), eta);
            for (i = 0; i < ncorr; i++)
            {
                fprintf(fp_cub, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt));
            }
            fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        }
        fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        xvgrclose(fp_cub);
        do_view(oenv, fn_cub, "-nxy");
    }
    xvgrclose(fp_vk);
    do_view(oenv, fn_vk, "-nxy");
}
Пример #4
0
static void estimate_error(char *eefile,int nb_min,int resol,int n,int nset,
                           double *av,double *sig,real **val,real dt,
                           bool bFitAc,bool bSingleExpFit,bool bAllowNegLTCorr)
{
    FILE   *fp;
    int    bs,prev_bs,nbs,nb;
    real   spacing,nbr;
    int    s,i,j;
    double blav,var;
    char   **leg;
    real   *tbs,*ybs,rtmp,dens,*fitsig,twooe,tau1_est,tau_sig;
    real   fitparm[4];
    real   ee,a,tau1,tau2;
    
    if (n < 4)
    {
      fprintf(stdout,"The number of points is smaller than 4, can not make an error estimate\n");
      
      return;
    }
    
    fp = xvgropen(eefile,"Error estimates",
                  "Block size (time)","Error estimate");
    if (bPrintXvgrCodes())
    {
        fprintf(fp,
                "@ subtitle \"using block averaging, total time %g (%d points)\"\n",
                (n-1)*dt,n);
    }
    snew(leg,2*nset);
    xvgr_legend(fp,2*nset,leg);
    sfree(leg);

    spacing = pow(2,1.0/resol);
    snew(tbs,n);
    snew(ybs,n);
    snew(fitsig,n);
    for(s=0; s<nset; s++)
    {
        nbs = 0;
        prev_bs = 0;
        nbr = nb_min;
        while (nbr <= n)
        {
            bs = n/(int)nbr;
            if (bs != prev_bs)
            {
                nb = n/bs;
                var = 0;
                for(i=0; i<nb; i++)
                {
                    blav=0;
                    for (j=0; j<bs; j++)
                    {
                        blav += val[s][bs*i+j];
                    }
                    var += sqr(av[s] - blav/bs);
                }
                tbs[nbs] = bs*dt;
                if (sig[s] == 0)
                {
                    ybs[nbs] = 0;
                }
                else
                {
                    ybs[nbs] = var/(nb*(nb-1.0))*(n*dt)/(sig[s]*sig[s]);
                }
                nbs++;
            }
            nbr *= spacing;
            nb = (int)(nbr+0.5);
            prev_bs = bs;
        }

        if (sig[s] == 0)
        {
            ee   = 0;
            a    = 1;
            tau1 = 0;
            tau2 = 0;
        }
        else
        {
            for(i=0; i<nbs/2; i++)
            {
                rtmp         = tbs[i];
                tbs[i]       = tbs[nbs-1-i];
                tbs[nbs-1-i] = rtmp;
                rtmp         = ybs[i];
                ybs[i]       = ybs[nbs-1-i];
                ybs[nbs-1-i] = rtmp;
            }
            /* The initial slope of the normalized ybs^2 is 1.
             * For a single exponential autocorrelation: ybs(tau1) = 2/e tau1
             * From this we take our initial guess for tau1.
             */
            twooe = 2/exp(1);
            i = -1;
            do
            {
                i++;
                tau1_est = tbs[i];
            } while (i < nbs - 1 &&
                     (ybs[i] > ybs[i+1] || ybs[i] > twooe*tau1_est));
            
            if (ybs[0] > ybs[1])
            {
                fprintf(stdout,"Data set %d has strange time correlations:\n"
                        "the std. error using single points is larger than that of blocks of 2 points\n"
                        "The error estimate might be inaccurate, check the fit\n",
                        s+1);
                /* Use the total time as tau for the fitting weights */
                tau_sig = (n - 1)*dt;
            }
            else
            {
                tau_sig = tau1_est;
            }
            
            if (debug)
            {
                fprintf(debug,"set %d tau1 estimate %f\n",s+1,tau1_est);
            }
            
            /* Generate more or less appropriate sigma's,
             * also taking the density of points into account.
             */
            for(i=0; i<nbs; i++)
            {
                if (i == 0)
                {
                    dens = tbs[1]/tbs[0] - 1;
                }
                else if (i == nbs-1)
                {
                    dens = tbs[nbs-1]/tbs[nbs-2] - 1;
                }
                else
                {
                    dens = 0.5*(tbs[i+1]/tbs[i-1] - 1);
                }
                fitsig[i] = sqrt((tau_sig + tbs[i])/dens);
            }
            
            if (!bSingleExpFit)
            {
                fitparm[0] = tau1_est;
                fitparm[1] = 0.95;
                /* We set the initial guess for tau2
                 * to halfway between tau1_est and the total time (on log scale).
                 */
                fitparm[2] = sqrt(tau1_est*(n-1)*dt);
                do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,0);
                fitparm[3] = 1-fitparm[1];
            }
            if (bSingleExpFit || fitparm[0]<0 || fitparm[2]<0 || fitparm[1]<0
                || (fitparm[1]>1 && !bAllowNegLTCorr) || fitparm[2]>(n-1)*dt)
            {
                if (!bSingleExpFit)
                {
                    if (fitparm[2] > (n-1)*dt)
                    {
                        fprintf(stdout,
                                "Warning: tau2 is longer than the length of the data (%g)\n"
                                "         the statistics might be bad\n",
                                (n-1)*dt);
                    }
                    else
                    {
                        fprintf(stdout,"a fitted parameter is negative\n");
                    }
                    fprintf(stdout,"invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
                            sig[s]*anal_ee_inf(fitparm,n*dt),
                            fitparm[1],fitparm[0],fitparm[2]);
                    /* Do a fit with tau2 fixed at the total time.
                     * One could also choose any other large value for tau2.
                     */
                    fitparm[0] = tau1_est;
                    fitparm[1] = 0.95;
                    fitparm[2] = (n-1)*dt;
                    fprintf(stderr,"Will fix tau2 at the total time: %g\n",fitparm[2]);
                    do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,4);
                    fitparm[3] = 1-fitparm[1];
                }
                if (bSingleExpFit || fitparm[0]<0 || fitparm[1]<0
                    || (fitparm[1]>1 && !bAllowNegLTCorr))
                {
                    if (!bSingleExpFit) {
                        fprintf(stdout,"a fitted parameter is negative\n");
                        fprintf(stdout,"invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
                                sig[s]*anal_ee_inf(fitparm,n*dt),
                                fitparm[1],fitparm[0],fitparm[2]);
                    }
                    /* Do a single exponential fit */
                    fprintf(stderr,"Will use a single exponential fit for set %d\n",s+1);
                    fitparm[0] = tau1_est;
                    fitparm[1] = 1.0;
                    fitparm[2] = 0.0;
                    do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,6);
                    fitparm[3] = 1-fitparm[1];
                }
            }
            ee   = sig[s]*anal_ee_inf(fitparm,n*dt);
            a    = fitparm[1];
            tau1 = fitparm[0];
            tau2 = fitparm[2];
        }
        fprintf(stdout,"Set %3d:  err.est. %g  a %g  tau1 %g  tau2 %g\n",
                s+1,ee,a,tau1,tau2);
        fprintf(fp,"@ legend string %d \"av %f\"\n",2*s,av[s]);
        fprintf(fp,"@ legend string %d \"ee %6g\"\n",
                2*s+1,sig[s]*anal_ee_inf(fitparm,n*dt));
        for(i=0; i<nbs; i++)
        {
            fprintf(fp,"%g %g %g\n",tbs[i],sig[s]*sqrt(ybs[i]/(n*dt)),
                    sig[s]*sqrt(fit_function(effnERREST,fitparm,tbs[i])/(n*dt)));
        }
        
        if (bFitAc)
        {
            int fitlen;
            real *ac,acint,ac_fit[4];
            
            snew(ac,n);
            for(i=0; i<n; i++) {
                ac[i] = val[s][i] - av[s];
                if (i > 0)
                    fitsig[i] = sqrt(i);
                else
                    fitsig[i] = 1;
            }
            low_do_autocorr(NULL,NULL,n,1,-1,&ac,
                            dt,eacNormal,1,FALSE,TRUE,
                            FALSE,0,0,effnNONE,0);
            
            fitlen = n/nb_min;
            
            /* Integrate ACF only up to fitlen/2 to avoid integrating noise */ 
            acint = 0.5*ac[0];
            for(i=1; i<=fitlen/2; i++)
            {
                acint += ac[i];
            }
            acint *= dt;
            
            /* Generate more or less appropriate sigma's */
            for(i=0; i<=fitlen; i++)
            {
                fitsig[i] = sqrt(acint + dt*i);
            }
            
            ac_fit[0] = 0.5*acint;
            ac_fit[1] = 0.95;
            ac_fit[2] = 10*acint;
            do_lmfit(n/nb_min,ac,fitsig,dt,0,0,fitlen*dt,
                     bDebugMode(),effnEXP3,ac_fit,0);
            ac_fit[3] = 1 - ac_fit[1];
            
            fprintf(stdout,"Set %3d:  ac erest %g  a %g  tau1 %g  tau2 %g\n",
                    s+1,sig[s]*anal_ee_inf(ac_fit,n*dt),
                    ac_fit[1],ac_fit[0],ac_fit[2]);
            
            fprintf(fp,"&\n");
            for(i=0; i<nbs; i++)
            {
                fprintf(fp,"%g %g\n",tbs[i],
                        sig[s]*sqrt(fit_function(effnERREST,ac_fit,tbs[i]))/(n*dt));
            }
            
            sfree(ac);
        }
        if (s < nset-1)
        {
            fprintf(fp,"&\n");
        }
    }
    sfree(fitsig);
    sfree(ybs);
    sfree(tbs);
    fclose(fp);
}
Пример #5
0
real fit_acf(int ncorr, int fitfn, const gmx_output_env_t *oenv, gmx_bool bVerbose,
             real tbeginfit, real tendfit, real dt, real c1[], real *fit)
{
    double      fitparm[3];
    double      tStart, tail_corr, sum, sumtot = 0, c_start, ct_estimate;
    real       *sig;
    int         i, j, jmax, nf_int;
    gmx_bool    bPrint;

    bPrint = bVerbose || bDebugMode();

    if (bPrint)
    {
        printf("COR:\n");
    }

    if (tendfit <= 0)
    {
        tendfit = ncorr*dt;
    }
    nf_int = std::min(ncorr, (int)(tendfit/dt));
    sum    = print_and_integrate(debug, nf_int, dt, c1, NULL, 1);

    if (bPrint)
    {
        printf("COR: Correlation time (plain integral from %6.3f to %6.3f ps) = %8.5f ps\n",
               0.0, dt*nf_int, sum);
        printf("COR: Relaxation times are computed as fit to an exponential:\n");
        printf("COR:   %s\n", effnDescription(fitfn));
        printf("COR: Fit to correlation function from %6.3f ps to %6.3f ps, results in a\n", tbeginfit, std::min(ncorr*dt, tendfit));
    }

    tStart = 0;
    if (bPrint)
    {
        printf("COR:%11s%11s%11s%11s%11s%11s%11s\n",
               "Fit from", "Integral", "Tail Value", "Sum (ps)", " a1 (ps)",
               (effnNparams(fitfn) >= 2) ? " a2 ()" : "",
               (effnNparams(fitfn) >= 3) ? " a3 (ps)" : "");
    }

    snew(sig, ncorr);

    if (tbeginfit > 0)
    {
        jmax = 3;
    }
    else
    {
        jmax = 1;
    }
    for (j = 0; ((j < jmax) && (tStart < tendfit) && (tStart < ncorr*dt)); j++)
    {
        /* Estimate the correlation time for better fitting */
        c_start     = -1;
        ct_estimate = 0;
        for (i = 0; (i < ncorr) && (dt*i < tStart || c1[i] > 0); i++)
        {
            if (c_start < 0)
            {
                if (dt*i >= tStart)
                {
                    c_start     = c1[i];
                    ct_estimate = 0.5*c1[i];
                }
            }
            else
            {
                ct_estimate += c1[i];
            }
        }
        if (c_start > 0)
        {
            ct_estimate *= dt/c_start;
        }
        else
        {
            /* The data is strange, so we need to choose somehting */
            ct_estimate = tendfit;
        }
        if (debug)
        {
            fprintf(debug, "tStart %g ct_estimate: %g\n", tStart, ct_estimate);
        }

        if (fitfn == effnEXPEXP)
        {
            fitparm[0] = 0.002*ncorr*dt;
            fitparm[1] = 0.95;
            fitparm[2] = 0.2*ncorr*dt;
        }
        else
        {
            /* Good initial guess, this increases the probability of convergence */
            fitparm[0] = ct_estimate;
            fitparm[1] = 1.0;
            fitparm[2] = 1.0;
        }

        /* Generate more or less appropriate sigma's */
        for (i = 0; i < ncorr; i++)
        {
            sig[i] = sqrt(ct_estimate+dt*i);
        }

        nf_int    = std::min(ncorr, (int)((tStart+1e-4)/dt));
        sum       = print_and_integrate(debug, nf_int, dt, c1, NULL, 1);
        tail_corr = do_lmfit(ncorr, c1, sig, dt, NULL, tStart, tendfit, oenv,
                             bDebugMode(), fitfn, fitparm, 0, NULL);
        sumtot = sum+tail_corr;
        if (fit && ((jmax == 1) || (j == 1)))
        {
            double mfp[3];
            for (i = 0; (i < 3); i++)
            {
                mfp[i] = fitparm[i];
            }
            for (i = 0; (i < ncorr); i++)
            {
                fit[i] = lmcurves[fitfn](i*dt, mfp);
            }
        }
        if (bPrint)
        {
            printf("COR:%11.4e%11.4e%11.4e%11.4e", tStart, sum, tail_corr, sumtot);
            for (i = 0; (i < effnNparams(fitfn)); i++)
            {
                printf(" %11.4e", fitparm[i]);
            }
            printf("\n");
        }
        tStart += tbeginfit;
    }
    sfree(sig);

    return sumtot;
}
Пример #6
0
static void do_fit(FILE *out, int n, gmx_bool bYdy,
                   int ny, real *x0, real **val,
                   int npargs, t_pargs *ppa, const gmx_output_env_t *oenv,
                   const char *fn_fitted)
{
    real   *c1 = NULL, *sig = NULL;
    double *fitparm;
    real    tendfit, tbeginfit;
    int     i, efitfn, nparm;

    efitfn = get_acffitfn();
    nparm  = effnNparams(efitfn);
    fprintf(out, "Will fit to the following function:\n");
    fprintf(out, "%s\n", effnDescription(efitfn));
    c1 = val[n];
    if (bYdy)
    {
        c1  = val[n];
        sig = val[n+1];
        fprintf(out, "Using two columns as y and sigma values\n");
    }
    else
    {
        snew(sig, ny);
    }
    if (opt2parg_bSet("-beginfit", npargs, ppa))
    {
        tbeginfit = opt2parg_real("-beginfit", npargs, ppa);
    }
    else
    {
        tbeginfit = x0[0];
    }
    if (opt2parg_bSet("-endfit", npargs, ppa))
    {
        tendfit   = opt2parg_real("-endfit", npargs, ppa);
    }
    else
    {
        tendfit   = x0[ny-1];
    }

    snew(fitparm, nparm);
    switch (efitfn)
    {
        case effnEXP1:
            fitparm[0] = 0.5;
            break;
        case effnEXP2:
            fitparm[0] = 0.5;
            fitparm[1] = c1[0];
            break;
        case effnEXPEXP:
            fitparm[0] = 1.0;
            fitparm[1] = 0.5*c1[0];
            fitparm[2] = 10.0;
            break;
        case effnEXP5:
            fitparm[0] = fitparm[2] = 0.5*c1[0];
            fitparm[1] = 10;
            fitparm[3] = 40;
            fitparm[4] = 0;
            break;
        case effnEXP7:
            fitparm[0] = fitparm[2] = fitparm[4] = 0.33*c1[0];
            fitparm[1] = 1;
            fitparm[3] = 10;
            fitparm[5] = 100;
            fitparm[6] = 0;
            break;
        case effnEXP9:
            fitparm[0] = fitparm[2] = fitparm[4] = fitparm[6] = 0.25*c1[0];
            fitparm[1] = 0.1;
            fitparm[3] = 1;
            fitparm[5] = 10;
            fitparm[7] = 100;
            fitparm[8] = 0;
            break;
        default:
            fprintf(out, "Warning: don't know how to initialize the parameters\n");
            for (i = 0; (i < nparm); i++)
            {
                fitparm[i] = 1;
            }
    }
    fprintf(out, "Starting parameters:\n");
    for (i = 0; (i < nparm); i++)
    {
        fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]);
    }
    if (do_lmfit(ny, c1, sig, 0, x0, tbeginfit, tendfit,
                 oenv, bDebugMode(), efitfn, fitparm, 0,
                 fn_fitted) > 0)
    {
        for (i = 0; (i < nparm); i++)
        {
            fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]);
        }
    }
    else
    {
        fprintf(out, "No solution was found\n");
    }
}
Пример #7
0
static void interfaces_txy (real ****Densmap, int xslices, int yslices, int zslices,
                            int tblocks, real binwidth, int method,
                            real dens1, real dens2, t_interf ****intf1,
                            t_interf ****intf2, const gmx_output_env_t *oenv)
{
    /*Returns two pointers to 3D arrays of t_interf structs containing (position,thickness) of the interface(s)*/
    FILE         *xvg;
    real         *zDensavg; /* zDensavg[z]*/
    int           i, j, k, n;
    int           xysize;
    int           ndx1, ndx2, *zperm;
    real          densmid;
    real          splitpoint, startpoint, endpoint;
    real         *sigma1, *sigma2;
    double        beginfit1[4];
    double        beginfit2[4];
    double       *fit1 = NULL, *fit2 = NULL;
    const double *avgfit1;
    const double *avgfit2;
    const real    onehalf = 1.00/2.00;
    t_interf   ***int1    = NULL, ***int2 = NULL; /*Interface matrices [t][x,y] - last index in row-major order*/
    /*Create int1(t,xy) and int2(t,xy) arrays with correct number of interf_t elements*/
    xysize = xslices*yslices;
    snew(int1, tblocks);
    snew(int2, tblocks);
    for (i = 0; i < tblocks; i++)
    {
        snew(int1[i], xysize);
        snew(int2[i], xysize);
        for (j = 0; j < xysize; j++)
        {
            snew(int1[i][j], 1);
            snew(int2[i][j], 1);
            init_interf(int1[i][j]);
            init_interf(int2[i][j]);
        }
    }

    if (method == methBISECT)
    {
        densmid = onehalf*(dens1+dens2);
        snew(zperm, zslices);
        for (n = 0; n < tblocks; n++)
        {
            for (i = 0; i < xslices; i++)
            {
                for (j = 0; j < yslices; j++)
                {
                    rangeArray(zperm, zslices); /*reset permutation array to identity*/
                    /*Binsearch returns slice-nr where the order param is  <= setpoint sgmid*/
                    ndx1 = start_binsearch(Densmap[n][i][j], zperm, 0, zslices/2-1, densmid, 1);
                    ndx2 = start_binsearch(Densmap[n][i][j], zperm, zslices/2, zslices-1, densmid, -1);

                    /* Linear interpolation (for use later if time allows)
                     * rho_1s= Densmap[n][i][j][zperm[ndx1]]
                     * rho_1e =Densmap[n][i][j][zperm[ndx1+1]] - in worst case might be far off
                     * rho_2s =Densmap[n][i][j][zperm[ndx2+1]]
                     * rho_2e =Densmap[n][i][j][zperm[ndx2]]
                     * For 1st interface we have:
                       densl= Densmap[n][i][j][zperm[ndx1]];
                       densr= Densmap[n][i][j][zperm[ndx1+1]];
                       alpha=(densmid-densl)/(densr-densl);
                       deltandx=zperm[ndx1+1]-zperm[ndx1];

                       if(debug){
                       printf("Alpha, Deltandx  %f %i\n", alpha,deltandx);
                       }
                       if(abs(alpha)>1.0 || abs(deltandx)>3){
                       pos=zperm[ndx1];
                       spread=-1;
                       }
                       else {
                       pos=zperm[ndx1]+alpha*deltandx;
                       spread=binwidth*deltandx;
                       }
                     * For the 2nd interface  can use the same formulation, since alpha should become negative ie:
                     * alpha=(densmid-Densmap[n][i][j][zperm[ndx2]])/(Densmap[n][i][j][zperm[nxd2+1]]-Densmap[n][i][j][zperm[ndx2]]);
                     * deltandx=zperm[ndx2+1]-zperm[ndx2];
                     * pos=zperm[ndx2]+alpha*deltandx;   */

                    /*After filtering we use the direct approach	*/
                    int1[n][j+(i*yslices)]->Z = (zperm[ndx1]+onehalf)*binwidth;
                    int1[n][j+(i*yslices)]->t = binwidth;
                    int2[n][j+(i*yslices)]->Z = (zperm[ndx2]+onehalf)*binwidth;
                    int2[n][j+(i*yslices)]->t = binwidth;
                }
            }
        }
    }

    if (method == methFUNCFIT)
    {
        /*Assume a box divided in 2 along midpoint of z for starters*/
        startpoint = 0.0;
        endpoint   = binwidth*zslices;
        splitpoint = (startpoint+endpoint)/2.0;
        /*Initial fit proposals*/
        beginfit1[0] = dens1;
        beginfit1[1] = dens2;
        beginfit1[2] = (splitpoint/2);
        beginfit1[3] = 0.5;

        beginfit2[0] = dens2;
        beginfit2[1] = dens1;
        beginfit2[2] = (3*splitpoint/2);
        beginfit2[3] = 0.5;

        snew(zDensavg, zslices);
        snew(sigma1, zslices);
        snew(sigma2, zslices);

        for (k = 0; k < zslices; k++)
        {
            sigma1[k] = sigma2[k] = 1;
        }
        /*Calculate average density along z - avoid smoothing by using coarse-grained-mesh*/
        for (k = 0; k < zslices; k++)
        {
            for (n = 0; n < tblocks; n++)
            {
                for (i = 0; i < xslices; i++)
                {
                    for (j = 0; j < yslices; j++)
                    {
                        zDensavg[k] += (Densmap[n][i][j][k]/(xslices*yslices*tblocks));
                    }
                }
            }
        }

        if (debug)
        {
            xvg = xvgropen("DensprofileonZ.xvg", "Averaged Densityprofile on Z", "z[nm]", "Density[kg/m^3]", oenv);
            for (k = 0; k < zslices; k++)
            {
                fprintf(xvg, "%4f.3   %8f.4\n", k*binwidth, zDensavg[k]);
            }
            xvgrclose(xvg);
        }

        /*Fit average density in z over whole trajectory to obtain tentative fit-parameters in fit1 and fit2*/

        /*Fit 1st half of box*/
        do_lmfit(zslices, zDensavg, sigma1, binwidth, NULL, startpoint, splitpoint, oenv, FALSE, effnERF, beginfit1, 8, NULL);
        /*Fit 2nd half of box*/
        do_lmfit(zslices, zDensavg, sigma2, binwidth, NULL, splitpoint, endpoint, oenv, FALSE, effnERF, beginfit2, 8, NULL);

        /*Initialise the const arrays for storing the average fit parameters*/
        avgfit1 = beginfit1;
        avgfit2 = beginfit2;



        /*Now do fit over each x  y and t slice to get Zint(x,y,t) - loop is very large, we potentially should average over time directly*/
        for (n = 0; n < tblocks; n++)
        {
            for (i = 0; i < xslices; i++)
            {
                for (j = 0; j < yslices; j++)
                {
                    /*Reinitialise fit for each mesh-point*/
                    srenew(fit1, 4);
                    srenew(fit2, 4);
                    for (k = 0; k < 4; k++)
                    {
                        fit1[k] = avgfit1[k];
                        fit2[k] = avgfit2[k];
                    }
                    /*Now fit and store in structures in row-major order int[n][i][j]*/
                    do_lmfit(zslices, Densmap[n][i][j], sigma1, binwidth, NULL, startpoint, splitpoint, oenv, FALSE, effnERF, fit1, 0, NULL);
                    int1[n][j+(yslices*i)]->Z = fit1[2];
                    int1[n][j+(yslices*i)]->t = fit1[3];
                    do_lmfit(zslices, Densmap[n][i][j], sigma2, binwidth, NULL, splitpoint, endpoint, oenv, FALSE, effnERF, fit2, 0, NULL);
                    int2[n][j+(yslices*i)]->Z = fit2[2];
                    int2[n][j+(yslices*i)]->t = fit2[3];
                }
            }
        }
    }


    *intf1 = int1;
    *intf2 = int2;

}
Пример #8
0
real fit_acf(int ncorr,int fitfn,const output_env_t oenv,gmx_bool bVerbose,
	     real tbeginfit,real tendfit,real dt,real c1[],real *fit)
{
  real    fitparm[3];
  real    tStart,tail_corr,sum,sumtot=0,ct_estimate,*sig;
  int     i,j,jmax,nf_int;
  gmx_bool    bPrint;

  bPrint = bVerbose || bDebugMode();

  if (bPrint) printf("COR:\n");    
  
  if (tendfit <= 0)
    tendfit = ncorr*dt;
  nf_int = min(ncorr,(int)(tendfit/dt));
  sum    = print_and_integrate(debug,nf_int,dt,c1,NULL,1);

  /* Estimate the correlation time for better fitting */
  ct_estimate = 0.5*c1[0];
  for(i=1; (i<ncorr) && (c1[i]>0); i++)
      ct_estimate += c1[i];
  ct_estimate *= dt/c1[0];

  if (bPrint) {
    printf("COR: Correlation time (plain integral from %6.3f to %6.3f ps) = %8.5f ps\n", 
	   0.0,dt*nf_int,sum);
    printf("COR: Relaxation times are computed as fit to an exponential:\n");
    printf("COR:   %s\n",longs_ffn[fitfn]);
    printf("COR: Fit to correlation function from %6.3f ps to %6.3f ps, results in a\n",tbeginfit,min(ncorr*dt,tendfit));
  }
  
  tStart = 0;
  if (bPrint) 
    printf("COR:%11s%11s%11s%11s%11s%11s%11s\n",
	   "Fit from","Integral","Tail Value","Sum (ps)"," a1 (ps)",
	   (nfp_ffn[fitfn]>=2) ? " a2 ()" : "",
	   (nfp_ffn[fitfn]>=3) ? " a3 (ps)" : "");
  if (tbeginfit > 0)
    jmax = 3;
  else
    jmax = 1;
  if (fitfn == effnEXP3) {
    fitparm[0] = 0.002*ncorr*dt;
    fitparm[1] = 0.95;
    fitparm[2] = 0.2*ncorr*dt;
  } else {
    /* Good initial guess, this increases the probability of convergence */
    fitparm[0] = ct_estimate;
    fitparm[1] = 1.0;
    fitparm[2] = 1.0;
  }

  /* Generate more or less appropriate sigma's */
  snew(sig,ncorr);
  for(i=0; i<ncorr; i++)
    sig[i] = sqrt(ct_estimate+dt*i);

  for(j=0; ((j<jmax) && (tStart < tendfit)); j++) {
    /* Use the previous fitparm as starting values for the next fit */
    nf_int = min(ncorr,(int)((tStart+1e-4)/dt));
    sum    = print_and_integrate(debug,nf_int,dt,c1,NULL,1);
    tail_corr = do_lmfit(ncorr,c1,sig,dt,NULL,tStart,tendfit,oenv,
			 bDebugMode(),fitfn,fitparm,0);
    sumtot = sum+tail_corr;
    if (fit && ((jmax == 1) || (j == 1)))
      for(i=0; (i<ncorr); i++)
	fit[i] = fit_function(fitfn,fitparm,i*dt);
    if (bPrint) {
      printf("COR:%11.4e%11.4e%11.4e%11.4e",tStart,sum,tail_corr,sumtot);
      for(i=0; (i<nfp_ffn[fitfn]); i++)
	printf(" %11.4e",fitparm[i]);
      printf("\n");
    }
    tStart += tbeginfit;
  }
  sfree(sig);

  return sumtot;
}