real numerical_deriv(int nx,real x[],real y[],real fity[],real combined[],real dy[],
		     real tendInt,int nsmooth)
{
  FILE *tmpfp;
  int  i,nbegin,i0,i1;
  real fac,fx,fy,integralSmth;
  
  nbegin = calc_nbegin(nx,x,tendInt);
  if (nsmooth == 0) {
    for(i=0; (i<nbegin); i++)
      combined[i]=y[i];
    fac = y[nbegin]/fity[nbegin];
    printf("scaling fitted curve by %g\n",fac);
    for(i=nbegin; (i<nx); i++)
      combined[i]=fity[i]*fac;
  }
  else {
    i0 = max(0,nbegin);
    i1 = min(nx-1,nbegin+nsmooth);
    printf("Making smooth transition from %d thru %d\n",i0,i1);
    for(i=0; (i<i0); i++)
      combined[i]=y[i];
    for(i=i0; (i<=i1); i++) {
      fx = (i1-i)/(real)(i1-i0);
      fy = (i-i0)/(real)(i1-i0);
      if (debug)
	fprintf(debug,"x: %g factors for smoothing: %10g %10g\n",x[i],fx,fy);
      combined[i] = fx*y[i] + fy*fity[i];
    } 
    for(i=i1+1; (i<nx); i++)
      combined[i]=fity[i];
  }
  
  tmpfp = ffopen("integral_smth.xvg","w");
  integralSmth=print_and_integrate(tmpfp,nx,x[1]-x[0],combined,NULL,1);
  printf("SMOOTH integral = %10.5e\n",integralSmth);

  dy[0] = (combined[1]-combined[0])/(x[1]-x[0]);
  for(i=1; (i<nx-1); i++) {
    dy[i] = (combined[i+1]-combined[i-1])/(x[i+1]-x[i-1]);
  }
  dy[nx-1] = (combined[nx-1]-combined[nx-2])/(x[nx-1]-x[nx-2]);
  
  for(i=0; (i<nx); i++)
    dy[i] *= -1;
    
  return integralSmth;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
0
void low_do_autocorr(const char *fn,const output_env_t oenv,const char *title,
		     int nframes,int nitem,int nout,real **c1,
		     real dt,unsigned long mode,int nrestart,
		     gmx_bool bAver,gmx_bool bNormalize,
		     gmx_bool bVerbose,real tbeginfit,real tendfit,
		     int eFitFn,int nskip)
{
  FILE    *fp,*gp=NULL;
  int     i,k,nfour;
  real    *csum;
  real    *ctmp,*fit;
  real    c0,sum,Ct2av,Ctav;
  gmx_bool    bFour = acf.bFour;
 
  /* Check flags and parameters */ 
  nout = get_acfnout();
  if (nout == -1)
    nout = acf.nout = (nframes+1)/2;
  else if (nout > nframes)
    nout=nframes;
  
  if (MODE(eacCos) && MODE(eacVector))
    gmx_fatal(FARGS,"Incompatible options bCos && bVector (%s, %d)",
		__FILE__,__LINE__);
  if ((MODE(eacP3) || MODE(eacRcross)) && bFour) {
    fprintf(stderr,"Can't combine mode %lu with FFT, turning off FFT\n",mode);
    bFour = FALSE;
  }
  if (MODE(eacNormal) && MODE(eacVector)) 
    gmx_fatal(FARGS,"Incompatible mode bits: normal and vector (or Legendre)");
    
  /* Print flags and parameters */
  if (bVerbose) {
    printf("Will calculate %s of %d thingies for %d frames\n",
	   title ? title : "autocorrelation",nitem,nframes);
    printf("bAver = %s, bFour = %s bNormalize= %s\n",
	   bool_names[bAver],bool_names[bFour],bool_names[bNormalize]);
    printf("mode = %lu, dt = %g, nrestart = %d\n",mode,dt,nrestart);
  }
  if (bFour) {  
    c0 = log((double)nframes)/log(2.0);
    k  = c0;
    if (k < c0)
      k++;
    k++;
    nfour = 1<<k;
    if (debug)
      fprintf(debug,"Using FFT to calculate %s, #points for FFT = %d\n",
	      title,nfour);
	
    /* Allocate temp arrays */
    snew(csum,nfour);
    snew(ctmp,nfour);
  } else {
    nfour = 0; /* To keep the compiler happy */
    snew(csum,nframes);
    snew(ctmp,nframes);
  }
  
  /* Loop over items (e.g. molecules or dihedrals) 
   * In this loop the actual correlation functions are computed, but without
   * normalizing them.
   */
  k = max(1,pow(10,(int)(log(nitem)/log(100))));
  for(i=0; i<nitem; i++) {
    if (bVerbose && ((i%k==0 || i==nitem-1)))
      fprintf(stderr,"\rThingie %d",i+1);
    
    if (bFour)
      do_four_core(mode,nfour,nframes,nframes,c1[i],csum,ctmp);
    else 
      do_ac_core(nframes,nout,ctmp,c1[i],nrestart,mode);
  }
  if (bVerbose)
    fprintf(stderr,"\n");
  sfree(ctmp);
  sfree(csum);
  
  if (fn) {
    snew(fit,nout);
    fp=xvgropen(fn,title,"Time (ps)","C(t)",oenv);
  } else {
    fit = NULL;
    fp  = NULL;
  }
  if (bAver) {
    if (nitem > 1)
      average_acf(bVerbose,nframes,nitem,c1);
    
    if (bNormalize)
      normalize_acf(nout,c1[0]);
    
    if (eFitFn != effnNONE) {
      fit_acf(nout,eFitFn,oenv,fn!=NULL,tbeginfit,tendfit,dt,c1[0],fit);
      sum = print_and_integrate(fp,nout,dt,c1[0],fit,1);
    } else {
      sum = print_and_integrate(fp,nout,dt,c1[0],NULL,1);
      if (bVerbose)
	printf("Correlation time (integral over corrfn): %g (ps)\n",sum);
    }
  } else {
    /* Not averaging. Normalize individual ACFs */
    Ctav = Ct2av = 0;
    if (debug)
      gp = xvgropen("ct-distr.xvg","Correlation times","item","time (ps)",oenv);
    for(i=0; i<nitem; i++) {
      if (bNormalize)
	normalize_acf(nout,c1[i]);
      if (eFitFn != effnNONE) {
	fit_acf(nout,eFitFn,oenv,fn!=NULL,tbeginfit,tendfit,dt,c1[i],fit);
	sum = print_and_integrate(fp,nout,dt,c1[i],fit,1);
      } else {
	sum = print_and_integrate(fp,nout,dt,c1[i],NULL,1);
	if (debug)
	  fprintf(debug,
		  "CORRelation time (integral over corrfn %d): %g (ps)\n",
		  i,sum);
      }
      Ctav += sum;
      Ct2av += sum*sum;
      if (debug)
	fprintf(gp,"%5d  %.3f\n",i,sum);
    }
    if (debug)
      ffclose(gp);
    if (nitem > 1) {
      Ctav  /= nitem;
      Ct2av /= nitem;
      printf("Average correlation time %.3f Std. Dev. %.3f Error %.3f (ps)\n",
	     Ctav,sqrt((Ct2av - sqr(Ctav))),
	     sqrt((Ct2av - sqr(Ctav))/(nitem-1)));
    }
  }
  if (fp)
    ffclose(fp);
  sfree(fit);
}
Beispiel #5
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;
}
Beispiel #6
0
static void do_rdf(char *fnNDX,char *fnTPS,char *fnTRX,
		   char *fnRDF,char *fnCNRDF, char *fnHQ,
		   bool bCM,char **rdft,bool bXY,bool bPBC,bool bNormalize,
		   real cutoff,real binwidth,real fade,int ng)
{
  FILE       *fp;
  int        status;
  char       outf1[STRLEN],outf2[STRLEN];
  char       title[STRLEN],gtitle[STRLEN];
  int        g,natoms,i,j,k,nbin,j0,j1,n,nframes;
  int        **count;
  char       **grpname;
  int        *isize,isize_cm=0,nrdf=0,max_i,isize0,isize_g;
  atom_id    **index,*index_cm=NULL;
#if (defined SIZEOF_LONG_LONG_INT) && (SIZEOF_LONG_LONG_INT >= 8)    
  long long int *sum;
#else
  double     *sum;
#endif
  real       t,rmax2,cut2,r,r2,invhbinw,normfac;
  real       segvol,spherevol,prev_spherevol,**rdf;
  rvec       *x,dx,*x0=NULL,*x_i1,xi;
  real       *inv_segvol,invvol,invvol_sum,rho;
  bool       *bExcl,bTop,bNonSelfExcl;
  matrix     box,box_pbc;
  int        **npairs;
  atom_id    ix,jx,***pairs;
  t_topology *top=NULL;
  int        ePBC=-1;
  t_block    *mols=NULL;
  t_blocka   *excl;
  t_atom     *atom=NULL;
  t_pbc      pbc;

  int        *is=NULL,**coi=NULL,cur,mol,i1,res,a;

  excl=NULL;
  
  if (fnTPS) {
    snew(top,1);
    bTop=read_tps_conf(fnTPS,title,top,&ePBC,&x,NULL,box,TRUE);
    if (bTop && !bCM)
      /* get exclusions from topology */
      excl = &(top->excls);
  }
  snew(grpname,ng+1);
  snew(isize,ng+1);
  snew(index,ng+1);
  fprintf(stderr,"\nSelect a reference group and %d group%s\n",
	  ng,ng==1?"":"s");
  if (fnTPS) {
    get_index(&(top->atoms),fnNDX,ng+1,isize,index,grpname);
    atom = top->atoms.atom;
  } else {
    rd_index(fnNDX,ng+1,isize,index,grpname);
  }

  if (rdft[0][0] != 'a') {
    /* Split up all the groups in molecules or residues */
    switch (rdft[0][0]) {
    case 'm':
      mols = &top->mols;
      break;
    case 'r':
      atom = top->atoms.atom;
      break;
    default:
      gmx_fatal(FARGS,"Unknown rdf option '%s'",rdft[0]);
    }
    snew(is,ng+1);
    snew(coi,ng+1);
    for(g=(bCM ? 1 : 0); g<ng+1; g++) {
      snew(coi[g],isize[g]+1);
      is[g] = 0;
      cur = -1;
      mol = 0;
      for(i=0; i<isize[g]; i++) {
	a = index[g][i];
	if (rdft[0][0] == 'm') {
	  /* Check if the molecule number has changed */
	  i1 = mols->index[mol+1];
	  while(a >= i1) {
	    mol++;
	    i1 = mols->index[mol+1];
	  }
	  if (mol != cur) {
	    coi[g][is[g]++] = i;
	    cur = mol;
	  }
	} else if (rdft[0][0] == 'r') {
	  /* Check if the residue number has changed */
	  res = atom[a].resnr;
	  if (res != cur) {
	    coi[g][is[g]++] = i;
	    cur = res;
	  }
	}
      }
      coi[g][is[g]] = i;
      srenew(coi[g],is[g]+1);
      printf("Group '%s' of %d atoms consists of %d %s\n",
	     grpname[g],isize[g],is[g],
	     (rdft[0][0]=='m' ? "molecules" : "residues"));
    }
  } else if (bCM) {
    snew(is,1);
    snew(coi,1);
  }
  
  if (bCM) {
    is[0] = 1;
    snew(coi[0],is[0]+1);
    coi[0][0] = 0;
    coi[0][1] = isize[0];
    isize0 = is[0];
    snew(x0,isize0);
  } else if (rdft[0][0] != 'a') {
    isize0 = is[0];
    snew(x0,isize0);
  } else {
    isize0 = isize[0];
  }
  
  natoms=read_first_x(&status,fnTRX,&t,&x,box);
  if ( !natoms )
    gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
  if (fnTPS)
    /* check with topology */
    if ( natoms > top->atoms.nr ) 
      gmx_fatal(FARGS,"Trajectory (%d atoms) does not match topology (%d atoms)",
		  natoms,top->atoms.nr);
  /* check with index groups */
  for (i=0; i<ng+1; i++)
    for (j=0; j<isize[i]; j++)
      if ( index[i][j] >= natoms )
	gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) larger "
		  "than number of atoms in trajectory (%d atoms)",
		  index[i][j],grpname[i],isize[i],natoms);
  
  /* initialize some handy things */
  copy_mat(box,box_pbc);
  if (bXY) {
    check_box_c(box);
    /* Make sure the z-height does not influence the cut-off */
    box_pbc[ZZ][ZZ] = 2*max(box[XX][XX],box[YY][YY]);
  }
  if (bPBC)
    rmax2   = 0.99*0.99*max_cutoff2(bXY ? epbcXY : epbcXYZ,box_pbc);
  else
    rmax2   = sqr(3*max(box[XX][XX],max(box[YY][YY],box[ZZ][ZZ])));
  if (debug)
    fprintf(debug,"rmax2 = %g\n",rmax2);

  /* We use the double amount of bins, so we can correctly
   * write the rdf and rdf_cn output at i*binwidth values.
   */
  nbin     = (int)(sqrt(rmax2) * 2 / binwidth);
  invhbinw = 2.0 / binwidth;
  cut2   = sqr(cutoff);

  snew(count,ng);
  snew(pairs,ng);
  snew(npairs,ng);

  snew(bExcl,natoms);
  max_i = 0;
  for(g=0; g<ng; g++) {
    if (isize[g+1] > max_i)
      max_i = isize[g+1];

    /* this is THE array */
    snew(count[g],nbin+1);
  
    /* make pairlist array for groups and exclusions */
    snew(pairs[g],isize[0]);
    snew(npairs[g],isize[0]);
    for(i=0; i<isize[0]; i++) {
      /* We can only have exclusions with atomic rdfs */
      if (!(bCM || rdft[0][0] != 'a')) {
	ix = index[0][i];
	for(j=0; j < natoms; j++)
	  bExcl[j] = FALSE;
	/* exclusions? */
	if (excl)
	  for( j = excl->index[ix]; j < excl->index[ix+1]; j++)
	    bExcl[excl->a[j]]=TRUE;
	k = 0;
	snew(pairs[g][i], isize[g+1]);
	bNonSelfExcl = FALSE;
	for(j=0; j<isize[g+1]; j++) {
	  jx = index[g+1][j];
	  if (!bExcl[jx])
	    pairs[g][i][k++]=jx;
	  else if (ix != jx)
	    /* Check if we have exclusions other than self exclusions */
	    bNonSelfExcl = TRUE;
	}
	if (bNonSelfExcl) {
	  npairs[g][i]=k;
	  srenew(pairs[g][i],npairs[g][i]);
	} else {
	  /* Save a LOT of memory and some cpu cycles */
	  npairs[g][i]=-1;
	  sfree(pairs[g][i]);
	}
      } else {
	npairs[g][i]=-1;
      }
    }
  }
  sfree(bExcl);

  snew(x_i1,max_i);
  nframes = 0;
  invvol_sum = 0;
  do {
    /* Must init pbc every step because of pressure coupling */
    copy_mat(box,box_pbc);
    if (bPBC) {
      if (top != NULL)
	rm_pbc(&top->idef,ePBC,natoms,box,x,x);
      if (bXY) {
	check_box_c(box);
	clear_rvec(box_pbc[ZZ]);
      }
      set_pbc(&pbc,ePBC,box_pbc);

      if (bXY)
	/* Set z-size to 1 so we get the surface iso the volume */
	box_pbc[ZZ][ZZ] = 1;
    }
    invvol = 1/det(box_pbc);
    invvol_sum += invvol;

    if (bCM) {
      /* Calculate center of mass of the whole group */
      calc_comg(is[0],coi[0],index[0],TRUE           ,atom,x,x0);
    } else if (rdft[0][0] != 'a') {
      calc_comg(is[0],coi[0],index[0],rdft[0][6]=='m',atom,x,x0);
    }

    for(g=0; g<ng; g++) {
      if (rdft[0][0] == 'a') {
	/* Copy the indexed coordinates to a continuous array */
	for(i=0; i<isize[g+1]; i++)
	  copy_rvec(x[index[g+1][i]],x_i1[i]);
      } else {
	/* Calculate the COMs/COGs and store in x_i1 */
	calc_comg(is[g+1],coi[g+1],index[g+1],rdft[0][6]=='m',atom,x,x_i1);
      }
    
      for(i=0; i<isize0; i++) {
	if (bCM || rdft[0][0] != 'a') {
	  copy_rvec(x0[i],xi);
	} else {
	  copy_rvec(x[index[0][i]],xi);
	}
	if (rdft[0][0] == 'a' && npairs[g][i] >= 0) {
	  /* Expensive loop, because of indexing */
	  for(j=0; j<npairs[g][i]; j++) {
	    jx=pairs[g][i][j];
	    if (bPBC)
	      pbc_dx(&pbc,xi,x[jx],dx);
	    else
	      rvec_sub(xi,x[jx],dx);
	      
	    if (bXY)
	      r2 = dx[XX]*dx[XX] + dx[YY]*dx[YY];
	    else 
	      r2=iprod(dx,dx);
	    if (r2>cut2 && r2<=rmax2)
	      count[g][(int)(sqrt(r2)*invhbinw)]++;
	  }
	} else {
	  /* Cheaper loop, no exclusions */
	  if (rdft[0][0] == 'a')
	    isize_g = isize[g+1];
	  else
	    isize_g = is[g+1];
	  for(j=0; j<isize_g; j++) {
	    if (bPBC)
	      pbc_dx(&pbc,xi,x_i1[j],dx);
	    else
	      rvec_sub(xi,x_i1[j],dx);
	    if (bXY)
	      r2 = dx[XX]*dx[XX] + dx[YY]*dx[YY];
	    else 
	      r2=iprod(dx,dx);
	    if (r2>cut2 && r2<=rmax2)
	      count[g][(int)(sqrt(r2)*invhbinw)]++;
	  }
	}
      }
    }
    nframes++;
  } while (read_next_x(status,&t,natoms,x,box));
  fprintf(stderr,"\n");
  
  close_trj(status);
  
  sfree(x);
  
  /* Average volume */
  invvol = invvol_sum/nframes;

  /* Calculate volume of sphere segments or length of circle segments */
  snew(inv_segvol,(nbin+1)/2);
  prev_spherevol=0;
  for(i=0; (i<(nbin+1)/2); i++) {
    r = (i + 0.5)*binwidth;
    if (bXY) {
      spherevol=M_PI*r*r;
    } else {
      spherevol=(4.0/3.0)*M_PI*r*r*r;
    }
    segvol=spherevol-prev_spherevol;
    inv_segvol[i]=1.0/segvol;
    prev_spherevol=spherevol;
  }
  
  snew(rdf,ng);
  for(g=0; g<ng; g++) {
    /* We have to normalize by dividing by the number of frames */
    if (rdft[0][0] == 'a')
      normfac = 1.0/(nframes*invvol*isize0*isize[g+1]);
    else
      normfac = 1.0/(nframes*invvol*isize0*is[g+1]);
      
    /* Do the normalization */
    nrdf = max((nbin+1)/2,1+2*fade/binwidth);
    snew(rdf[g],nrdf);
    for(i=0; i<(nbin+1)/2; i++) {
      r = i*binwidth;
      if (i == 0)
	j = count[g][0];
      else
	j = count[g][i*2-1] + count[g][i*2];
      if ((fade > 0) && (r >= fade))
	rdf[g][i] = 1 + (j*inv_segvol[i]*normfac-1)*exp(-16*sqr(r/fade-1));
      else {
	if (bNormalize)
	  rdf[g][i] = j*inv_segvol[i]*normfac;
	else
	  rdf[g][i] = j/(binwidth*isize0*nframes);
      }
    }
    for( ; (i<nrdf); i++)
      rdf[g][i] = 1.0;
  }

  if (rdft[0][0] == 'a') {
    sprintf(gtitle,"Radial distribution");
  } else {
    sprintf(gtitle,"Radial distribution of %s %s",
	    rdft[0][0]=='m' ? "molecule" : "residue",
	    rdft[0][6]=='m' ? "COM" : "COG");
  }
  fp=xvgropen(fnRDF,gtitle,"r","");
  if (ng==1) {
    if (bPrintXvgrCodes())
      fprintf(fp,"@ subtitle \"%s%s - %s\"\n",
	      grpname[0],bCM ? " COM" : "",grpname[1]);
  }
  else {
    if (bPrintXvgrCodes())
      fprintf(fp,"@ subtitle \"reference %s%s\"\n",
	      grpname[0],bCM ? " COM" : "");
    xvgr_legend(fp,ng,grpname+1);
  }
  for(i=0; (i<nrdf); i++) {
    fprintf(fp,"%10g",i*binwidth);
    for(g=0; g<ng; g++)
      fprintf(fp," %10g",rdf[g][i]);
    fprintf(fp,"\n");
  }
  ffclose(fp);
  
  do_view(fnRDF,NULL);

  /* h(Q) function: fourier transform of rdf */  
  if (fnHQ) {
    int nhq = 401;
    real *hq,*integrand,Q;
    
    /* Get a better number density later! */
    rho = isize[1]*invvol;
    snew(hq,nhq);
    snew(integrand,nrdf);
    for(i=0; (i<nhq); i++) {
      Q = i*0.5;
      integrand[0] = 0;
      for(j=1; (j<nrdf); j++) {
	r = j*binwidth;
	integrand[j]  = (Q == 0) ? 1.0 : sin(Q*r)/(Q*r);
	integrand[j] *= 4.0*M_PI*rho*r*r*(rdf[0][j]-1.0);
      }
      hq[i] = print_and_integrate(debug,nrdf,binwidth,integrand,NULL,0);
    }
    fp=xvgropen(fnHQ,"h(Q)","Q(/nm)","h(Q)");
    for(i=0; (i<nhq); i++) 
      fprintf(fp,"%10g %10g\n",i*0.5,hq[i]);
    ffclose(fp);
    do_view(fnHQ,NULL);
    sfree(hq);
    sfree(integrand);
  }
  
  if (fnCNRDF) {  
    normfac = 1.0/(isize0*nframes);
    fp=xvgropen(fnCNRDF,"Cumulative Number RDF","r","number");
    if (ng==1) {
      if (bPrintXvgrCodes())
	fprintf(fp,"@ subtitle \"%s-%s\"\n",grpname[0],grpname[1]);
    }
    else {
      if (bPrintXvgrCodes())
	fprintf(fp,"@ subtitle \"reference %s\"\n",grpname[0]);
      xvgr_legend(fp,ng,grpname+1);
    }
    snew(sum,ng);
    for(i=0; (i<=nbin/2); i++) {
      fprintf(fp,"%10g",i*binwidth);
      for(g=0; g<ng; g++) {
	fprintf(fp," %10g",(real)((double)sum[g]*normfac));
	if (i*2+1 < nbin)
	  sum[g] += count[g][i*2] + count[g][i*2+1];
      }
      fprintf(fp,"\n");
    }
    ffclose(fp);
    sfree(sum);
    
    do_view(fnCNRDF,NULL);
  }

  for(g=0; g<ng; g++)
    sfree(rdf[g]);
  sfree(rdf);
}
Beispiel #7
0
void low_do_autocorr(const char *fn, const gmx_output_env_t *oenv, const char *title,
                     int nframes, int nitem, int nout, real **c1,
                     real dt, unsigned long mode, int nrestart,
                     gmx_bool bAver, gmx_bool bNormalize,
                     gmx_bool bVerbose, real tbeginfit, real tendfit,
                     int eFitFn)
{
    FILE       *fp, *gp = NULL;
    int         i;
    real       *csum;
    real       *ctmp, *fit;
    real        sum, Ct2av, Ctav;
    gmx_bool    bFour = acf.bFour;

    /* Check flags and parameters */
    nout = get_acfnout();
    if (nout == -1)
    {
        nout = acf.nout = (nframes+1)/2;
    }
    else if (nout > nframes)
    {
        nout = nframes;
    }

    if (MODE(eacCos) && MODE(eacVector))
    {
        gmx_fatal(FARGS, "Incompatible options bCos && bVector (%s, %d)",
                  __FILE__, __LINE__);
    }
    if ((MODE(eacP3) || MODE(eacRcross)) && bFour)
    {
        if (bVerbose)
        {
            fprintf(stderr, "Can't combine mode %lu with FFT, turning off FFT\n", mode);
        }
        bFour = FALSE;
    }
    if (MODE(eacNormal) && MODE(eacVector))
    {
        gmx_fatal(FARGS, "Incompatible mode bits: normal and vector (or Legendre)");
    }

    /* Print flags and parameters */
    if (bVerbose)
    {
        printf("Will calculate %s of %d thingies for %d frames\n",
               title ? title : "autocorrelation", nitem, nframes);
        printf("bAver = %s, bFour = %s bNormalize= %s\n",
               gmx::boolToString(bAver), gmx::boolToString(bFour),
               gmx::boolToString(bNormalize));
        printf("mode = %lu, dt = %g, nrestart = %d\n", mode, dt, nrestart);
    }
    /* Allocate temp arrays */
    snew(csum, nframes);
    snew(ctmp, nframes);

    /* Loop over items (e.g. molecules or dihedrals)
     * In this loop the actual correlation functions are computed, but without
     * normalizing them.
     */
    for (int i = 0; i < nitem; i++)
    {
        if (bVerbose && (((i % 100) == 0) || (i == nitem-1)))
        {
            fprintf(stderr, "\rThingie %d", i+1);
            fflush(stderr);
        }

        if (bFour)
        {
            do_four_core(mode, nframes, c1[i], csum, ctmp);
        }
        else
        {
            do_ac_core(nframes, nout, ctmp, c1[i], nrestart, mode);
        }
    }
    if (bVerbose)
    {
        fprintf(stderr, "\n");
    }
    sfree(ctmp);
    sfree(csum);

    if (fn)
    {
        snew(fit, nout);
        fp = xvgropen(fn, title, "Time (ps)", "C(t)", oenv);
    }
    else
    {
        fit = NULL;
        fp  = NULL;
    }
    if (bAver)
    {
        if (nitem > 1)
        {
            average_acf(bVerbose, nframes, nitem, c1);
        }

        if (bNormalize)
        {
            normalize_acf(nout, c1[0]);
        }

        if (eFitFn != effnNONE)
        {
            fit_acf(nout, eFitFn, oenv, fn != NULL, tbeginfit, tendfit, dt, c1[0], fit);
            sum = print_and_integrate(fp, nout, dt, c1[0], fit, 1);
        }
        else
        {
            sum = print_and_integrate(fp, nout, dt, c1[0], NULL, 1);
        }
        if (bVerbose)
        {
            printf("Correlation time (integral over corrfn): %g (ps)\n", sum);
        }
    }
    else
    {
        /* Not averaging. Normalize individual ACFs */
        Ctav = Ct2av = 0;
        if (debug)
        {
            gp = xvgropen("ct-distr.xvg", "Correlation times", "item", "time (ps)", oenv);
        }
        for (i = 0; i < nitem; i++)
        {
            if (bNormalize)
            {
                normalize_acf(nout, c1[i]);
            }
            if (eFitFn != effnNONE)
            {
                fit_acf(nout, eFitFn, oenv, fn != NULL, tbeginfit, tendfit, dt, c1[i], fit);
                sum = print_and_integrate(fp, nout, dt, c1[i], fit, 1);
            }
            else
            {
                sum = print_and_integrate(fp, nout, dt, c1[i], NULL, 1);
                if (debug)
                {
                    fprintf(debug,
                            "CORRelation time (integral over corrfn %d): %g (ps)\n",
                            i, sum);
                }
            }
            Ctav  += sum;
            Ct2av += sum*sum;
            if (debug)
            {
                fprintf(gp, "%5d  %.3f\n", i, sum);
            }
        }
        if (debug)
        {
            xvgrclose(gp);
        }
        if (nitem > 1)
        {
            Ctav  /= nitem;
            Ct2av /= nitem;
            printf("Average correlation time %.3f Std. Dev. %.3f Error %.3f (ps)\n",
                   Ctav, std::sqrt((Ct2av - gmx::square(Ctav))),
                   std::sqrt((Ct2av - gmx::square(Ctav))/(nitem-1)));
        }
    }
    if (fp)
    {
        xvgrclose(fp);
    }
    sfree(fit);
}