Exemple #1
0
int gmx_velacc(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] computes the velocity autocorrelation function.",
        "When the [TT]-m[tt] option is used, the momentum autocorrelation",
        "function is calculated.[PAR]",
        "With option [TT]-mol[tt] the velocity autocorrelation function of",
        "molecules is calculated. In this case the index group should consist",
        "of molecule numbers instead of atom numbers.[PAR]",
        "Be sure that your trajectory contains frames with velocity information",
        "(i.e. [TT]nstvout[tt] was set in your original [REF].mdp[ref] file),",
        "and that the time interval between data collection points is",
        "much shorter than the time scale of the autocorrelation."
    };

    static gmx_bool bMass = FALSE, bMol = FALSE, bRecip = TRUE;
    t_pargs         pa[]  = {
        { "-m", FALSE, etBOOL, {&bMass},
          "Calculate the momentum autocorrelation function" },
        { "-recip", FALSE, etBOOL, {&bRecip},
          "Use cm^-1 on X-axis instead of 1/ps for spectra." },
        { "-mol", FALSE, etBOOL, {&bMol},
          "Calculate the velocity acf of molecules" }
    };

    t_topology      top;
    int             ePBC = -1;
    t_trxframe      fr;
    matrix          box;
    gmx_bool        bTPS = FALSE, bTop = FALSE;
    int             gnx;
    int            *index;
    char           *grpname;
    /* t0, t1 are the beginning and end time respectively.
     * dt is the time step, mass is temp variable for atomic mass.
     */
    real              t0, t1, dt, mass;
    t_trxstatus      *status;
    int               counter, n_alloc, i, j, counter_dim, k, l;
    rvec              mv_mol;
    /* Array for the correlation function */
    real            **c1;
    real             *normm = NULL;
    gmx_output_env_t *oenv;

#define NHISTO 360

    t_filenm  fnm[] = {
        { efTRN, "-f",    NULL,   ffREAD  },
        { efTPS, NULL,    NULL,   ffOPTRD },
        { efNDX, NULL,    NULL,   ffOPTRD },
        { efXVG, "-o",    "vac",  ffWRITE },
        { efXVG, "-os",   "spectrum", ffOPTWR }
    };
#define NFILE asize(fnm)
    int       npargs;
    t_pargs  *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);
    if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
    {
        sfree(ppa);
        return 0;
    }

    if (bMol || bMass)
    {
        bTPS = ftp2bSet(efTPS, NFILE, fnm) || !ftp2bSet(efNDX, NFILE, fnm);
    }

    if (bTPS)
    {
        bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, NULL, NULL, box,
                             TRUE);
        get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
    }
    else
    {
        rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
    }

    if (bMol)
    {
        if (!bTop)
        {
            gmx_fatal(FARGS, "Need a topology to determine the molecules");
        }
        snew(normm, top.atoms.nr);
        precalc(top, normm);
        index_atom2mol(&gnx, index, &top.mols);
    }

    /* Correlation stuff */
    snew(c1, gnx);
    for (i = 0; (i < gnx); i++)
    {
        c1[i] = NULL;
    }

    read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr, TRX_NEED_V);
    t0 = fr.time;

    n_alloc = 0;
    counter = 0;
    do
    {
        if (counter >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < gnx; i++)
            {
                srenew(c1[i], DIM*n_alloc);
            }
        }
        counter_dim = DIM*counter;
        if (bMol)
        {
            for (i = 0; i < gnx; i++)
            {
                clear_rvec(mv_mol);
                k = top.mols.index[index[i]];
                l = top.mols.index[index[i]+1];
                for (j = k; j < l; j++)
                {
                    if (bMass)
                    {
                        mass = top.atoms.atom[j].m;
                    }
                    else
                    {
                        mass = normm[j];
                    }
                    mv_mol[XX] += mass*fr.v[j][XX];
                    mv_mol[YY] += mass*fr.v[j][YY];
                    mv_mol[ZZ] += mass*fr.v[j][ZZ];
                }
                c1[i][counter_dim+XX] = mv_mol[XX];
                c1[i][counter_dim+YY] = mv_mol[YY];
                c1[i][counter_dim+ZZ] = mv_mol[ZZ];
            }
        }
        else
        {
            for (i = 0; i < gnx; i++)
            {
                if (bMass)
                {
                    mass = top.atoms.atom[index[i]].m;
                }
                else
                {
                    mass = 1;
                }
                c1[i][counter_dim+XX] = mass*fr.v[index[i]][XX];
                c1[i][counter_dim+YY] = mass*fr.v[index[i]][YY];
                c1[i][counter_dim+ZZ] = mass*fr.v[index[i]][ZZ];
            }
        }

        t1 = fr.time;

        counter++;
    }
    while (read_next_frame(oenv, status, &fr));

    close_trj(status);

    if (counter >= 4)
    {
        /* Compute time step between frames */
        dt = (t1-t0)/(counter-1);
        do_autocorr(opt2fn("-o", NFILE, fnm), oenv,
                    bMass ?
                    "Momentum Autocorrelation Function" :
                    "Velocity Autocorrelation Function",
                    counter, gnx, c1, dt, eacVector, TRUE);

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

        if (opt2bSet("-os", NFILE, fnm))
        {
            calc_spectrum(counter/2, (real *) (c1[0]), (t1-t0)/2, opt2fn("-os", NFILE, fnm),
                          oenv, bRecip);
            do_view(oenv, opt2fn("-os", NFILE, fnm), "-nxy");
        }
    }
    else
    {
        fprintf(stderr, "Not enough frames in trajectory - no output generated.\n");
    }

    return 0;
}
int gmx_rotacf(int argc,char *argv[])
{
  static char *desc[] = {
    "g_rotacf calculates the rotational correlation function",
    "for molecules. Three atoms (i,j,k) must be given in the index",
    "file, defining two vectors ij and jk. The rotational acf",
    "is calculated as the autocorrelation function of the vector",
    "n = ij x jk, i.e. the cross product of the two vectors.",
    "Since three atoms span a plane, the order of the three atoms",
    "does not matter. Optionally, controlled by the -d switch, you can",
    "calculate the rotational correlation function for linear molecules",
    "by specifying two atoms (i,j) in the index file.",
    "[PAR]",
    "EXAMPLES[PAR]",
    "g_rotacf -P 1 -nparm 2 -fft -n index -o rotacf-x-P1",
    "-fa expfit-x-P1 -beginfit 2.5 -endfit 20.0[PAR]",
    "This will calculate the rotational correlation function using a first",
    "order Legendre polynomial of the angle of a vector defined by the index",
    "file. The correlation function will be fitted from 2.5 ps till 20.0 ps",
    "to a two parameter exponential",


    ""
  };
  static bool bVec    = FALSE,bAver=TRUE;

  t_pargs pa[] = {
    { "-d",   FALSE, etBOOL, {&bVec},
      "Use index doublets (vectors) for correlation function instead of triplets (planes)" },
    { "-aver",FALSE, etBOOL, {&bAver},
      "Average over molecules" }
  };

  int        status,isize;
  atom_id    *index;
  char       *grpname;
  rvec       *x,*x_s;
  matrix     box;
  real       **c1;
  rvec       xij,xjk,n;
  int        i,m,teller,n_alloc,natoms,nvec,ai,aj,ak;
  unsigned long mode;
  real       t,t0,t1,dt;
  t_topology *top;
  int        ePBC;
  t_filenm   fnm[] = {
    { efTRX, "-f", NULL,  ffREAD  },
    { efTPX, NULL, NULL,  ffREAD },
    { efNDX, NULL, NULL,  ffREAD  },
    { efXVG, "-o", "rotacf",  ffWRITE }
  };
#define NFILE asize(fnm)
  int     npargs;
  t_pargs *ppa;
  
  CopyRight(stderr,argv[0]);
  npargs = asize(pa);
  ppa    = add_acf_pargs(&npargs,pa);
  
  parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL);
  
  rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
  
  if (bVec) 
    nvec = isize/2;
  else
    nvec = isize/3;
  
  if (((isize % 3) != 0) && !bVec)
    gmx_fatal(FARGS,"number of index elements not multiple of 3, "
		"these can not be atom triplets\n");
  if (((isize % 2) != 0) && bVec)
    gmx_fatal(FARGS,"number of index elements not multiple of 2, "
		"these can not be atom doublets\n");
  
  top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC);
  
  snew(c1,nvec);
  for (i=0; (i<nvec); i++)
    c1[i]=NULL;
  n_alloc=0;

  natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
  snew(x_s,natoms);
  
  /* Start the loop over frames */
  t1 = t0 = t;
  teller  = 0;
  do {
    if (teller >= n_alloc) {
      n_alloc+=100;
      for (i=0; (i<nvec); i++)
	srenew(c1[i],DIM*n_alloc);
    }
    t1 = t;
    
    /* Remove periodicity */
    rm_pbc(&(top->idef),ePBC,natoms,box,x,x_s);
    
    /* Compute crossproducts for all vectors, if triplets.
     * else, just get the vectors in case of doublets.
     */
    if (bVec == FALSE) {
      for (i=0; (i<nvec); i++) {
	ai=index[3*i];
	aj=index[3*i+1];
	ak=index[3*i+2];
	rvec_sub(x_s[ai],x_s[aj],xij);
	rvec_sub(x_s[aj],x_s[ak],xjk);
	cprod(xij,xjk,n);
	for(m=0; (m<DIM); m++)
	  c1[i][DIM*teller+m]=n[m];
      }
    }
    else {
      for (i=0; (i<nvec); i++) {
	ai=index[2*i];
	aj=index[2*i+1];
	rvec_sub(x_s[ai],x_s[aj],n);
	for(m=0; (m<DIM); m++)
	  c1[i][DIM*teller+m]=n[m];
      }
    }
    /* Increment loop counter */
    teller++;
  } while (read_next_x(status,&t,natoms,x,box));  
  close_trj(status); 
  fprintf(stderr,"\nDone with trajectory\n");
  
  /* Autocorrelation function */
  if (teller < 2)
    fprintf(stderr,"Not enough frames for correlation function\n");
  else {
    dt=(t1 - t0)/(teller-1);
    
    mode = eacVector;
    
    do_autocorr(ftp2fn(efXVG,NFILE,fnm),"Rotational Correlation Function",
		teller,nvec,c1,dt,mode,bAver);
  }

  do_view(ftp2fn(efXVG,NFILE,fnm),NULL);
    
  thanx(stderr);
    
  return 0;
}
Exemple #3
0
int gmx_analyze(int argc,char *argv[])
{
  static const char *desc[] = {
    "g_analyze reads an ascii file and analyzes data sets.",
    "A line in the input file may start with a time",
    "(see option [TT]-time[tt]) and any number of y values may follow.",
    "Multiple sets can also be",
    "read when they are seperated by & (option [TT]-n[tt]),",
    "in this case only one y value is read from each line.",
    "All lines starting with # and @ are skipped.",
    "All analyses can also be done for the derivative of a set",
    "(option [TT]-d[tt]).[PAR]",

    "All options, except for [TT]-av[tt] and [TT]-power[tt] assume that the",
    "points are equidistant in time.[PAR]",

    "g_analyze always shows the average and standard deviation of each",
    "set. For each set it also shows the relative deviation of the third",
    "and forth cumulant from those of a Gaussian distribution with the same",
    "standard deviation.[PAR]",

    "Option [TT]-ac[tt] produces the autocorrelation function(s).[PAR]",
    
    "Option [TT]-cc[tt] plots the resemblance of set i with a cosine of",
    "i/2 periods. The formula is:[BR]"
    "2 (int0-T y(t) cos(i pi t) dt)^2 / int0-T y(t) y(t) dt[BR]",
    "This is useful for principal components obtained from covariance",
    "analysis, since the principal components of random diffusion are",
    "pure cosines.[PAR]",
    
    "Option [TT]-msd[tt] produces the mean square displacement(s).[PAR]",
    
    "Option [TT]-dist[tt] produces distribution plot(s).[PAR]",
    
    "Option [TT]-av[tt] produces the average over the sets.",
    "Error bars can be added with the option [TT]-errbar[tt].",
    "The errorbars can represent the standard deviation, the error",
    "(assuming the points are independent) or the interval containing",
    "90% of the points, by discarding 5% of the points at the top and",
    "the bottom.[PAR]",
    
    "Option [TT]-ee[tt] produces error estimates using block averaging.",
    "A set is divided in a number of blocks and averages are calculated for",
    "each block. The error for the total average is calculated from",
    "the variance between averages of the m blocks B_i as follows:",
    "error^2 = Sum (B_i - <B>)^2 / (m*(m-1)).",
    "These errors are plotted as a function of the block size.",
    "Also an analytical block average curve is plotted, assuming",
    "that the autocorrelation is a sum of two exponentials.",
    "The analytical curve for the block average is:[BR]",
    "f(t) = sigma sqrt(2/T (  a   (tau1 ((exp(-t/tau1) - 1) tau1/t + 1)) +[BR]",
    "                       (1-a) (tau2 ((exp(-t/tau2) - 1) tau2/t + 1)))),[BR]"
    "where T is the total time.",
    "a, tau1 and tau2 are obtained by fitting f^2(t) to error^2.",
    "When the actual block average is very close to the analytical curve,",
    "the error is sigma*sqrt(2/T (a tau1 + (1-a) tau2)).",
    "The complete derivation is given in",
    "B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]",

    "Option [TT]-filter[tt] prints the RMS high-frequency fluctuation",
    "of each set and over all sets with respect to a filtered average.",
    "The filter is proportional to cos(pi t/len) where t goes from -len/2",
    "to len/2. len is supplied with the option [TT]-filter[tt].",
    "This filter reduces oscillations with period len/2 and len by a factor",
    "of 0.79 and 0.33 respectively.[PAR]",

    "Option [TT]-g[tt] fits the data to the function given with option",
    "[TT]-fitfn[tt].[PAR]",
    
    "Option [TT]-power[tt] fits the data to b t^a, which is accomplished",
    "by fitting to a t + b on log-log scale. All points after the first",
    "zero or negative value are ignored.[PAR]"
    
    "Option [TT]-luzar[tt] performs a Luzar & Chandler kinetics analysis",
    "on output from [TT]g_hbond[tt]. The input file can be taken directly",
    "from [TT]g_hbond -ac[tt], and then the same result should be produced."
  };
  static real tb=-1,te=-1,frac=0.5,filtlen=0,binwidth=0.1,aver_start=0;
  static bool bHaveT=TRUE,bDer=FALSE,bSubAv=TRUE,bAverCorr=FALSE,bXYdy=FALSE;
  static bool bEESEF=FALSE,bEENLC=FALSE,bEeFitAc=FALSE,bPower=FALSE;
  static bool bIntegrate=FALSE,bRegression=FALSE,bLuzar=FALSE,bLuzarError=FALSE; 
  static int  nsets_in=1,d=1,nb_min=4,resol=10;
  static real temp=298.15,fit_start=1,smooth_tail_start=-1;
  
  /* must correspond to enum avbar* declared at beginning of file */
  static const char *avbar_opt[avbarNR+1] = { 
    NULL, "none", "stddev", "error", "90", NULL
  };

  t_pargs pa[] = {
    { "-time",    FALSE, etBOOL, {&bHaveT},
      "Expect a time in the input" },
    { "-b",       FALSE, etREAL, {&tb},
      "First time to read from set" },
    { "-e",       FALSE, etREAL, {&te},
      "Last time to read from set" },
    { "-n",       FALSE, etINT, {&nsets_in},
      "Read # sets seperated by &" },
    { "-d",       FALSE, etBOOL, {&bDer},
	"Use the derivative" },
    { "-dp",      FALSE, etINT, {&d}, 
      "HIDDENThe derivative is the difference over # points" },
    { "-bw",      FALSE, etREAL, {&binwidth},
      "Binwidth for the distribution" },
    { "-errbar",  FALSE, etENUM, {avbar_opt},
      "Error bars for -av" },
    { "-integrate",FALSE,etBOOL, {&bIntegrate},
      "Integrate data function(s) numerically using trapezium rule" },
    { "-aver_start",FALSE, etREAL, {&aver_start},
      "Start averaging the integral from here" },
    { "-xydy",    FALSE, etBOOL, {&bXYdy},
      "Interpret second data set as error in the y values for integrating" },
    { "-regression",FALSE,etBOOL,{&bRegression},
      "Perform a linear regression analysis on the data" },
    { "-luzar",   FALSE, etBOOL, {&bLuzar},
      "Do a Luzar and Chandler analysis on a correlation function and related as produced by g_hbond. When in addition the -xydy flag is given the second and fourth column will be interpreted as errors in c(t) and n(t)." },
    { "-temp",    FALSE, etREAL, {&temp},
      "Temperature for the Luzar hydrogen bonding kinetics analysis" },
    { "-fitstart", FALSE, etREAL, {&fit_start},
      "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" }, 
    { "-smooth",FALSE, etREAL, {&smooth_tail_start},
      "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
    { "-nbmin",   FALSE, etINT, {&nb_min},
      "HIDDENMinimum number of blocks for block averaging" },
    { "-resol", FALSE, etINT, {&resol},
      "HIDDENResolution for the block averaging, block size increases with"
    " a factor 2^(1/#)" },
    { "-eeexpfit", FALSE, etBOOL, {&bEESEF},
      "HIDDENAlways use a single exponential fit for the error estimate" },
    { "-eenlc", FALSE, etBOOL, {&bEENLC},
      "HIDDENAllow a negative long-time correlation" },
    { "-eefitac", FALSE, etBOOL, {&bEeFitAc},
      "HIDDENAlso plot analytical block average using a autocorrelation fit" },
    { "-filter",  FALSE, etREAL, {&filtlen},
      "Print the high-frequency fluctuation after filtering with a cosine filter of length #" },
    { "-power", FALSE, etBOOL, {&bPower},
      "Fit data to: b t^a" },
    { "-subav", FALSE, etBOOL, {&bSubAv},
      "Subtract the average before autocorrelating" },
    { "-oneacf", FALSE, etBOOL, {&bAverCorr},
      "Calculate one ACF over all sets" }
  };
#define NPA asize(pa)

  FILE     *out,*out_fit;
  int      n,nlast,s,nset,i,j=0;
  real     **val,*t,dt,tot,error;
  double   *av,*sig,cum1,cum2,cum3,cum4,db;
  char     *acfile,*msdfile,*ccfile,*distfile,*avfile,*eefile,*fitfile;
  
  t_filenm fnm[] = { 
    { efXVG, "-f",    "graph",    ffREAD   },
    { efXVG, "-ac",   "autocorr", ffOPTWR  },
    { efXVG, "-msd",  "msd",      ffOPTWR  },
    { efXVG, "-cc",   "coscont",  ffOPTWR  },
    { efXVG, "-dist", "distr",    ffOPTWR  },
    { efXVG, "-av",   "average",  ffOPTWR  },
    { efXVG, "-ee",   "errest",   ffOPTWR  },
    { efLOG, "-g",    "fitlog",   ffOPTWR  }
  }; 
#define NFILE asize(fnm) 

  int     npargs;
  t_pargs *ppa;

  npargs = asize(pa); 
  ppa    = add_acf_pargs(&npargs,pa);
  
  CopyRight(stderr,argv[0]); 
  parse_common_args(&argc,argv,PCA_CAN_VIEW,
		    NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL); 

  acfile   = opt2fn_null("-ac",NFILE,fnm);
  msdfile  = opt2fn_null("-msd",NFILE,fnm);
  ccfile   = opt2fn_null("-cc",NFILE,fnm);
  distfile = opt2fn_null("-dist",NFILE,fnm);
  avfile   = opt2fn_null("-av",NFILE,fnm);
  eefile   = opt2fn_null("-ee",NFILE,fnm);
  if (opt2parg_bSet("-fitfn",npargs,ppa)) 
    fitfile  = opt2fn("-g",NFILE,fnm);
  else
    fitfile  = opt2fn_null("-g",NFILE,fnm);
    
  val=read_xvg_time(opt2fn("-f",NFILE,fnm),bHaveT,
		    opt2parg_bSet("-b",npargs,ppa),tb,
		    opt2parg_bSet("-e",npargs,ppa),te,
		    nsets_in,&nset,&n,&dt,&t);
  printf("Read %d sets of %d points, dt = %g\n\n",nset,n,dt);
  
  if (bDer) {
    printf("Calculating the derivative as (f[i+%d]-f[i])/(%d*dt)\n\n",
	    d,d);
    n -= d;
    for(s=0; s<nset; s++)
      for(i=0; (i<n); i++)
	val[s][i] = (val[s][i+d]-val[s][i])/(d*dt);
  }
  if (bIntegrate) {
    real sum,stddev;
    printf("Calculating the integral using the trapezium rule\n");
    
    if (bXYdy) {
      sum = evaluate_integral(n,t,val[0],val[1],aver_start,&stddev);
      printf("Integral %10.3f +/- %10.5f\n",sum,stddev);
    }
    else {
      for(s=0; s<nset; s++) {
	sum = evaluate_integral(n,t,val[s],NULL,aver_start,&stddev);
	printf("Integral %d  %10.5f  +/- %10.5f\n",s+1,sum,stddev);
      }
    }
  }
  if (fitfile) {
    out_fit = ffopen(fitfile,"w");
    if (bXYdy && nset>=2) {
      do_fit(out_fit,0,TRUE,n,t,val,npargs,ppa);
    } else {
      for(s=0; s<nset; s++)
	do_fit(out_fit,s,FALSE,n,t,val,npargs,ppa);
    }
    fclose(out_fit);
  }

  printf("                                      std. dev.    relative deviation of\n");
  printf("                       standard       ---------   cumulants from those of\n");
  printf("set      average       deviation      sqrt(n-1)   a Gaussian distribition\n");
  printf("                                                      cum. 3   cum. 4\n");
  snew(av,nset);
  snew(sig,nset);
  for(s=0; (s<nset); s++) {
    cum1 = 0;
    cum2 = 0;
    cum3 = 0;
    cum4 = 0;
    for(i=0; (i<n); i++)
      cum1 += val[s][i];
    cum1 /= n;
    for(i=0; (i<n); i++) {
      db = val[s][i]-cum1;
      cum2 += db*db;
      cum3 += db*db*db;
      cum4 += db*db*db*db;
    }
    cum2  /= n;
    cum3  /= n;
    cum4  /= n;
    av[s]  = cum1;
    sig[s] = sqrt(cum2);
    if (n > 1)
      error = sqrt(cum2/(n-1));
    else
      error = 0;
    printf("SS%d  %13.6e   %12.6e   %12.6e      %6.3f   %6.3f\n",
	   s+1,av[s],sig[s],error,
	   sig[s] ? cum3/(sig[s]*sig[s]*sig[s]*sqrt(8/M_PI)) : 0,
	   sig[s] ? cum4/(sig[s]*sig[s]*sig[s]*sig[s]*3)-1 : 0); 
  }
  printf("\n");

  if (filtlen)
    filter(filtlen,n,nset,val,dt);
  
  if (msdfile) {
    out=xvgropen(msdfile,"Mean square displacement",
		 "time","MSD (nm\\S2\\N)");
    nlast = (int)(n*frac);
    for(s=0; s<nset; s++) {
      for(j=0; j<=nlast; j++) {
	if (j % 100 == 0)
	  fprintf(stderr,"\r%d",j);
	tot=0;
	for(i=0; i<n-j; i++)
	  tot += sqr(val[s][i]-val[s][i+j]); 
	tot /= (real)(n-j);
	fprintf(out," %g %8g\n",dt*j,tot);
      }
      if (s<nset-1)
	fprintf(out,"&\n");
    }
    fclose(out);
    fprintf(stderr,"\r%d, time=%g\n",j-1,(j-1)*dt);
  }
  if (ccfile)
    plot_coscont(ccfile,n,nset,val);
  
  if (distfile)
    histogram(distfile,binwidth,n,nset,val);
  if (avfile)
    average(avfile,nenum(avbar_opt),n,nset,val,t);
  if (eefile)
    estimate_error(eefile,nb_min,resol,n,nset,av,sig,val,dt,
		   bEeFitAc,bEESEF,bEENLC);
  if (bPower)
    power_fit(n,nset,val,t);
  if (acfile) {
    if (bSubAv) 
      for(s=0; s<nset; s++)
	for(i=0; i<n; i++)
	  val[s][i] -= av[s];
    do_autocorr(acfile,"Autocorrelation",n,nset,val,dt,
		eacNormal,bAverCorr);
  }
  if (bRegression)
    regression_analysis(n,bXYdy,t,val);

  if (bLuzar) 
    luzar_correl(n,t,nset,val,temp,bXYdy,fit_start,smooth_tail_start);
    
  view_all(NFILE, fnm);
  
  thanx(stderr);

  return 0;
}
Exemple #4
0
int gmx_tcaf(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] computes tranverse current autocorrelations.",
        "These are used to estimate the shear viscosity, [GRK]eta[grk].",
        "For details see: Palmer, Phys. Rev. E 49 (1994) pp 359-366.[PAR]",
        "Transverse currents are calculated using the",
        "k-vectors (1,0,0) and (2,0,0) each also in the [IT]y[it]- and [IT]z[it]-direction,",
        "(1,1,0) and (1,-1,0) each also in the 2 other planes (these vectors",
        "are not independent) and (1,1,1) and the 3 other box diagonals (also",
        "not independent). For each k-vector the sine and cosine are used, in",
        "combination with the velocity in 2 perpendicular directions. This gives",
        "a total of 16*2*2=64 transverse currents. One autocorrelation is",
        "calculated fitted for each k-vector, which gives 16 TCAFs. Each of",
        "these TCAFs is fitted to [MATH]f(t) = [EXP]-v[exp]([COSH]Wv[cosh] + 1/W [SINH]Wv[sinh])[math],",
        "[MATH]v = -t/(2 [GRK]tau[grk])[math], [MATH]W = [SQRT]1 - 4 [GRK]tau[grk] [GRK]eta[grk]/[GRK]rho[grk] k^2[sqrt][math], which gives 16 values of [GRK]tau[grk]",
        "and [GRK]eta[grk]. The fit weights decay exponentially with time constant [MATH]w[math] (given with [TT]-wt[tt]) as [MATH][EXP]-t/w[exp][math], and the TCAF and",
        "fit are calculated up to time [MATH]5*w[math].",
        "The [GRK]eta[grk] values should be fitted to [MATH]1 - a [GRK]eta[grk](k) k^2[math], from which",
        "one can estimate the shear viscosity at k=0.[PAR]",
        "When the box is cubic, one can use the option [TT]-oc[tt], which",
        "averages the TCAFs over all k-vectors with the same length.",
        "This results in more accurate TCAFs.",
        "Both the cubic TCAFs and fits are written to [TT]-oc[tt]",
        "The cubic [GRK]eta[grk] estimates are also written to [TT]-ov[tt].[PAR]",
        "With option [TT]-mol[tt], the transverse current is determined of",
        "molecules instead of atoms. In this case, the index group should",
        "consist of molecule numbers instead of atom numbers.[PAR]",
        "The k-dependent viscosities in the [TT]-ov[tt] file should be",
        "fitted to [MATH][GRK]eta[grk](k) = [GRK]eta[grk][SUB]0[sub] (1 - a k^2)[math] to obtain the viscosity at",
        "infinite wavelength.[PAR]",
        "[BB]Note:[bb] make sure you write coordinates and velocities often enough.",
        "The initial, non-exponential, part of the autocorrelation function",
        "is very important for obtaining a good fit."
    };

    static gmx_bool   bMol = FALSE, bK34 = FALSE;
    static real       wt   = 5;
    t_pargs           pa[] = {
        { "-mol", FALSE, etBOOL, {&bMol},
          "Calculate TCAF of molecules" },
        { "-k34", FALSE, etBOOL, {&bK34},
          "Also use k=(3,0,0) and k=(4,0,0)" },
        { "-wt", FALSE, etREAL, {&wt},
          "Exponential decay time for the TCAF fit weights" }
    };

    t_topology        top;
    int               ePBC;
    t_trxframe        fr;
    matrix            box;
    gmx_bool          bTop;
    int               gnx;
    int              *index, *atndx = NULL, at;
    char             *grpname;
    char              title[256];
    real              t0, t1, dt, m, mtot, sysmass, rho, sx, cx;
    t_trxstatus      *status;
    int               nframes, n_alloc, i, j, k, d;
    rvec              mv_mol, cm_mol, kfac[NK];
    int               nkc, nk, ntc;
    real            **tc;
    gmx_output_env_t *oenv;

#define NHISTO 360

    t_filenm  fnm[] = {
        { efTRN, "-f",    NULL,      ffREAD  },
        { efTPS, NULL,    NULL,      ffOPTRD },
        { efNDX, NULL,    NULL,      ffOPTRD },
        { efXVG, "-ot",  "transcur", ffOPTWR },
        { efXVG, "-oa",  "tcaf_all", ffWRITE },
        { efXVG, "-o",   "tcaf",     ffWRITE },
        { efXVG, "-of",  "tcaf_fit", ffWRITE },
        { efXVG, "-oc",  "tcaf_cub", ffOPTWR },
        { efXVG, "-ov",  "visc_k",   ffWRITE }
    };
#define NFILE asize(fnm)
    int       npargs;
    t_pargs  *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);

    if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, NULL, NULL, box,
                         TRUE);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);

    if (bMol)
    {
        if (!bTop)
        {
            gmx_fatal(FARGS, "Need a topology to determine the molecules");
        }
        atndx = top.mols.index;
    }

    if (bK34)
    {
        nkc = NKC;
    }
    else
    {
        nkc = NKC0;
    }
    nk  = kset_c[nkc];
    ntc = nk*NPK;

    sprintf(title, "Velocity Autocorrelation Function for %s", grpname);

    sysmass = 0;
    for (i = 0; i < nk; i++)
    {
        if (iprod(v0[i], v1[i]) != 0)
        {
            gmx_fatal(FARGS, "DEATH HORROR: vectors not orthogonal");
        }
        if (iprod(v0[i], v2[i]) != 0)
        {
            gmx_fatal(FARGS, "DEATH HORROR: vectors not orthogonal");
        }
        if (iprod(v1[i], v2[i]) != 0)
        {
            gmx_fatal(FARGS, "DEATH HORROR: vectors not orthogonal");
        }
        unitv(v1[i], v1[i]);
        unitv(v2[i], v2[i]);
    }
    snew(tc, ntc);
    for (i = 0; i < top.atoms.nr; i++)
    {
        sysmass += top.atoms.atom[i].m;
    }

    read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr,
                     TRX_NEED_X | TRX_NEED_V);
    t0 = fr.time;

    n_alloc = 0;
    nframes = 0;
    rho     = 0;

    do
    {

        if (nframes >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < ntc; i++)
            {
                srenew(tc[i], n_alloc);
            }
        }

        rho += 1/det(fr.box);
        for (k = 0; k < nk; k++)
        {
            for (d = 0; d < DIM; d++)
            {
                kfac[k][d] = 2*M_PI*v0[k][d]/fr.box[d][d];
            }
        }
        for (i = 0; i < ntc; i++)
        {
            tc[i][nframes] = 0;
        }

        for (i = 0; i < gnx; i++)
        {
            if (bMol)
            {
                clear_rvec(mv_mol);
                clear_rvec(cm_mol);
                mtot = 0;
                for (j = 0; j < atndx[index[i]+1] - atndx[index[i]]; j++)
                {
                    at          = atndx[index[i]] + j;
                    m           = top.atoms.atom[at].m;
                    mv_mol[XX] += m*fr.v[at][XX];
                    mv_mol[YY] += m*fr.v[at][YY];
                    mv_mol[ZZ] += m*fr.v[at][ZZ];
                    cm_mol[XX] += m*fr.x[at][XX];
                    cm_mol[YY] += m*fr.x[at][YY];
                    cm_mol[ZZ] += m*fr.x[at][ZZ];
                    mtot       += m;
                }
                svmul(1.0/mtot, cm_mol, cm_mol);
            }
            else
            {
                svmul(top.atoms.atom[index[i]].m, fr.v[index[i]], mv_mol);
            }

            if (!bMol)
            {
                copy_rvec(fr.x[index[i]], cm_mol);
            }
            j = 0;
            for (k = 0; k < nk; k++)
            {
                sx              = std::sin(iprod(kfac[k], cm_mol));
                cx              = std::cos(iprod(kfac[k], cm_mol));
                tc[j][nframes] += sx*iprod(v1[k], mv_mol);
                j++;
                tc[j][nframes] += cx*iprod(v1[k], mv_mol);
                j++;
                tc[j][nframes] += sx*iprod(v2[k], mv_mol);
                j++;
                tc[j][nframes] += cx*iprod(v2[k], mv_mol);
                j++;
            }
        }

        t1 = fr.time;
        nframes++;
    }
    while (read_next_frame(oenv, status, &fr));
    close_trj(status);

    dt = (t1-t0)/(nframes-1);

    rho *= sysmass/nframes*AMU/(NANO*NANO*NANO);
    fprintf(stdout, "Density = %g (kg/m^3)\n", rho);
    process_tcaf(nframes, dt, nkc, tc, kfac, rho, wt,
                 opt2fn_null("-ot", NFILE, fnm),
                 opt2fn("-oa", NFILE, fnm), opt2fn("-o", NFILE, fnm),
                 opt2fn("-of", NFILE, fnm), opt2fn_null("-oc", NFILE, fnm),
                 opt2fn("-ov", NFILE, fnm), oenv);

    return 0;
}
Exemple #5
0
int gmx_analyze(int argc, char *argv[])
{
    static const char *desc[] = {
        "[TT]g_analyze[tt] reads an ASCII file and analyzes data sets.",
        "A line in the input file may start with a time",
        "(see option [TT]-time[tt]) and any number of [IT]y[it]-values may follow.",
        "Multiple sets can also be",
        "read when they are separated by & (option [TT]-n[tt]);",
        "in this case only one [IT]y[it]-value is read from each line.",
        "All lines starting with # and @ are skipped.",
        "All analyses can also be done for the derivative of a set",
        "(option [TT]-d[tt]).[PAR]",

        "All options, except for [TT]-av[tt] and [TT]-power[tt], assume that the",
        "points are equidistant in time.[PAR]",

        "[TT]g_analyze[tt] always shows the average and standard deviation of each",
        "set, as well as the relative deviation of the third",
        "and fourth cumulant from those of a Gaussian distribution with the same",
        "standard deviation.[PAR]",

        "Option [TT]-ac[tt] produces the autocorrelation function(s).",
        "Be sure that the time interval between data points is",
        "much shorter than the time scale of the autocorrelation.[PAR]",

        "Option [TT]-cc[tt] plots the resemblance of set i with a cosine of",
        "i/2 periods. The formula is:[BR]"
        "[MATH]2 ([INT][FROM]0[from][TO]T[to][int] y(t) [COS]i [GRK]pi[grk] t[cos] dt)^2 / [INT][FROM]0[from][TO]T[to][int] y^2(t) dt[math][BR]",
        "This is useful for principal components obtained from covariance",
        "analysis, since the principal components of random diffusion are",
        "pure cosines.[PAR]",

        "Option [TT]-msd[tt] produces the mean square displacement(s).[PAR]",

        "Option [TT]-dist[tt] produces distribution plot(s).[PAR]",

        "Option [TT]-av[tt] produces the average over the sets.",
        "Error bars can be added with the option [TT]-errbar[tt].",
        "The errorbars can represent the standard deviation, the error",
        "(assuming the points are independent) or the interval containing",
        "90% of the points, by discarding 5% of the points at the top and",
        "the bottom.[PAR]",

        "Option [TT]-ee[tt] produces error estimates using block averaging.",
        "A set is divided in a number of blocks and averages are calculated for",
        "each block. The error for the total average is calculated from",
        "the variance between averages of the m blocks B[SUB]i[sub] as follows:",
        "error^2 = [SUM][sum] (B[SUB]i[sub] - [CHEVRON]B[chevron])^2 / (m*(m-1)).",
        "These errors are plotted as a function of the block size.",
        "Also an analytical block average curve is plotted, assuming",
        "that the autocorrelation is a sum of two exponentials.",
        "The analytical curve for the block average is:[BR]",
        "[MATH]f(t) = [GRK]sigma[grk][TT]*[tt][SQRT]2/T (  [GRK]alpha[grk]   ([GRK]tau[grk][SUB]1[sub] (([EXP]-t/[GRK]tau[grk][SUB]1[sub][exp] - 1) [GRK]tau[grk][SUB]1[sub]/t + 1)) +[BR]",
        "                       (1-[GRK]alpha[grk]) ([GRK]tau[grk][SUB]2[sub] (([EXP]-t/[GRK]tau[grk][SUB]2[sub][exp] - 1) [GRK]tau[grk][SUB]2[sub]/t + 1)))[sqrt][math],[BR]"
        "where T is the total time.",
        "[GRK]alpha[grk], [GRK]tau[grk][SUB]1[sub] and [GRK]tau[grk][SUB]2[sub] are obtained by fitting f^2(t) to error^2.",
        "When the actual block average is very close to the analytical curve,",
        "the error is [MATH][GRK]sigma[grk][TT]*[tt][SQRT]2/T (a [GRK]tau[grk][SUB]1[sub] + (1-a) [GRK]tau[grk][SUB]2[sub])[sqrt][math].",
        "The complete derivation is given in",
        "B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]",

        "Option [TT]-bal[tt] finds and subtracts the ultrafast \"ballistic\"",
        "component from a hydrogen bond autocorrelation function by the fitting",
        "of a sum of exponentials, as described in e.g.",
        "O. Markovitch, J. Chem. Phys. 129:084505, 2008. The fastest term",
        "is the one with the most negative coefficient in the exponential,",
        "or with [TT]-d[tt], the one with most negative time derivative at time 0.",
        "[TT]-nbalexp[tt] sets the number of exponentials to fit.[PAR]",

        "Option [TT]-gem[tt] fits bimolecular rate constants ka and kb",
        "(and optionally kD) to the hydrogen bond autocorrelation function",
        "according to the reversible geminate recombination model. Removal of",
        "the ballistic component first is strongly advised. The model is presented in",
        "O. Markovitch, J. Chem. Phys. 129:084505, 2008.[PAR]",

        "Option [TT]-filter[tt] prints the RMS high-frequency fluctuation",
        "of each set and over all sets with respect to a filtered average.",
        "The filter is proportional to cos([GRK]pi[grk] t/len) where t goes from -len/2",
        "to len/2. len is supplied with the option [TT]-filter[tt].",
        "This filter reduces oscillations with period len/2 and len by a factor",
        "of 0.79 and 0.33 respectively.[PAR]",

        "Option [TT]-g[tt] fits the data to the function given with option",
        "[TT]-fitfn[tt].[PAR]",

        "Option [TT]-power[tt] fits the data to [MATH]b t^a[math], which is accomplished",
        "by fitting to [MATH]a t + b[math] on log-log scale. All points after the first",
        "zero or with a negative value are ignored.[PAR]"

        "Option [TT]-luzar[tt] performs a Luzar & Chandler kinetics analysis",
        "on output from [TT]g_hbond[tt]. The input file can be taken directly",
        "from [TT]g_hbond -ac[tt], and then the same result should be produced."
    };
    static real        tb         = -1, te = -1, frac = 0.5, filtlen = 0, binwidth = 0.1, aver_start = 0;
    static gmx_bool    bHaveT     = TRUE, bDer = FALSE, bSubAv = TRUE, bAverCorr = FALSE, bXYdy = FALSE;
    static gmx_bool    bEESEF     = FALSE, bEENLC = FALSE, bEeFitAc = FALSE, bPower = FALSE;
    static gmx_bool    bIntegrate = FALSE, bRegression = FALSE, bLuzar = FALSE, bLuzarError = FALSE;
    static int         nsets_in   = 1, d = 1, nb_min = 4, resol = 10, nBalExp = 4, nFitPoints = 100;
    static real        temp       = 298.15, fit_start = 1, fit_end = 60, smooth_tail_start = -1, balTime = 0.2, diffusion = 5e-5, rcut = 0.35;

    /* must correspond to enum avbar* declared at beginning of file */
    static const char *avbar_opt[avbarNR+1] = {
        NULL, "none", "stddev", "error", "90", NULL
    };

    t_pargs            pa[] = {
        { "-time",    FALSE, etBOOL, {&bHaveT},
          "Expect a time in the input" },
        { "-b",       FALSE, etREAL, {&tb},
          "First time to read from set" },
        { "-e",       FALSE, etREAL, {&te},
          "Last time to read from set" },
        { "-n",       FALSE, etINT, {&nsets_in},
          "Read this number of sets separated by &" },
        { "-d",       FALSE, etBOOL, {&bDer},
          "Use the derivative" },
        { "-dp",      FALSE, etINT, {&d},
          "HIDDENThe derivative is the difference over this number of points" },
        { "-bw",      FALSE, etREAL, {&binwidth},
          "Binwidth for the distribution" },
        { "-errbar",  FALSE, etENUM, {avbar_opt},
          "Error bars for [TT]-av[tt]" },
        { "-integrate", FALSE, etBOOL, {&bIntegrate},
          "Integrate data function(s) numerically using trapezium rule" },
        { "-aver_start", FALSE, etREAL, {&aver_start},
          "Start averaging the integral from here" },
        { "-xydy",    FALSE, etBOOL, {&bXYdy},
          "Interpret second data set as error in the y values for integrating" },
        { "-regression", FALSE, etBOOL, {&bRegression},
          "Perform a linear regression analysis on the data. If [TT]-xydy[tt] is set a second set will be interpreted as the error bar in the Y value. Otherwise, if multiple data sets are present a multilinear regression will be performed yielding the constant A that minimize [MATH][GRK]chi[grk]^2 = (y - A[SUB]0[sub] x[SUB]0[sub] - A[SUB]1[sub] x[SUB]1[sub] - ... - A[SUB]N[sub] x[SUB]N[sub])^2[math] where now Y is the first data set in the input file and x[SUB]i[sub] the others. Do read the information at the option [TT]-time[tt]." },
        { "-luzar",   FALSE, etBOOL, {&bLuzar},
          "Do a Luzar and Chandler analysis on a correlation function and related as produced by [TT]g_hbond[tt]. When in addition the [TT]-xydy[tt] flag is given the second and fourth column will be interpreted as errors in c(t) and n(t)." },
        { "-temp",    FALSE, etREAL, {&temp},
          "Temperature for the Luzar hydrogen bonding kinetics analysis (K)" },
        { "-fitstart", FALSE, etREAL, {&fit_start},
          "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" },
        { "-fitend", FALSE, etREAL, {&fit_end},
          "Time (ps) where to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. Only with [TT]-gem[tt]" },
        { "-smooth", FALSE, etREAL, {&smooth_tail_start},
          "If this value is >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: [MATH]y = A [EXP]-x/[GRK]tau[grk][exp][math]" },
        { "-nbmin",   FALSE, etINT, {&nb_min},
          "HIDDENMinimum number of blocks for block averaging" },
        { "-resol", FALSE, etINT, {&resol},
          "HIDDENResolution for the block averaging, block size increases with"
          " a factor 2^(1/resol)" },
        { "-eeexpfit", FALSE, etBOOL, {&bEESEF},
          "HIDDENAlways use a single exponential fit for the error estimate" },
        { "-eenlc", FALSE, etBOOL, {&bEENLC},
          "HIDDENAllow a negative long-time correlation" },
        { "-eefitac", FALSE, etBOOL, {&bEeFitAc},
          "HIDDENAlso plot analytical block average using a autocorrelation fit" },
        { "-filter",  FALSE, etREAL, {&filtlen},
          "Print the high-frequency fluctuation after filtering with a cosine filter of this length" },
        { "-power", FALSE, etBOOL, {&bPower},
          "Fit data to: b t^a" },
        { "-subav", FALSE, etBOOL, {&bSubAv},
          "Subtract the average before autocorrelating" },
        { "-oneacf", FALSE, etBOOL, {&bAverCorr},
          "Calculate one ACF over all sets" },
        { "-nbalexp", FALSE, etINT, {&nBalExp},
          "HIDDENNumber of exponentials to fit to the ultrafast component" },
        { "-baltime", FALSE, etREAL, {&balTime},
          "HIDDENTime up to which the ballistic component will be fitted" },
/*     { "-gemnp", FALSE, etINT, {&nFitPoints}, */
/*       "HIDDENNumber of data points taken from the ACF to use for fitting to rev. gem. recomb. model."}, */
/*     { "-rcut", FALSE, etREAL, {&rcut}, */
/*       "Cut-off for hydrogen bonds in geminate algorithms" }, */
/*     { "-gemtype", FALSE, etENUM, {gemType}, */
/*       "What type of gminate recombination to use"}, */
/*     { "-D", FALSE, etREAL, {&diffusion}, */
/*       "The self diffusion coefficient which is used for the reversible geminate recombination model."} */
    };
#define NPA asize(pa)

    FILE           *out, *out_fit;
    int             n, nlast, s, nset, i, j = 0;
    real          **val, *t, dt, tot, error;
    double         *av, *sig, cum1, cum2, cum3, cum4, db;
    const char     *acfile, *msdfile, *ccfile, *distfile, *avfile, *eefile, *balfile, *gemfile, *fitfile;
    output_env_t    oenv;

    t_filenm        fnm[] = {
        { efXVG, "-f",    "graph",    ffREAD   },
        { efXVG, "-ac",   "autocorr", ffOPTWR  },
        { efXVG, "-msd",  "msd",      ffOPTWR  },
        { efXVG, "-cc",   "coscont",  ffOPTWR  },
        { efXVG, "-dist", "distr",    ffOPTWR  },
        { efXVG, "-av",   "average",  ffOPTWR  },
        { efXVG, "-ee",   "errest",   ffOPTWR  },
        { efXVG, "-bal",  "ballisitc", ffOPTWR  },
/*     { efXVG, "-gem",  "geminate", ffOPTWR  }, */
        { efLOG, "-g",    "fitlog",   ffOPTWR  }
    };
#define NFILE asize(fnm)

    int      npargs;
    t_pargs *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);

    parse_common_args(&argc, argv, PCA_CAN_VIEW,
                      NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv);

    acfile   = opt2fn_null("-ac", NFILE, fnm);
    msdfile  = opt2fn_null("-msd", NFILE, fnm);
    ccfile   = opt2fn_null("-cc", NFILE, fnm);
    distfile = opt2fn_null("-dist", NFILE, fnm);
    avfile   = opt2fn_null("-av", NFILE, fnm);
    eefile   = opt2fn_null("-ee", NFILE, fnm);
    balfile  = opt2fn_null("-bal", NFILE, fnm);
/*   gemfile  = opt2fn_null("-gem",NFILE,fnm); */
    /* When doing autocorrelation we don't want a fitlog for fitting
     * the function itself (not the acf) when the user did not ask for it.
     */
    if (opt2parg_bSet("-fitfn", npargs, ppa) && acfile == NULL)
    {
        fitfile  = opt2fn("-g", NFILE, fnm);
    }
    else
    {
        fitfile  = opt2fn_null("-g", NFILE, fnm);
    }

    val = read_xvg_time(opt2fn("-f", NFILE, fnm), bHaveT,
                        opt2parg_bSet("-b", npargs, ppa), tb,
                        opt2parg_bSet("-e", npargs, ppa), te,
                        nsets_in, &nset, &n, &dt, &t);
    printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt);

    if (bDer)
    {
        printf("Calculating the derivative as (f[i+%d]-f[i])/(%d*dt)\n\n",
               d, d);
        n -= d;
        for (s = 0; s < nset; s++)
        {
            for (i = 0; (i < n); i++)
            {
                val[s][i] = (val[s][i+d]-val[s][i])/(d*dt);
            }
        }
    }

    if (bIntegrate)
    {
        real sum, stddev;

        printf("Calculating the integral using the trapezium rule\n");

        if (bXYdy)
        {
            sum = evaluate_integral(n, t, val[0], val[1], aver_start, &stddev);
            printf("Integral %10.3f +/- %10.5f\n", sum, stddev);
        }
        else
        {
            for (s = 0; s < nset; s++)
            {
                sum = evaluate_integral(n, t, val[s], NULL, aver_start, &stddev);
                printf("Integral %d  %10.5f  +/- %10.5f\n", s+1, sum, stddev);
            }
        }
    }

    if (fitfile != NULL)
    {
        out_fit = ffopen(fitfile, "w");
        if (bXYdy && nset >= 2)
        {
            do_fit(out_fit, 0, TRUE, n, t, val, npargs, ppa, oenv);
        }
        else
        {
            for (s = 0; s < nset; s++)
            {
                do_fit(out_fit, s, FALSE, n, t, val, npargs, ppa, oenv);
            }
        }
        ffclose(out_fit);
    }

    printf("                                      std. dev.    relative deviation of\n");
    printf("                       standard       ---------   cumulants from those of\n");
    printf("set      average       deviation      sqrt(n-1)   a Gaussian distribition\n");
    printf("                                                      cum. 3   cum. 4\n");
    snew(av, nset);
    snew(sig, nset);
    for (s = 0; (s < nset); s++)
    {
        cum1 = 0;
        cum2 = 0;
        cum3 = 0;
        cum4 = 0;
        for (i = 0; (i < n); i++)
        {
            cum1 += val[s][i];
        }
        cum1 /= n;
        for (i = 0; (i < n); i++)
        {
            db    = val[s][i]-cum1;
            cum2 += db*db;
            cum3 += db*db*db;
            cum4 += db*db*db*db;
        }
        cum2  /= n;
        cum3  /= n;
        cum4  /= n;
        av[s]  = cum1;
        sig[s] = sqrt(cum2);
        if (n > 1)
        {
            error = sqrt(cum2/(n-1));
        }
        else
        {
            error = 0;
        }
        printf("SS%d  %13.6e   %12.6e   %12.6e      %6.3f   %6.3f\n",
               s+1, av[s], sig[s], error,
               sig[s] ? cum3/(sig[s]*sig[s]*sig[s]*sqrt(8/M_PI)) : 0,
               sig[s] ? cum4/(sig[s]*sig[s]*sig[s]*sig[s]*3)-1 : 0);
    }
    printf("\n");

    if (filtlen)
    {
        filter(filtlen, n, nset, val, dt);
    }

    if (msdfile)
    {
        out = xvgropen(msdfile, "Mean square displacement",
                       "time", "MSD (nm\\S2\\N)", oenv);
        nlast = (int)(n*frac);
        for (s = 0; s < nset; s++)
        {
            for (j = 0; j <= nlast; j++)
            {
                if (j % 100 == 0)
                {
                    fprintf(stderr, "\r%d", j);
                }
                tot = 0;
                for (i = 0; i < n-j; i++)
                {
                    tot += sqr(val[s][i]-val[s][i+j]);
                }
                tot /= (real)(n-j);
                fprintf(out, " %g %8g\n", dt*j, tot);
            }
            if (s < nset-1)
            {
                fprintf(out, "&\n");
            }
        }
        ffclose(out);
        fprintf(stderr, "\r%d, time=%g\n", j-1, (j-1)*dt);
    }
    if (ccfile)
    {
        plot_coscont(ccfile, n, nset, val, oenv);
    }

    if (distfile)
    {
        histogram(distfile, binwidth, n, nset, val, oenv);
    }
    if (avfile)
    {
        average(avfile, nenum(avbar_opt), n, nset, val, t);
    }
    if (eefile)
    {
        estimate_error(eefile, nb_min, resol, n, nset, av, sig, val, dt,
                       bEeFitAc, bEESEF, bEENLC, oenv);
    }
    if (balfile)
    {
        do_ballistic(balfile, n, t, val, nset, balTime, nBalExp, oenv);
    }
/*   if (gemfile) */
/*       do_geminate(gemfile,n,t,val,nset,diffusion,rcut,balTime, */
/*                   nFitPoints, fit_start, fit_end, oenv); */
    if (bPower)
    {
        power_fit(n, nset, val, t);
    }

    if (acfile != NULL)
    {
        if (bSubAv)
        {
            for (s = 0; s < nset; s++)
            {
                for (i = 0; i < n; i++)
                {
                    val[s][i] -= av[s];
                }
            }
        }
        do_autocorr(acfile, oenv, "Autocorrelation", n, nset, val, dt,
                    eacNormal, bAverCorr);
    }

    if (bRegression)
    {
        regression_analysis(n, bXYdy, t, nset, val);
    }

    if (bLuzar)
    {
        luzar_correl(n, t, nset, val, temp, bXYdy, fit_start, smooth_tail_start, oenv);
    }

    view_all(oenv, NFILE, fnm);

    return 0;
}
Exemple #6
0
int gmx_dos(int argc, char *argv[])
{
    const char         *desc[] = {
        "[TT]g_dos[tt] computes the Density of States from a simulations.",
        "In order for this to be meaningful the velocities must be saved",
        "in the trajecotry with sufficiently high frequency such as to cover",
        "all vibrations. For flexible systems that would be around a few fs",
        "between saving. Properties based on the DoS are printed on the",
        "standard output."
    };
    const char         *bugs[] = {
        "This program needs a lot of memory: total usage equals the number of atoms times 3 times number of frames times 4 (or 8 when run in double precision)."
    };
    FILE               *fp, *fplog;
    t_topology          top;
    int                 ePBC = -1;
    t_trxframe          fr;
    matrix              box;
    int                 gnx;
    char                title[256];
    real                t0, t1, m;
    t_trxstatus        *status;
    int                 nV, nframes, n_alloc, i, j, k, l, fftcode, Nmol, Natom;
    double              rho, dt, V2sum, Vsum, V, tmass, dostot, dos2, dosabs;
    real              **c1, **dos, mi, beta, bfac, *nu, *tt, stddev, c1j;
    output_env_t        oenv;
    gmx_fft_t           fft;
    double              cP, S, A, E, DiffCoeff, Delta, f, y, z, sigHS, Shs, Sig, DoS0, recip_fac;
    double              wCdiff, wSdiff, wAdiff, wEdiff;

    static     gmx_bool bVerbose = TRUE, bAbsolute = FALSE, bNormalize = FALSE;
    static     gmx_bool bRecip   = FALSE, bDump = FALSE;
    static     real     Temp     = 298.15, toler = 1e-6;
    t_pargs             pa[]     = {
        { "-v", FALSE, etBOOL, {&bVerbose},
          "Be loud and noisy." },
        { "-recip", FALSE, etBOOL, {&bRecip},
          "Use cm^-1 on X-axis instead of 1/ps for DoS plots." },
        { "-abs", FALSE, etBOOL, {&bAbsolute},
          "Use the absolute value of the Fourier transform of the VACF as the Density of States. Default is to use the real component only" },
        { "-normdos", FALSE, etBOOL, {&bNormalize},
          "Normalize the DoS such that it adds up to 3N. This is a hack that should not be necessary." },
        { "-T", FALSE, etREAL, {&Temp},
          "Temperature in the simulation" },
        { "-toler", FALSE, etREAL, {&toler},
          "[HIDDEN]Tolerance when computing the fluidicity using bisection algorithm" },
        { "-dump", FALSE, etBOOL, {&bDump},
          "[HIDDEN]Dump the y/fy plot corresponding to Fig. 2 inLin2003a and the and the weighting functions corresponding to Fig. 1 in Berens1983a." }
    };

    t_filenm            fnm[] = {
        { efTRN, "-f",    NULL,    ffREAD  },
        { efTPX, "-s",    NULL,    ffREAD  },
        { efNDX, NULL,    NULL,    ffOPTRD },
        { efXVG, "-vacf", "vacf",  ffWRITE },
        { efXVG, "-mvacf", "mvacf", ffWRITE },
        { efXVG, "-dos",  "dos",   ffWRITE },
        { efLOG, "-g",    "dos",   ffWRITE },
    };
#define NFILE asize(fnm)
    int                 npargs;
    t_pargs            *ppa;
    const char         *DoSlegend[] = {
        "DoS(v)", "DoS(v)[Solid]", "DoS(v)[Diff]"
    };

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);
    parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE, fnm, npargs, ppa, asize(desc), desc,
                      asize(bugs), bugs, &oenv);

    beta = 1/(Temp*BOLTZ);
    if (bDump)
    {
        printf("Dumping reference figures. Thanks for your patience.\n");
        dump_fy(oenv, toler);
        dump_w(oenv, beta);
        exit(0);
    }

    fplog = gmx_fio_fopen(ftp2fn(efLOG, NFILE, fnm), "w");
    fprintf(fplog, "Doing density of states analysis based on trajectory.\n");
    please_cite(fplog, "Pascal2011a");
    please_cite(fplog, "Caleman2011b");

    read_tps_conf(ftp2fn(efTPX, NFILE, fnm), title, &top, &ePBC, NULL, NULL, box,
                  TRUE);
    V     = det(box);
    tmass = 0;
    for (i = 0; (i < top.atoms.nr); i++)
    {
        tmass += top.atoms.atom[i].m;
    }

    Natom = top.atoms.nr;
    Nmol  = top.mols.nr;
    gnx   = Natom*DIM;

    /* Correlation stuff */
    snew(c1, gnx);
    for (i = 0; (i < gnx); i++)
    {
        c1[i] = NULL;
    }

    read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr, TRX_NEED_V);
    t0 = fr.time;

    n_alloc = 0;
    nframes = 0;
    Vsum    = V2sum = 0;
    nV      = 0;
    do
    {
        if (fr.bBox)
        {
            V      = det(fr.box);
            V2sum += V*V;
            Vsum  += V;
            nV++;
        }
        if (nframes >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < gnx; i++)
            {
                srenew(c1[i], n_alloc);
            }
        }
        for (i = 0; i < gnx; i += DIM)
        {
            c1[i+XX][nframes] = fr.v[i/DIM][XX];
            c1[i+YY][nframes] = fr.v[i/DIM][YY];
            c1[i+ZZ][nframes] = fr.v[i/DIM][ZZ];
        }

        t1 = fr.time;

        nframes++;
    }
    while (read_next_frame(oenv, status, &fr));

    close_trj(status);

    dt = (t1-t0)/(nframes-1);
    if (nV > 0)
    {
        V = Vsum/nV;
    }
    if (bVerbose)
    {
        printf("Going to do %d fourier transforms of length %d. Hang on.\n",
               gnx, nframes);
    }
    low_do_autocorr(NULL, oenv, NULL, nframes, gnx, nframes, c1, dt, eacNormal, 0, FALSE,
                    FALSE, FALSE, -1, -1, 0, 0);
    snew(dos, DOS_NR);
    for (j = 0; (j < DOS_NR); j++)
    {
        snew(dos[j], nframes+4);
    }

    if (bVerbose)
    {
        printf("Going to merge the ACFs into the mass-weighted and plain ACF\n");
    }
    for (i = 0; (i < gnx); i += DIM)
    {
        mi = top.atoms.atom[i/DIM].m;
        for (j = 0; (j < nframes/2); j++)
        {
            c1j            = (c1[i+XX][j] + c1[i+YY][j] + c1[i+ZZ][j]);
            dos[VACF][j]  += c1j/Natom;
            dos[MVACF][j] += mi*c1j;
        }
    }
    fp = xvgropen(opt2fn("-vacf", NFILE, fnm), "Velocity ACF",
                  "Time (ps)", "C(t)", oenv);
    snew(tt, nframes/2);
    for (j = 0; (j < nframes/2); j++)
    {
        tt[j] = j*dt;
        fprintf(fp, "%10g  %10g\n", tt[j], dos[VACF][j]);
    }
    xvgrclose(fp);
    fp = xvgropen(opt2fn("-mvacf", NFILE, fnm), "Mass-weighted velocity ACF",
                  "Time (ps)", "C(t)", oenv);
    for (j = 0; (j < nframes/2); j++)
    {
        fprintf(fp, "%10g  %10g\n", tt[j], dos[MVACF][j]);
    }
    xvgrclose(fp);

    if ((fftcode = gmx_fft_init_1d_real(&fft, nframes/2,
                                        GMX_FFT_FLAG_NONE)) != 0)
    {
        gmx_fatal(FARGS, "gmx_fft_init_1d_real returned %d", fftcode);
    }
    if ((fftcode = gmx_fft_1d_real(fft, GMX_FFT_REAL_TO_COMPLEX,
                                   (void *)dos[MVACF], (void *)dos[DOS])) != 0)
    {
        gmx_fatal(FARGS, "gmx_fft_1d_real returned %d", fftcode);
    }

    /* First compute the DoS */
    /* Magic factor of 8 included now. */
    bfac = 8*dt*beta/2;
    dos2 = 0;
    snew(nu, nframes/4);
    for (j = 0; (j < nframes/4); j++)
    {
        nu[j] = 2*j/(t1-t0);
        dos2 += sqr(dos[DOS][2*j]) + sqr(dos[DOS][2*j+1]);
        if (bAbsolute)
        {
            dos[DOS][j] = bfac*sqrt(sqr(dos[DOS][2*j]) + sqr(dos[DOS][2*j+1]));
        }
        else
        {
            dos[DOS][j] = bfac*dos[DOS][2*j];
        }
    }
    /* Normalize it */
    dostot = evaluate_integral(nframes/4, nu, dos[DOS], NULL, nframes/4, &stddev);
    if (bNormalize)
    {
        for (j = 0; (j < nframes/4); j++)
        {
            dos[DOS][j] *= 3*Natom/dostot;
        }
    }

    /* Now analyze it */
    DoS0 = dos[DOS][0];

    /* Note this eqn. is incorrect in Pascal2011a! */
    Delta = ((2*DoS0/(9*Natom))*sqrt(M_PI*BOLTZ*Temp*Natom/tmass)*
             pow((Natom/V), 1.0/3.0)*pow(6/M_PI, 2.0/3.0));
    f     = calc_fluidicity(Delta, toler);
    y     = calc_y(f, Delta, toler);
    z     = calc_compress(y);
    Sig   = BOLTZ*(5.0/2.0+log(2*M_PI*BOLTZ*Temp/(sqr(PLANCK))*V/(f*Natom)));
    Shs   = Sig+calc_Shs(f, y);
    rho   = (tmass*AMU)/(V*NANO*NANO*NANO);
    sigHS = pow(6*y*V/(M_PI*Natom), 1.0/3.0);

    fprintf(fplog, "System = \"%s\"\n", title);
    fprintf(fplog, "Nmol = %d\n", Nmol);
    fprintf(fplog, "Natom = %d\n", Natom);
    fprintf(fplog, "dt = %g ps\n", dt);
    fprintf(fplog, "tmass = %g amu\n", tmass);
    fprintf(fplog, "V = %g nm^3\n", V);
    fprintf(fplog, "rho = %g g/l\n", rho);
    fprintf(fplog, "T = %g K\n", Temp);
    fprintf(fplog, "beta = %g mol/kJ\n", beta);

    fprintf(fplog, "\nDoS parameters\n");
    fprintf(fplog, "Delta = %g\n", Delta);
    fprintf(fplog, "fluidicity = %g\n", f);
    fprintf(fplog, "hard sphere packing fraction = %g\n", y);
    fprintf(fplog, "hard sphere compressibility = %g\n", z);
    fprintf(fplog, "ideal gas entropy = %g\n", Sig);
    fprintf(fplog, "hard sphere entropy = %g\n", Shs);
    fprintf(fplog, "sigma_HS = %g nm\n", sigHS);
    fprintf(fplog, "DoS0 = %g\n", DoS0);
    fprintf(fplog, "Dos2 = %g\n", dos2);
    fprintf(fplog, "DoSTot = %g\n", dostot);

    /* Now compute solid (2) and diffusive (3) components */
    fp = xvgropen(opt2fn("-dos", NFILE, fnm), "Density of states",
                  bRecip ? "E (cm\\S-1\\N)" : "\\f{12}n\\f{4} (1/ps)",
                  "\\f{4}S(\\f{12}n\\f{4})", oenv);
    xvgr_legend(fp, asize(DoSlegend), DoSlegend, oenv);
    recip_fac = bRecip ? (1e7/SPEED_OF_LIGHT) : 1.0;
    for (j = 0; (j < nframes/4); j++)
    {
        dos[DOS_DIFF][j]  = DoS0/(1+sqr(DoS0*M_PI*nu[j]/(6*f*Natom)));
        dos[DOS_SOLID][j] = dos[DOS][j]-dos[DOS_DIFF][j];
        fprintf(fp, "%10g  %10g  %10g  %10g\n",
                recip_fac*nu[j],
                dos[DOS][j]/recip_fac,
                dos[DOS_SOLID][j]/recip_fac,
                dos[DOS_DIFF][j]/recip_fac);
    }
    xvgrclose(fp);

    /* Finally analyze the results! */
    wCdiff = 0.5;
    wSdiff = Shs/(3*BOLTZ); /* Is this correct? */
    wEdiff = 0.5;
    wAdiff = wEdiff-wSdiff;
    for (j = 0; (j < nframes/4); j++)
    {
        dos[DOS_CP][j] = (dos[DOS_DIFF][j]*wCdiff +
                          dos[DOS_SOLID][j]*wCsolid(nu[j], beta));
        dos[DOS_S][j]  = (dos[DOS_DIFF][j]*wSdiff +
                          dos[DOS_SOLID][j]*wSsolid(nu[j], beta));
        dos[DOS_A][j]  = (dos[DOS_DIFF][j]*wAdiff +
                          dos[DOS_SOLID][j]*wAsolid(nu[j], beta));
        dos[DOS_E][j]  = (dos[DOS_DIFF][j]*wEdiff +
                          dos[DOS_SOLID][j]*wEsolid(nu[j], beta));
    }
    DiffCoeff = evaluate_integral(nframes/2, tt, dos[VACF], NULL, nframes/2, &stddev);
    DiffCoeff = 1000*DiffCoeff/3.0;
    fprintf(fplog, "Diffusion coefficient from VACF %g 10^-5 cm^2/s\n",
            DiffCoeff);
    fprintf(fplog, "Diffusion coefficient from DoS %g 10^-5 cm^2/s\n",
            1000*DoS0/(12*tmass*beta));

    cP = BOLTZ * evaluate_integral(nframes/4, nu, dos[DOS_CP], NULL,
                                   nframes/4, &stddev);
    fprintf(fplog, "Heat capacity %g J/mol K\n", 1000*cP/Nmol);

    /*
       S  = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_S],NULL,
                                   nframes/4,&stddev);
       fprintf(fplog,"Entropy %g J/mol K\n",1000*S/Nmol);
       A  = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_A],NULL,
                                   nframes/4,&stddev);
       fprintf(fplog,"Helmholtz energy %g kJ/mol\n",A/Nmol);
       E  = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_E],NULL,
                                   nframes/4,&stddev);
       fprintf(fplog,"Internal energy %g kJ/mol\n",E/Nmol);
     */
    fprintf(fplog, "\nArrivederci!\n");
    gmx_fio_fclose(fplog);

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy");

    thanx(stderr);

    return 0;
}
Exemple #7
0
int gmx_gyrate(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] computes the radius of gyration of a molecule",
        "and the radii of gyration about the [IT]x[it]-, [IT]y[it]- and [IT]z[it]-axes,",
        "as a function of time. The atoms are explicitly mass weighted.[PAR]",
        "The axis components corresponds to the mass-weighted root-mean-square",
        "of the radii components orthogonal to each axis, for example:[PAR]",
        "Rg(x) = sqrt((sum_i m_i (R_i(y)^2 + R_i(z)^2))/(sum_i m_i)).[PAR]",
        "With the [TT]-nmol[tt] option the radius of gyration will be calculated",
        "for multiple molecules by splitting the analysis group in equally",
        "sized parts.[PAR]",
        "With the option [TT]-nz[tt] 2D radii of gyration in the [IT]x-y[it] plane",
        "of slices along the [IT]z[it]-axis are calculated."
    };
    static int        nmol = 1, nz = 0;
    static gmx_bool   bQ   = FALSE, bRot = FALSE, bMOI = FALSE;
    t_pargs           pa[] = {
        { "-nmol", FALSE, etINT, {&nmol},
          "The number of molecules to analyze" },
        { "-q", FALSE, etBOOL, {&bQ},
          "Use absolute value of the charge of an atom as weighting factor instead of mass" },
        { "-p", FALSE, etBOOL, {&bRot},
          "Calculate the radii of gyration about the principal axes." },
        { "-moi", FALSE, etBOOL, {&bMOI},
          "Calculate the moments of inertia (defined by the principal axes)." },
        { "-nz", FALSE, etINT, {&nz},
          "Calculate the 2D radii of gyration of this number of slices along the z-axis" },
    };
    FILE             *out;
    t_trxstatus      *status;
    t_topology        top;
    int               ePBC;
    rvec             *x, *x_s;
    rvec              xcm, gvec, gvec1;
    matrix            box, trans;
    gmx_bool          bACF;
    real            **moi_trans = NULL;
    int               max_moi   = 0, delta_moi = 100;
    rvec              d, d1; /* eigenvalues of inertia tensor */
    real              t, t0, tm, gyro;
    int               natoms;
    char             *grpname;
    int               j, m, gnx, nam, mol;
    atom_id          *index;
    gmx_output_env_t *oenv;
    gmx_rmpbc_t       gpbc   = NULL;
    const char       *leg[]  = { "Rg", "Rg\\sX\\N", "Rg\\sY\\N", "Rg\\sZ\\N" };
    const char       *legI[] = { "Itot", "I1", "I2", "I3" };
#define NLEG asize(leg)
    t_filenm          fnm[] = {
        { efTRX, "-f",   NULL,       ffREAD },
        { efTPS, NULL,   NULL,       ffREAD },
        { efNDX, NULL,   NULL,       ffOPTRD },
        { efXVG, NULL,   "gyrate",   ffWRITE },
        { efXVG, "-acf", "moi-acf",  ffOPTWR },
    };
#define NFILE asize(fnm)
    int               npargs;
    t_pargs          *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }
    bACF = opt2bSet("-acf", NFILE, fnm);
    if (bACF && nmol != 1)
    {
        gmx_fatal(FARGS, "Can only do acf with nmol=1");
    }
    bRot = bRot || bMOI || bACF;
    /*
       if (nz > 0)
       bMOI = TRUE;
     */
    if (bRot)
    {
        printf("Will rotate system along principal axes\n");
        snew(moi_trans, DIM);
    }
    if (bMOI)
    {
        printf("Will print moments of inertia\n");
        bQ = FALSE;
    }
    if (bQ)
    {
        printf("Will print radius normalised by charge\n");
    }

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, NULL, box, TRUE);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);

    if (nmol > gnx || gnx % nmol != 0)
    {
        gmx_fatal(FARGS, "The number of atoms in the group (%d) is not a multiple of nmol (%d)", gnx, nmol);
    }
    nam = gnx/nmol;

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
    snew(x_s, natoms);

    j  = 0;
    t0 = t;
    if (bQ)
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Radius of Charge (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
    }
    else if (bMOI)
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Moments of inertia (total and around axes)", "Time (ps)", "I (a.m.u. nm\\S2\\N)", oenv);
    }
    else
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Radius of gyration (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
    }
    if (bMOI)
    {
        xvgr_legend(out, NLEG, legI, oenv);
    }
    else
    {
        if (bRot)
        {
            if (output_env_get_print_xvgr_codes(oenv))
            {
                fprintf(out, "@ subtitle \"Axes are principal component axes\"\n");
            }
        }
        xvgr_legend(out, NLEG, leg, oenv);
    }
    if (nz == 0)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    }
    do
    {
        if (nz == 0)
        {
            gmx_rmpbc_copy(gpbc, natoms, box, x, x_s);
        }
        gyro = 0;
        clear_rvec(gvec);
        clear_rvec(gvec1);
        clear_rvec(d);
        clear_rvec(d1);
        for (mol = 0; mol < nmol; mol++)
        {
            tm    = sub_xcm(nz == 0 ? x_s : x, nam, index+mol*nam, top.atoms.atom, xcm, bQ);
            if (nz == 0)
            {
                gyro += calc_gyro(x_s, nam, index+mol*nam, top.atoms.atom,
                                  tm, gvec1, d1, bQ, bRot, bMOI, trans);
            }
            else
            {
                calc_gyro_z(x, box, nam, index+mol*nam, top.atoms.atom, nz, t, out);
            }
            rvec_inc(gvec, gvec1);
            rvec_inc(d, d1);
        }
        if (nmol > 0)
        {
            gyro /= nmol;
            svmul(1.0/nmol, gvec, gvec);
            svmul(1.0/nmol, d, d);
        }

        if (nz == 0)
        {
            if (bRot)
            {
                if (j >= max_moi)
                {
                    max_moi += delta_moi;
                    for (m = 0; (m < DIM); m++)
                    {
                        srenew(moi_trans[m], max_moi*DIM);
                    }
                }
                for (m = 0; (m < DIM); m++)
                {
                    copy_rvec(trans[m], moi_trans[m]+DIM*j);
                }
                fprintf(out, "%10g  %10g  %10g  %10g  %10g\n",
                        t, gyro, d[XX], d[YY], d[ZZ]);
            }
            else
            {
                fprintf(out, "%10g  %10g  %10g  %10g  %10g\n",
                        t, gyro, gvec[XX], gvec[YY], gvec[ZZ]);
            }
        }
        j++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);
    if (nz == 0)
    {
        gmx_rmpbc_done(gpbc);
    }

    xvgrclose(out);

    if (bACF)
    {
        int mode = eacVector;

        do_autocorr(opt2fn("-acf", NFILE, fnm), oenv,
                    "Moment of inertia vector ACF",
                    j, 3, moi_trans, (t-t0)/j, mode, FALSE);
        do_view(oenv, opt2fn("-acf", NFILE, fnm), "-nxy");
    }

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy");

    return 0;
}
Exemple #8
0
int gmx_g_angle(int argc, char *argv[])
{
    static const char *desc[] = {
        "[TT]g_angle[tt] computes the angle distribution for a number of angles",
        "or dihedrals.[PAR]",
        "With option [TT]-ov[tt], you can plot the average angle of",
        "a group of angles as a function of time. With the [TT]-all[tt] option,",
        "the first graph is the average and the rest are the individual angles.[PAR]",
        "With the [TT]-of[tt] option, [TT]g_angle[tt] also calculates the fraction of trans",
        "dihedrals (only for dihedrals) as function of time, but this is",
        "probably only fun for a select few.[PAR]",
        "With option [TT]-oc[tt], a dihedral correlation function is calculated.[PAR]",
        "It should be noted that the index file must contain",
        "atom triplets for angles or atom quadruplets for dihedrals.",
        "If this is not the case, the program will crash.[PAR]",
        "With option [TT]-or[tt], a trajectory file is dumped containing cos and",
        "sin of selected dihedral angles, which subsequently can be used as",
        "input for a principal components analysis using [TT]g_covar[tt].[PAR]",
        "Option [TT]-ot[tt] plots when transitions occur between",
        "dihedral rotamers of multiplicity 3 and [TT]-oh[tt]",
        "records a histogram of the times between such transitions,",
        "assuming the input trajectory frames are equally spaced in time."
    };
    static const char *opt[]    = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL };
    static gmx_bool    bALL     = FALSE, bChandler = FALSE, bAverCorr = FALSE, bPBC = TRUE;
    static real        binwidth = 1;
    t_pargs            pa[]     = {
        {   "-type", FALSE, etENUM, {opt},
            "Type of angle to analyse"
        },
        {   "-all",    FALSE,  etBOOL, {&bALL},
            "Plot all angles separately in the averages file, in the order of appearance in the index file."
        },
        {   "-binwidth", FALSE, etREAL, {&binwidth},
            "binwidth (degrees) for calculating the distribution"
        },
        {   "-periodic", FALSE, etBOOL, {&bPBC},
            "Print dihedral angles modulo 360 degrees"
        },
        {   "-chandler", FALSE,  etBOOL, {&bChandler},
            "Use Chandler correlation function (N[trans] = 1, N[gauche] = 0) rather than cosine correlation function. Trans is defined as phi < -60 or phi > 60."
        },
        {   "-avercorr", FALSE,  etBOOL, {&bAverCorr},
            "Average the correlation functions for the individual angles/dihedrals"
        }
    };
    static const char *bugs[] = {
        "Counting transitions only works for dihedrals with multiplicity 3"
    };

    FILE              *out;
    real               tmp, dt;
    int                status, isize;
    atom_id           *index;
    char              *grpname;
    real               maxang, Jc, S2, norm_fac, maxstat;
    unsigned long      mode;
    int                nframes, maxangstat, mult, *angstat;
    int                i, j, total, nangles, natoms, nat2, first, last, angind;
    gmx_bool           bAver, bRb, bPeriodic,
                       bFrac,                           /* calculate fraction too?  */
                       bTrans,                          /* worry about transtions too? */
                       bCorr;                           /* correlation function ? */
    real         t, aa, aver, aver2, aversig, fraction; /* fraction trans dihedrals */
    double       tfrac = 0;
    char         title[256];
    real       **dih = NULL;      /* mega array with all dih. angles at all times*/
    char         buf[80];
    real        *time, *trans_frac, *aver_angle;
    t_filenm     fnm[] = {
        { efTRX, "-f", NULL,  ffREAD  },
        { efNDX, NULL, "angle",  ffREAD  },
        { efXVG, "-od", "angdist",  ffWRITE },
        { efXVG, "-ov", "angaver",  ffOPTWR },
        { efXVG, "-of", "dihfrac",  ffOPTWR },
        { efXVG, "-ot", "dihtrans", ffOPTWR },
        { efXVG, "-oh", "trhisto",  ffOPTWR },
        { efXVG, "-oc", "dihcorr",  ffOPTWR },
        { efTRR, "-or", NULL,       ffOPTWR }
    };
#define NFILE asize(fnm)
    int          npargs;
    t_pargs     *ppa;
    output_env_t oenv;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);
    parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs,
                      &oenv);

    mult   = 4;
    maxang = 360.0;
    bRb    = FALSE;
    switch (opt[0][0])
    {
    case 'a':
        mult   = 3;
        maxang = 180.0;
        break;
    case 'd':
        break;
    case 'i':
        break;
    case 'r':
        bRb = TRUE;
        break;
    }

    if (opt2bSet("-or", NFILE, fnm))
    {
        if (mult != 4)
        {
            gmx_fatal(FARGS, "Can not combine angles with trn dump");
        }
        else
        {
            please_cite(stdout, "Mu2005a");
        }
    }

    /* Calculate bin size */
    maxangstat = (int)(maxang/binwidth+0.5);
    binwidth   = maxang/maxangstat;

    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
    nangles = isize/mult;
    if ((isize % mult) != 0)
    {
        gmx_fatal(FARGS, "number of index elements not multiple of %d, "
                  "these can not be %s\n",
                  mult, (mult == 3) ? "angle triplets" : "dihedral quadruplets");
    }


    /* Check whether specific analysis has to be performed */
    bCorr  = opt2bSet("-oc", NFILE, fnm);
    bAver  = opt2bSet("-ov", NFILE, fnm);
    bTrans = opt2bSet("-ot", NFILE, fnm);
    bFrac  = opt2bSet("-of", NFILE, fnm);
    if (bTrans && opt[0][0] != 'd')
    {
        fprintf(stderr, "Option -ot should only accompany -type dihedral. Disabling -ot.\n");
        bTrans = FALSE;
    }

    if (bChandler && !bCorr)
    {
        bCorr = TRUE;
    }

    if (bFrac && !bRb)
    {
        fprintf(stderr, "Warning:"
                " calculating fractions as defined in this program\n"
                "makes sense for Ryckaert Bellemans dihs. only. Ignoring -of\n\n");
        bFrac = FALSE;
    }

    if ( (bTrans || bFrac || bCorr) && mult == 3)
    {
        gmx_fatal(FARGS, "Can only do transition, fraction or correlation\n"
                  "on dihedrals. Select -d\n");
    }

    /*
     * We need to know the nr of frames so we can allocate memory for an array
     * with all dihedral angles at all timesteps. Works for me.
     */
    if (bTrans || bCorr  || bALL || opt2bSet("-or", NFILE, fnm))
    {
        snew(dih, nangles);
    }

    snew(angstat, maxangstat);

    read_ang_dih(ftp2fn(efTRX, NFILE, fnm), (mult == 3),
                 bALL || bCorr || bTrans || opt2bSet("-or", NFILE, fnm),
                 bRb, bPBC, maxangstat, angstat,
                 &nframes, &time, isize, index, &trans_frac, &aver_angle, dih,
                 oenv);

    dt = (time[nframes-1]-time[0])/(nframes-1);

    if (bAver)
    {
        sprintf(title, "Average Angle: %s", grpname);
        out = xvgropen(opt2fn("-ov", NFILE, fnm),
                       title, "Time (ps)", "Angle (degrees)", oenv);
        for (i = 0; (i < nframes); i++)
        {
            fprintf(out, "%10.5f  %8.3f", time[i], aver_angle[i]*RAD2DEG);
            if (bALL)
            {
                for (j = 0; (j < nangles); j++)
                {
                    if (bPBC)
                    {
                        real dd = dih[j][i];
                        fprintf(out, "  %8.3f", atan2(sin(dd), cos(dd))*RAD2DEG);
                    }
                    else
                    {
                        fprintf(out, "  %8.3f", dih[j][i]*RAD2DEG);
                    }
                }
            }
            fprintf(out, "\n");
        }
        ffclose(out);
    }
    if (opt2bSet("-or", NFILE, fnm))
    {
        dump_dih_trn(nframes, nangles, dih, opt2fn("-or", NFILE, fnm), time);
    }

    if (bFrac)
    {
        sprintf(title, "Trans fraction: %s", grpname);
        out = xvgropen(opt2fn("-of", NFILE, fnm),
                       title, "Time (ps)", "Fraction", oenv);
        tfrac = 0.0;
        for (i = 0; (i < nframes); i++)
        {
            fprintf(out, "%10.5f  %10.3f\n", time[i], trans_frac[i]);
            tfrac += trans_frac[i];
        }
        ffclose(out);

        tfrac /= nframes;
        fprintf(stderr, "Average trans fraction: %g\n", tfrac);
    }
    sfree(trans_frac);

    if (bTrans)
    {
        ana_dih_trans(opt2fn("-ot", NFILE, fnm), opt2fn("-oh", NFILE, fnm),
                      dih, nframes, nangles, grpname, time, bRb, oenv);
    }

    if (bCorr)
    {
        /* Autocorrelation function */
        if (nframes < 2)
        {
            fprintf(stderr, "Not enough frames for correlation function\n");
        }
        else
        {

            if (bChandler)
            {
                real     dval, sixty = DEG2RAD*60;
                gmx_bool bTest;

                for (i = 0; (i < nangles); i++)
                {
                    for (j = 0; (j < nframes); j++)
                    {
                        dval = dih[i][j];
                        if (bRb)
                        {
                            bTest = (dval > -sixty) && (dval < sixty);
                        }
                        else
                        {
                            bTest = (dval < -sixty) || (dval > sixty);
                        }
                        if (bTest)
                        {
                            dih[i][j] = dval-tfrac;
                        }
                        else
                        {
                            dih[i][j] = -tfrac;
                        }
                    }
                }
            }
            if (bChandler)
            {
                mode = eacNormal;
            }
            else
            {
                mode = eacCos;
            }
            do_autocorr(opt2fn("-oc", NFILE, fnm), oenv,
                        "Dihedral Autocorrelation Function",
                        nframes, nangles, dih, dt, mode, bAverCorr);
        }
    }


    /* Determine the non-zero part of the distribution */
    for (first = 0; (first < maxangstat-1) && (angstat[first+1] == 0); first++)
    {
        ;
    }
    for (last = maxangstat-1; (last > 0) && (angstat[last-1] == 0); last--)
    {
        ;
    }

    aver = aver2 = 0;
    for (i = 0; (i < nframes); i++)
    {
        aver  += RAD2DEG*aver_angle[i];
        aver2 += sqr(RAD2DEG*aver_angle[i]);
    }
    aver   /= (real) nframes;
    aver2  /= (real) nframes;
    aversig = sqrt(aver2-sqr(aver));
    printf("Found points in the range from %d to %d (max %d)\n",
           first, last, maxangstat);
    printf(" < angle >  = %g\n", aver);
    printf("< angle^2 > = %g\n", aver2);
    printf("Std. Dev.   = %g\n", aversig);

    if (mult == 3)
    {
        sprintf(title, "Angle Distribution: %s", grpname);
    }
    else
    {
        sprintf(title, "Dihedral Distribution: %s", grpname);

        calc_distribution_props(maxangstat, angstat, -180.0, 0, NULL, &S2);
        fprintf(stderr, "Order parameter S^2 = %g\n", S2);
    }

    bPeriodic = (mult == 4) && (first == 0) && (last == maxangstat-1);

    out = xvgropen(opt2fn("-od", NFILE, fnm), title, "Degrees", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@    subtitle \"average angle: %g\\So\\N\"\n", aver);
    }
    norm_fac = 1.0/(nangles*nframes*binwidth);
    if (bPeriodic)
    {
        maxstat = 0;
        for (i = first; (i <= last); i++)
        {
            maxstat = max(maxstat, angstat[i]*norm_fac);
        }
        fprintf(out, "@with g0\n");
        fprintf(out, "@    world xmin -180\n");
        fprintf(out, "@    world xmax  180\n");
        fprintf(out, "@    world ymin 0\n");
        fprintf(out, "@    world ymax %g\n", maxstat*1.05);
        fprintf(out, "@    xaxis  tick major 60\n");
        fprintf(out, "@    xaxis  tick minor 30\n");
        fprintf(out, "@    yaxis  tick major 0.005\n");
        fprintf(out, "@    yaxis  tick minor 0.0025\n");
    }
    for (i = first; (i <= last); i++)
    {
        fprintf(out, "%10g  %10f\n", i*binwidth+180.0-maxang, angstat[i]*norm_fac);
    }
    if (bPeriodic)
    {
        /* print first bin again as last one */
        fprintf(out, "%10g  %10f\n", 180.0, angstat[0]*norm_fac);
    }

    ffclose(out);

    do_view(oenv, opt2fn("-od", NFILE, fnm), "-nxy");
    if (bAver)
    {
        do_view(oenv, opt2fn("-ov", NFILE, fnm), "-nxy");
    }

    thanx(stderr);

    return 0;
}
Exemple #9
0
int main(int argc,char *argv[])
{
  FILE *fp;
  const char *desc[] = {
    "testac tests the functioning of the GROMACS acf routines"
  };
  static int nframes = 1024;
  static int datatp  = 0;
  static real a=0.02*M_PI;
  output_env_t oenv;
  t_pargs pa[] = {
    { "-np", FALSE, etINT, &nframes,
      "Number of data points" },
    { "-dtp",FALSE, etINT, &datatp,
      "Which data: 0=all 0.0, 1=all 1.0, 2=cos(a t), 3=random, 4=cos(a t)+random, 5=sin(a t)/(a t)" }
  };
  static char *str[] = {
    "all 0.0", 
    "all 1.0",
    "cos(a t)",
    "random", 
    "cos(a t)+random",
    "sin(a t)/(a t)"
  };
  t_filenm fnm[] = {
    { efXVG, "-d", "acf-data", ffWRITE },
    { efXVG, "-c", "acf-corr", ffWRITE },
    { efXVG, "-comb", "acf-comb.xvg", ffWRITE }
  };
#define NFILE asize(fnm)
  int     npargs,i,nlag;
  int     seed=1993;
  real    *data,*data2,x;
  t_pargs *ppa;
  
  CopyRight(stderr,argv[0]);
  npargs = asize(pa);
  ppa    = add_acf_pargs(&npargs,pa);
  parse_common_args_r(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
		      NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
  snew(data,nframes);
  snew(data2,nframes);
  
  fp = xvgropen(opt2fn("-d",NFILE,fnm),"testac","x","y",oenv);
  for(i=0; (i<nframes); i++) {
    x = a*i;
    switch (datatp) {
    case 1:
      data[i] = 1;
      break;
    case 2:
      data[i] = cos(x);
      break;
    case 3:
      data[i] = 2*rando(&seed)-1.0;
      break;
    case 4:
      data[i] = cos(x)+2*rando(&seed)-1.0;
      break;
    case 5:
      if (i==0)
	data[i] = 1;
      else
	data[i] = sin(x)/(x);
    default:
      /* Data remains 0.0 */
      break;
    }
    fprintf(fp,"%10g  %10g\n",x,data[i]);
    data2[i] = data[i];
  }
  ffclose(fp);
  
  do_autocorr(opt2fn("-c",NFILE,fnm),oenv,str[datatp],
	      nframes,1,&data,a,eacNormal,FALSE);
	      
  nlag = get_acfnout();
  fp = xvgropen(opt2fn("-comb",NFILE,fnm),"testac","x","y",oenv);
  for(i=0; (i<nlag); i++) {
    fprintf(fp,"%10g  %10g  %10g\n",a*i,data2[i],data[i]);
  }
  ffclose(fp);

  do_view(opt2fn("-c",NFILE,fnm),"-nxy");
    
  thanx(stderr);

  return 0;
}
Exemple #10
0
int gmx_dos(int argc, char *argv[])
{
    const char         *desc[] = {
        "[THISMODULE] computes the Density of States from a simulations.",
        "In order for this to be meaningful the velocities must be saved",
        "in the trajecotry with sufficiently high frequency such as to cover",
        "all vibrations. For flexible systems that would be around a few fs",
        "between saving. Properties based on the DoS are printed on the",
        "standard output."
        "Note that the density of states is calculated from the mass-weighted",
        "autocorrelation, and by default only from the square of the real",
        "component rather than absolute value. This means the shape can differ",
        "substantially from the plain vibrational power spectrum you can",
        "calculate with gmx velacc."
    };
    const char         *bugs[] = {
        "This program needs a lot of memory: total usage equals the number of atoms times 3 times number of frames times 4 (or 8 when run in double precision)."
    };
    FILE               *fp, *fplog;
    t_topology          top;
    int                 ePBC = -1;
    t_trxframe          fr;
    matrix              box;
    int                 gnx;
    real                t0, t1;
    t_trxstatus        *status;
    int                 nV, nframes, n_alloc, i, j, fftcode, Nmol, Natom;
    double              rho, dt, Vsum, V, tmass, dostot, dos2;
    real              **c1, **dos, mi, beta, bfac, *nu, *tt, stddev, c1j;
    gmx_output_env_t   *oenv;
    gmx_fft_t           fft;
    double              cP, DiffCoeff, Delta, f, y, z, sigHS, Shs, Sig, DoS0, recip_fac;
    double              wCdiff, wSdiff, wAdiff, wEdiff;
    int                 grpNatoms;
    int                *index;
    char               *grpname;
    double              invNormalize;
    gmx_bool            normalizeAutocorrelation;

    static     gmx_bool bVerbose = TRUE, bAbsolute = FALSE, bNormalizeDos = FALSE;
    static     gmx_bool bRecip   = FALSE;
    static     real     Temp     = 298.15, toler = 1e-6;

    t_pargs             pa[]     = {
        {   "-v", FALSE, etBOOL, {&bVerbose},
            "Be loud and noisy."
        },
        {   "-recip", FALSE, etBOOL, {&bRecip},
            "Use cm^-1 on X-axis instead of 1/ps for DoS plots."
        },
        {   "-abs", FALSE, etBOOL, {&bAbsolute},
            "Use the absolute value of the Fourier transform of the VACF as the Density of States. Default is to use the real component only"
        },
        {   "-normdos", FALSE, etBOOL, {&bNormalizeDos},
            "Normalize the DoS such that it adds up to 3N. This should usually not be necessary."
        },
        {   "-T", FALSE, etREAL, {&Temp},
            "Temperature in the simulation"
        },
        {   "-toler", FALSE, etREAL, {&toler},
            "[HIDDEN]Tolerance when computing the fluidicity using bisection algorithm"
        }
    };

    t_filenm            fnm[] = {
        { efTRN, "-f",    NULL,    ffREAD  },
        { efTPR, "-s",    NULL,    ffREAD  },
        { efNDX, NULL,    NULL,    ffOPTRD },
        { efXVG, "-vacf", "vacf",  ffWRITE },
        { efXVG, "-mvacf", "mvacf", ffWRITE },
        { efXVG, "-dos",  "dos",   ffWRITE },
        { efLOG, "-g",    "dos",   ffWRITE },
    };
#define NFILE asize(fnm)
    int                 npargs;
    t_pargs            *ppa;
    const char         *DoSlegend[] = {
        "DoS(v)", "DoS(v)[Solid]", "DoS(v)[Diff]"
    };

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);
    if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
                           NFILE, fnm, npargs, ppa, asize(desc), desc,
                           asize(bugs), bugs, &oenv))
    {
        return 0;
    }

    beta = 1/(Temp*BOLTZ);

    fplog = gmx_fio_fopen(ftp2fn(efLOG, NFILE, fnm), "w");
    fprintf(fplog, "Doing density of states analysis based on trajectory.\n");
    please_cite(fplog, "Pascal2011a");
    please_cite(fplog, "Caleman2011b");

    read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &ePBC, NULL, NULL, box, TRUE);

    /* Handle index groups */
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &grpNatoms, &index, &grpname);

    V     = det(box);
    tmass = 0;
    for (i = 0; i < grpNatoms; i++)
    {
        tmass += top.atoms.atom[index[i]].m;
    }

    Natom = grpNatoms;
    Nmol  = calcMoleculesInIndexGroup(&top.mols, top.atoms.nr, index, grpNatoms);
    gnx   = Natom*DIM;

    /* Correlation stuff */
    snew(c1, gnx);
    for (i = 0; (i < gnx); i++)
    {
        c1[i] = NULL;
    }

    read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr, TRX_NEED_V);
    t0 = fr.time;

    n_alloc = 0;
    nframes = 0;
    Vsum    = 0;
    nV      = 0;
    do
    {
        if (fr.bBox)
        {
            V      = det(fr.box);
            Vsum  += V;
            nV++;
        }
        if (nframes >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < gnx; i++)
            {
                srenew(c1[i], n_alloc);
            }
        }
        for (i = 0; i < gnx; i += DIM)
        {
            c1[i+XX][nframes] = fr.v[index[i/DIM]][XX];
            c1[i+YY][nframes] = fr.v[index[i/DIM]][YY];
            c1[i+ZZ][nframes] = fr.v[index[i/DIM]][ZZ];
        }

        t1 = fr.time;

        nframes++;
    }
    while (read_next_frame(oenv, status, &fr));

    close_trj(status);

    dt = (t1-t0)/(nframes-1);
    if (nV > 0)
    {
        V = Vsum/nV;
    }
    if (bVerbose)
    {
        printf("Going to do %d fourier transforms of length %d. Hang on.\n",
               gnx, nframes);
    }
    /* Unfortunately the -normalize program option for the autocorrelation
     * function calculation is added as a hack with a static variable in the
     * autocorrelation.c source. That would work if we called the normal
     * do_autocorr(), but this routine overrides that by directly calling
     * the low-level functionality. That unfortunately leads to ignoring the
     * default value for the option (which is to normalize).
     * Since the absolute value seems to be important for the subsequent
     * analysis below, we detect the value directly from the option, calculate
     * the autocorrelation without normalization, and then apply the
     * normalization just to the autocorrelation output
     * (or not, if the user asked for a non-normalized autocorrelation).
     */
    normalizeAutocorrelation = opt2parg_bool("-normalize", npargs, ppa);

    /* Note that we always disable normalization here, regardless of user settings */
    low_do_autocorr(NULL, oenv, NULL, nframes, gnx, nframes, c1, dt, eacNormal, 0, FALSE,
                    FALSE, FALSE, -1, -1, 0);
    snew(dos, DOS_NR);
    for (j = 0; (j < DOS_NR); j++)
    {
        snew(dos[j], nframes+4);
    }

    if (bVerbose)
    {
        printf("Going to merge the ACFs into the mass-weighted and plain ACF\n");
    }
    for (i = 0; (i < gnx); i += DIM)
    {
        mi = top.atoms.atom[index[i/DIM]].m;
        for (j = 0; (j < nframes/2); j++)
        {
            c1j            = (c1[i+XX][j] + c1[i+YY][j] + c1[i+ZZ][j]);
            dos[VACF][j]  += c1j/Natom;
            dos[MVACF][j] += mi*c1j;
        }
    }

    fp = xvgropen(opt2fn("-vacf", NFILE, fnm), "Velocity autocorrelation function",
                  "Time (ps)", "C(t)", oenv);
    snew(tt, nframes/2);

    invNormalize = normalizeAutocorrelation ? 1.0/dos[VACF][0] : 1.0;

    for (j = 0; (j < nframes/2); j++)
    {
        tt[j] = j*dt;
        fprintf(fp, "%10g  %10g\n", tt[j], dos[VACF][j] * invNormalize);
    }
    xvgrclose(fp);

    fp = xvgropen(opt2fn("-mvacf", NFILE, fnm), "Mass-weighted velocity autocorrelation function",
                  "Time (ps)", "C(t)", oenv);

    invNormalize = normalizeAutocorrelation ? 1.0/dos[VACF][0] : 1.0;

    for (j = 0; (j < nframes/2); j++)
    {
        fprintf(fp, "%10g  %10g\n", tt[j], dos[MVACF][j] * invNormalize);
    }
    xvgrclose(fp);

    if ((fftcode = gmx_fft_init_1d_real(&fft, nframes/2,
                                        GMX_FFT_FLAG_NONE)) != 0)
    {
        gmx_fatal(FARGS, "gmx_fft_init_1d_real returned %d", fftcode);
    }
    if ((fftcode = gmx_fft_1d_real(fft, GMX_FFT_REAL_TO_COMPLEX,
                                   (void *)dos[MVACF], (void *)dos[DOS])) != 0)
    {
        gmx_fatal(FARGS, "gmx_fft_1d_real returned %d", fftcode);
    }

    /* First compute the DoS */
    /* Magic factor of 8 included now. */
    bfac = 8*dt*beta/2;
    dos2 = 0;
    snew(nu, nframes/4);
    for (j = 0; (j < nframes/4); j++)
    {
        nu[j] = 2*j/(t1-t0);
        dos2 += gmx::square(dos[DOS][2*j]) + gmx::square(dos[DOS][2*j+1]);
        if (bAbsolute)
        {
            dos[DOS][j] = bfac*std::hypot(dos[DOS][2*j], dos[DOS][2*j+1]);
        }
        else
        {
            dos[DOS][j] = bfac*dos[DOS][2*j];
        }
    }
    /* Normalize it */
    dostot = evaluate_integral(nframes/4, nu, dos[DOS], NULL, nframes/4, &stddev);
    if (bNormalizeDos)
    {
        for (j = 0; (j < nframes/4); j++)
        {
            dos[DOS][j] *= 3*Natom/dostot;
        }
    }

    /* Now analyze it */
    DoS0 = dos[DOS][0];

    /* Note this eqn. is incorrect in Pascal2011a! */
    Delta = ((2*DoS0/(9*Natom))*std::sqrt(M_PI*BOLTZ*Temp*Natom/tmass)*
             std::pow((Natom/V), 1.0/3.0)*std::pow(6.0/M_PI, 2.0/3.0));
    f     = calc_fluidicity(Delta, toler);
    y     = calc_y(f, Delta, toler);
    z     = calc_compress(y);
    Sig   = BOLTZ*(5.0/2.0+std::log(2*M_PI*BOLTZ*Temp/(gmx::square(PLANCK))*V/(f*Natom)));
    Shs   = Sig+calc_Shs(f, y);
    rho   = (tmass*AMU)/(V*NANO*NANO*NANO);
    sigHS = std::cbrt(6*y*V/(M_PI*Natom));

    fprintf(fplog, "System = \"%s\"\n", *top.name);
    fprintf(fplog, "Nmol = %d\n", Nmol);
    fprintf(fplog, "Natom = %d\n", Natom);
    fprintf(fplog, "dt = %g ps\n", dt);
    fprintf(fplog, "tmass = %g amu\n", tmass);
    fprintf(fplog, "V = %g nm^3\n", V);
    fprintf(fplog, "rho = %g g/l\n", rho);
    fprintf(fplog, "T = %g K\n", Temp);
    fprintf(fplog, "beta = %g mol/kJ\n", beta);

    fprintf(fplog, "\nDoS parameters\n");
    fprintf(fplog, "Delta = %g\n", Delta);
    fprintf(fplog, "fluidicity = %g\n", f);
    fprintf(fplog, "hard sphere packing fraction = %g\n", y);
    fprintf(fplog, "hard sphere compressibility = %g\n", z);
    fprintf(fplog, "ideal gas entropy = %g\n", Sig);
    fprintf(fplog, "hard sphere entropy = %g\n", Shs);
    fprintf(fplog, "sigma_HS = %g nm\n", sigHS);
    fprintf(fplog, "DoS0 = %g\n", DoS0);
    fprintf(fplog, "Dos2 = %g\n", dos2);
    fprintf(fplog, "DoSTot = %g\n", dostot);

    /* Now compute solid (2) and diffusive (3) components */
    fp = xvgropen(opt2fn("-dos", NFILE, fnm), "Density of states",
                  bRecip ? "E (cm\\S-1\\N)" : "\\f{12}n\\f{4} (1/ps)",
                  "\\f{4}S(\\f{12}n\\f{4})", oenv);
    xvgr_legend(fp, asize(DoSlegend), DoSlegend, oenv);
    recip_fac = bRecip ? (1e7/SPEED_OF_LIGHT) : 1.0;
    for (j = 0; (j < nframes/4); j++)
    {
        dos[DOS_DIFF][j]  = DoS0/(1+gmx::square(DoS0*M_PI*nu[j]/(6*f*Natom)));
        dos[DOS_SOLID][j] = dos[DOS][j]-dos[DOS_DIFF][j];
        fprintf(fp, "%10g  %10g  %10g  %10g\n",
                recip_fac*nu[j],
                dos[DOS][j]/recip_fac,
                dos[DOS_SOLID][j]/recip_fac,
                dos[DOS_DIFF][j]/recip_fac);
    }
    xvgrclose(fp);

    /* Finally analyze the results! */
    wCdiff = 0.5;
    wSdiff = Shs/(3*BOLTZ); /* Is this correct? */
    wEdiff = 0.5;
    wAdiff = wEdiff-wSdiff;
    for (j = 0; (j < nframes/4); j++)
    {
        dos[DOS_CP][j] = (dos[DOS_DIFF][j]*wCdiff +
                          dos[DOS_SOLID][j]*wCsolid(nu[j], beta));
        dos[DOS_S][j]  = (dos[DOS_DIFF][j]*wSdiff +
                          dos[DOS_SOLID][j]*wSsolid(nu[j], beta));
        dos[DOS_A][j]  = (dos[DOS_DIFF][j]*wAdiff +
                          dos[DOS_SOLID][j]*wAsolid(nu[j], beta));
        dos[DOS_E][j]  = (dos[DOS_DIFF][j]*wEdiff +
                          dos[DOS_SOLID][j]*wEsolid(nu[j], beta));
    }
    DiffCoeff = evaluate_integral(nframes/2, tt, dos[VACF], NULL, nframes/2, &stddev);
    DiffCoeff = 1000*DiffCoeff/3.0;
    fprintf(fplog, "Diffusion coefficient from VACF %g 10^-5 cm^2/s\n",
            DiffCoeff);
    fprintf(fplog, "Diffusion coefficient from DoS %g 10^-5 cm^2/s\n",
            1000*DoS0/(12*tmass*beta));

    cP = BOLTZ * evaluate_integral(nframes/4, nu, dos[DOS_CP], NULL,
                                   nframes/4, &stddev);
    fprintf(fplog, "Heat capacity %g J/mol K\n", 1000*cP/Nmol);
    fprintf(fplog, "\nArrivederci!\n");
    gmx_fio_fclose(fplog);

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy");

    return 0;
}
int gmx_chi(int argc,char *argv[])
{
  const char *desc[] = {
    "[TT]g_chi[tt] computes [GRK]phi[grk], [GRK]psi[grk], [GRK]omega[grk], and [GRK]chi[grk] dihedrals for all your ",
    "amino acid backbone and sidechains.",
    "It can compute dihedral angle as a function of time, and as",
    "histogram distributions.",
    "The distributions [TT](histo-(dihedral)(RESIDUE).xvg[tt]) are cumulative over all residues of each type.[PAR]", 
    "If option [TT]-corr[tt] is given, the program will",
    "calculate dihedral autocorrelation functions. The function used",
    "is C(t) = < cos([GRK]chi[grk]([GRK]tau[grk])) cos([GRK]chi[grk]([GRK]tau[grk]+t)) >. The use of cosines",
    "rather than angles themselves, resolves the problem of periodicity.",
    "(Van der Spoel & Berendsen (1997), Biophys. J. 72, 2032-2041).",
    "Separate files for each dihedral of each residue", 
    "[TT](corr(dihedral)(RESIDUE)(nresnr).xvg[tt]) are output, as well as a", 
    "file containing the information for all residues (argument of [TT]-corr[tt]).[PAR]", 
    "With option [TT]-all[tt], the angles themselves as a function of time for", 
    "each residue are printed to separate files [TT](dihedral)(RESIDUE)(nresnr).xvg[tt].", 
    "These can be in radians or degrees.[PAR]", 
    "A log file (argument [TT]-g[tt]) is also written. This contains [BR]",
    "(a) information about the number of residues of each type.[BR]", 
    "(b) The NMR ^3J coupling constants from the Karplus equation.[BR]", 
    "(c) a table for each residue of the number of transitions between ", 
    "rotamers per nanosecond,  and the order parameter S^2 of each dihedral.[BR]",
    "(d) a table for each residue of the rotamer occupancy.[PAR]", 
    "All rotamers are taken as 3-fold, except for [GRK]omega[grk] and [GRK]chi[grk] dihedrals",
    "to planar groups (i.e. [GRK]chi[grk]2 of aromatics, Asp and Asn; [GRK]chi[grk]3 of Glu", 
    "and Gln; and [GRK]chi[grk]4 of Arg), which are 2-fold. \"rotamer 0\" means ", 
    "that the dihedral was not in the core region of each rotamer. ", 
    "The width of the core region can be set with [TT]-core_rotamer[tt][PAR]", 

    "The S^2 order parameters are also output to an [TT].xvg[tt] file", 
    "(argument [TT]-o[tt] ) and optionally as a [TT].pdb[tt] file with", 
    "the S^2 values as B-factor (argument [TT]-p[tt]). ", 
    "The total number of rotamer transitions per timestep", 
    "(argument [TT]-ot[tt]), the number of transitions per rotamer", 
    "(argument [TT]-rt[tt]), and the ^3J couplings (argument [TT]-jc[tt]), ", 
    "can also be written to [TT].xvg[tt] files.[PAR]", 

    "If [TT]-chi_prod[tt] is set (and [TT]-maxchi[tt] > 0), cumulative rotamers, e.g.", 
    "1+9([GRK]chi[grk]1-1)+3([GRK]chi[grk]2-1)+([GRK]chi[grk]3-1) (if the residue has three 3-fold ", 
    "dihedrals and [TT]-maxchi[tt] >= 3)", 
    "are calculated. As before, if any dihedral is not in the core region,", 
    "the rotamer is taken to be 0. The occupancies of these cumulative ",
    "rotamers (starting with rotamer 0) are written to the file", 
    "that is the argument of [TT]-cp[tt], and if the [TT]-all[tt] flag", 
    "is given, the rotamers as functions of time", 
    "are written to [TT]chiproduct(RESIDUE)(nresnr).xvg[tt] ", 
    "and their occupancies to [TT]histo-chiproduct(RESIDUE)(nresnr).xvg[tt].[PAR]", 

    "The option [TT]-r[tt] generates a contour plot of the average [GRK]omega[grk] angle",
    "as a function of the [GRK]phi[grk] and [GRK]psi[grk] angles, that is, in a Ramachandran plot",
    "the average [GRK]omega[grk] angle is plotted using color coding.", 

  };
  
  const char *bugs[] = {
    "Produces MANY output files (up to about 4 times the number of residues in the protein, twice that if autocorrelation functions are calculated). Typically several hundred files are output.",
    "[GRK]phi[grk] and [GRK]psi[grk] dihedrals are calculated in a non-standard way, using H-N-CA-C for [GRK]phi[grk] instead of C(-)-N-CA-C, and N-CA-C-O for [GRK]psi[grk] instead of N-CA-C-N(+). This causes (usually small) discrepancies with the output of other tools like [TT]g_rama[tt].", 
    "[TT]-r0[tt] option does not work properly", 
    "Rotamers with multiplicity 2 are printed in [TT]chi.log[tt] as if they had multiplicity 3, with the 3rd (g(+)) always having probability 0" 
  };

  /* defaults */ 
  static int  r0=1,ndeg=1,maxchi=2;
  static gmx_bool bAll=FALSE;
  static gmx_bool bPhi=FALSE,bPsi=FALSE,bOmega=FALSE;
  static real bfac_init=-1.0,bfac_max=0;
  static const char *maxchistr[] = { NULL, "0", "1", "2", "3",  "4", "5", "6", NULL };
  static gmx_bool bRama=FALSE,bShift=FALSE,bViol=FALSE,bRamOmega=FALSE;
  static gmx_bool bNormHisto=TRUE,bChiProduct=FALSE,bHChi=FALSE,bRAD=FALSE,bPBC=TRUE;
  static real core_frac=0.5 ;  
  t_pargs pa[] = {
    { "-r0",  FALSE, etINT, {&r0},
      "starting residue" },
    { "-phi",  FALSE, etBOOL, {&bPhi},
      "Output for [GRK]phi[grk] dihedral angles" },
    { "-psi",  FALSE, etBOOL, {&bPsi},
      "Output for [GRK]psi[grk] dihedral angles" },
    { "-omega",FALSE, etBOOL, {&bOmega},  
      "Output for [GRK]omega[grk] dihedrals (peptide bonds)" },
    { "-rama", FALSE, etBOOL, {&bRama},
      "Generate [GRK]phi[grk]/[GRK]psi[grk] and [GRK]chi[grk]1/[GRK]chi[grk]2 Ramachandran plots" },
    { "-viol", FALSE, etBOOL, {&bViol},
      "Write a file that gives 0 or 1 for violated Ramachandran angles" },
    { "-periodic", FALSE, etBOOL, {&bPBC},
      "Print dihedral angles modulo 360 degrees" },
    { "-all",  FALSE, etBOOL, {&bAll},
      "Output separate files for every dihedral." },
    { "-rad",  FALSE, etBOOL, {&bRAD},
      "in angle vs time files, use radians rather than degrees."}, 
    { "-shift", FALSE, etBOOL, {&bShift},
	"Compute chemical shifts from [GRK]phi[grk]/[GRK]psi[grk] angles" },
    { "-binwidth", FALSE, etINT, {&ndeg},
      "bin width for histograms (degrees)" },
    { "-core_rotamer", FALSE, etREAL, {&core_frac},
      "only the central [TT]-core_rotamer[tt]*(360/multiplicity) belongs to each rotamer (the rest is assigned to rotamer 0)" },
    { "-maxchi", FALSE, etENUM, {maxchistr},
      "calculate first ndih [GRK]chi[grk] dihedrals" },
    { "-normhisto", FALSE, etBOOL, {&bNormHisto},
      "Normalize histograms" },
    { "-ramomega",FALSE,etBOOL, {&bRamOmega},
      "compute average omega as a function of phi/psi and plot it in an [TT].xpm[tt] plot" },
    { "-bfact", FALSE, etREAL, {&bfac_init},
      "B-factor value for [TT].pdb[tt] file for atoms with no calculated dihedral order parameter"},
    { "-chi_prod",FALSE,etBOOL, {&bChiProduct},
      "compute a single cumulative rotamer for each residue"},
    { "-HChi",FALSE,etBOOL, {&bHChi},
      "Include dihedrals to sidechain hydrogens"}, 
    { "-bmax",  FALSE, etREAL, {&bfac_max},
      "Maximum B-factor on any of the atoms that make up a dihedral, for the dihedral angle to be considere in the statistics. Applies to database work where a number of X-Ray structures is analyzed. [TT]-bmax[tt] <= 0 means no limit." }
  };

  FILE       *log;
  int        natoms,nlist,idum,nbin;
  t_atoms    atoms;
  rvec       *x;
  int        ePBC;
  matrix     box;
  char       title[256],grpname[256]; 
  t_dlist    *dlist;
  gmx_bool       bChi,bCorr,bSSHisto;
  gmx_bool       bDo_rt, bDo_oh, bDo_ot, bDo_jc ; 
  real       dt=0, traj_t_ns;
  output_env_t oenv;
  gmx_residuetype_t rt;
  
  atom_id    isize,*index;
  int        ndih,nactdih,nf;
  real       **dih,*trans_frac,*aver_angle,*time;
  int        i,j,**chi_lookup,*xity; 
  
  t_filenm  fnm[] = {
    { efSTX, "-s",  NULL,     ffREAD  },
    { efTRX, "-f",  NULL,     ffREAD  },
    { efXVG, "-o",  "order",  ffWRITE },
    { efPDB, "-p",  "order",  ffOPTWR },
    { efDAT, "-ss", "ssdump", ffOPTRD },
    { efXVG, "-jc", "Jcoupling", ffWRITE },
    { efXVG, "-corr",  "dihcorr",ffOPTWR },
    { efLOG, "-g",  "chi",    ffWRITE },
    /* add two more arguments copying from g_angle */ 
    { efXVG, "-ot", "dihtrans", ffOPTWR }, 
    { efXVG, "-oh", "trhisto",  ffOPTWR },
    { efXVG, "-rt", "restrans",  ffOPTWR }, 
    { efXVG, "-cp", "chiprodhisto",  ffOPTWR }  
  };
#define NFILE asize(fnm)
  int     npargs;
  t_pargs *ppa;

  CopyRight(stderr,argv[0]);
  npargs = asize(pa);
  ppa    = add_acf_pargs(&npargs,pa);
  parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,npargs,ppa,asize(desc),desc,asize(bugs),bugs,
                    &oenv);

  /* Handle result from enumerated type */
  sscanf(maxchistr[0],"%d",&maxchi);
  bChi = (maxchi > 0);
  
  log=ffopen(ftp2fn(efLOG,NFILE,fnm),"w");

  if (bRamOmega) {
    bOmega = TRUE;
    bPhi   = TRUE;
    bPsi   = TRUE;
  }
    
  /* set some options */ 
  bDo_rt=(opt2bSet("-rt",NFILE,fnm));
  bDo_oh=(opt2bSet("-oh",NFILE,fnm));
  bDo_ot=(opt2bSet("-ot",NFILE,fnm));
  bDo_jc=(opt2bSet("-jc",NFILE,fnm));
  bCorr=(opt2bSet("-corr",NFILE,fnm));
  if (bCorr) 
    fprintf(stderr,"Will calculate autocorrelation\n");
  
  if (core_frac > 1.0 ) {
    fprintf(stderr, "core_rotamer fraction > 1.0 ; will use 1.0\n"); 
    core_frac=1.0 ; 
  }
  if (core_frac < 0.0 ) {
    fprintf(stderr, "core_rotamer fraction < 0.0 ; will use 0.0\n"); 
    core_frac=0.0 ; 
  }

  if (maxchi > MAXCHI) {
    fprintf(stderr, 
	    "Will only calculate first %d Chi dihedrals in stead of %d.\n",
	    MAXCHI, maxchi);
    maxchi=MAXCHI;
  }
  bSSHisto = ftp2bSet(efDAT,NFILE,fnm);
  nbin = 360/ndeg ; 

  /* Find the chi angles using atoms struct and a list of amino acids */
  get_stx_coordnum(ftp2fn(efSTX,NFILE,fnm),&natoms);
  init_t_atoms(&atoms,natoms,TRUE);
  snew(x,natoms);
  read_stx_conf(ftp2fn(efSTX,NFILE,fnm),title,&atoms,x,NULL,&ePBC,box);
  fprintf(log,"Title: %s\n",title);
  
  gmx_residuetype_init(&rt);
  dlist=mk_dlist(log,&atoms,&nlist,bPhi,bPsi,bChi,bHChi,maxchi,r0,rt);
  fprintf(stderr,"%d residues with dihedrals found\n", nlist);
  
  if (nlist == 0) 
    gmx_fatal(FARGS,"No dihedrals in your structure!\n");
  
  /* Make a linear index for reading all. */
  index=make_chi_ind(nlist,dlist,&ndih);
  isize=4*ndih;
  fprintf(stderr,"%d dihedrals found\n", ndih);

  snew(dih,ndih);

  /* COMPUTE ALL DIHEDRALS! */
  read_ang_dih(ftp2fn(efTRX,NFILE,fnm),FALSE,TRUE,FALSE,bPBC,1,&idum,
	       &nf,&time,isize,index,&trans_frac,&aver_angle,dih,oenv);
  
  dt=(time[nf-1]-time[0])/(nf-1); /* might want this for corr or n. transit*/ 
  if (bCorr) 
  {
	  if (nf < 2)
	  {
		  gmx_fatal(FARGS,"Need at least 2 frames for correlation");
	  }
  }

  /* put angles in -M_PI to M_PI ! and correct phase factor for phi and psi 
  * pass nactdih instead of ndih to low_ana_dih_trans and get_chi_product_traj
  * to prevent accessing off end of arrays when maxchi < 5 or 6. */ 
  nactdih = reset_em_all(nlist,dlist,nf,dih,maxchi);
  
  if (bAll)
    dump_em_all(nlist,dlist,nf,time,dih,maxchi,bPhi,bPsi,bChi,bOmega,bRAD,oenv);
  
  /* Histogramming & J coupling constants & calc of S2 order params */
  histogramming(log,nbin,rt,nf,maxchi,dih,nlist,dlist,index,
		bPhi,bPsi,bOmega,bChi,
		bNormHisto,bSSHisto,ftp2fn(efDAT,NFILE,fnm),bfac_max,&atoms,
		bDo_jc,opt2fn("-jc",NFILE,fnm),oenv);

  /* transitions 
   *
   * added multiplicity */ 

  snew(xity,ndih) ;
  mk_multiplicity_lookup(xity, maxchi, dih, nlist, dlist,ndih); 
 
  strcpy(grpname, "All residues, "); 
  if(bPhi) 
    strcat(grpname, "Phi "); 
  if(bPsi) 
    strcat(grpname, "Psi "); 
  if(bOmega) 
    strcat(grpname, "Omega "); 
  if(bChi){ 
    strcat(grpname, "Chi 1-") ; 
    sprintf(grpname + strlen(grpname), "%i", maxchi); 
  }


  low_ana_dih_trans(bDo_ot, opt2fn("-ot",NFILE,fnm),
		    bDo_oh, opt2fn("-oh",NFILE,fnm),maxchi, 
		    dih, nlist, dlist, nf, nactdih, grpname, xity, 
		    *time,  dt, FALSE, core_frac,oenv) ; 

  /* Order parameters */  
  order_params(log,opt2fn("-o",NFILE,fnm),maxchi,nlist,dlist,
	       ftp2fn_null(efPDB,NFILE,fnm),bfac_init,
	       &atoms,x,ePBC,box,bPhi,bPsi,bChi,oenv);
  
  /* Print ramachandran maps! */
  if (bRama)
    do_rama(nf,nlist,dlist,dih,bViol,bRamOmega,oenv);
  
  if (bShift)
    do_pp2shifts(log,nf,nlist,dlist,dih);

  /* rprint S^2, transitions, and rotamer occupancies to log */ 
  traj_t_ns = 0.001 * (time[nf-1]-time[0]) ; 
  pr_dlist(log,nlist,dlist,traj_t_ns,edPrintST,bPhi,bPsi,bChi,bOmega,maxchi);
  pr_dlist(log,nlist,dlist,traj_t_ns,edPrintRO,bPhi,bPsi,bChi,bOmega,maxchi);  
  ffclose(log);
  /* transitions to xvg */
  if (bDo_rt)
    print_transitions(opt2fn("-rt",NFILE,fnm),maxchi,nlist,dlist,
		      &atoms,x,box,bPhi,bPsi,bChi,traj_t_ns,oenv); 
  
  /* chi_product trajectories (ie one "rotamer number" for each residue) */
  if (bChiProduct && bChi ) {
    snew(chi_lookup,nlist) ;
    for (i=0;i<nlist;i++)
      snew(chi_lookup[i], maxchi) ; 
    mk_chi_lookup(chi_lookup, maxchi, dih, nlist, dlist); 
    
    get_chi_product_traj(dih,nf,nactdih,nlist,
			 maxchi,dlist,time,chi_lookup,xity,
			 FALSE,bNormHisto, core_frac,bAll,
			 opt2fn("-cp",NFILE,fnm),oenv); 

    for (i=0;i<nlist;i++)
      sfree(chi_lookup[i]); 
  }

  /* Correlation comes last because it f***s up the angles */
  if (bCorr)
    do_dihcorr(opt2fn("-corr",NFILE,fnm),nf,ndih,dih,dt,nlist,dlist,time,
	       maxchi,bPhi,bPsi,bChi,bOmega,oenv);
  
  
  do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy");
  do_view(oenv,opt2fn("-jc",NFILE,fnm),"-nxy");
  if (bCorr)
    do_view(oenv,opt2fn("-corr",NFILE,fnm),"-nxy");
    
  gmx_residuetype_destroy(rt);

  thanx(stderr);
    
  return 0;
}
int gmx_dipoles(int argc,char *argv[])
{
    const char *desc[] = {
        "[TT]g_dipoles[tt] computes the total dipole plus fluctuations of a simulation",
        "system. From this you can compute e.g. the dielectric constant for",
        "low-dielectric media.",
        "For molecules with a net charge, the net charge is subtracted at",
        "center of mass of the molecule.[PAR]",
        "The file [TT]Mtot.xvg[tt] contains the total dipole moment of a frame, the",
        "components as well as the norm of the vector.",
        "The file [TT]aver.xvg[tt] contains < |Mu|^2 > and |< Mu >|^2 during the",
        "simulation.",
        "The file [TT]dipdist.xvg[tt] contains the distribution of dipole moments during",
        "the simulation",
        "The value of [TT]-mumax[tt] is used as the highest value in the distribution graph.[PAR]",
        "Furthermore, the dipole autocorrelation function will be computed when",
        "option [TT]-corr[tt] is used. The output file name is given with the [TT]-c[tt]",
        "option.",
        "The correlation functions can be averaged over all molecules",
        "([TT]mol[tt]), plotted per molecule separately ([TT]molsep[tt])",
        "or it can be computed over the total dipole moment of the simulation box",
        "([TT]total[tt]).[PAR]",
        "Option [TT]-g[tt] produces a plot of the distance dependent Kirkwood",
        "G-factor, as well as the average cosine of the angle between the dipoles",
        "as a function of the distance. The plot also includes gOO and hOO",
        "according to Nymand & Linse, J. Chem. Phys. 112 (2000) pp 6386-6395. In the same plot, ",
        "we also include the energy per scale computed by taking the inner product of",
        "the dipoles divided by the distance to the third power.[PAR]",
        "[PAR]",
        "EXAMPLES[PAR]",
        "[TT]g_dipoles -corr mol -P 1 -o dip_sqr -mu 2.273 -mumax 5.0[tt][PAR]",
        "This will calculate the autocorrelation function of the molecular",
        "dipoles using a first order Legendre polynomial of the angle of the",
        "dipole vector and itself a time t later. For this calculation 1001",
        "frames will be used. Further, the dielectric constant will be calculated",
        "using an [GRK]epsilon[grk]RF of infinity (default), temperature of 300 K (default) and",
        "an average dipole moment of the molecule of 2.273 (SPC). For the",
        "distribution function a maximum of 5.0 will be used."
    };
    real mu_max=5, mu_aver=-1,rcmax=0;
    real epsilonRF=0.0, temp=300;
    gmx_bool bAverCorr=FALSE,bMolCorr=FALSE,bPairs=TRUE,bPhi=FALSE;
    const char *corrtype[]={NULL, "none", "mol", "molsep", "total", NULL};
    const char *axtitle="Z";
    int  nslices = 10;      /* nr of slices defined       */
    int  skip=0,nFA=0,nFB=0,ncos=1;
    int  nlevels=20,ndegrees=90;
    output_env_t oenv;
    t_pargs pa[] = {
        { "-mu",       FALSE, etREAL, {&mu_aver},
          "dipole of a single molecule (in Debye)" },
        { "-mumax",    FALSE, etREAL, {&mu_max},
          "max dipole in Debye (for histogram)" },
        { "-epsilonRF",FALSE, etREAL, {&epsilonRF},
          "epsilon of the reaction field used during the simulation, needed for dielectric constant calculation. WARNING: 0.0 means infinity (default)" },
        { "-skip",     FALSE, etINT, {&skip},
          "Skip steps in the output (but not in the computations)" },
        { "-temp",     FALSE, etREAL, {&temp},
          "Average temperature of the simulation (needed for dielectric constant calculation)" },
        { "-corr",     FALSE, etENUM, {corrtype},
          "Correlation function to calculate" },
        { "-pairs",    FALSE, etBOOL, {&bPairs},
          "Calculate |cos [GRK]theta[grk]| between all pairs of molecules. May be slow" },
        { "-ncos",     FALSE, etINT, {&ncos},
          "Must be 1 or 2. Determines whether the <cos> is computed between all molecules in one group, or between molecules in two different groups. This turns on the [TT]-gkr[tt] flag." }, 
        { "-axis",     FALSE, etSTR, {&axtitle}, 
          "Take the normal on the computational box in direction X, Y or Z." },
        { "-sl",       FALSE, etINT, {&nslices},
          "Divide the box in #nr slices." },
        { "-gkratom",  FALSE, etINT, {&nFA},
          "Use the n-th atom of a molecule (starting from 1) to calculate the distance between molecules rather than the center of charge (when 0) in the calculation of distance dependent Kirkwood factors" },
        { "-gkratom2", FALSE, etINT, {&nFB},
          "Same as previous option in case ncos = 2, i.e. dipole interaction between two groups of molecules" },
        { "-rcmax",    FALSE, etREAL, {&rcmax},
          "Maximum distance to use in the dipole orientation distribution (with ncos == 2). If zero, a criterion based on the box length will be used." },
        { "-phi",      FALSE, etBOOL, {&bPhi},
          "Plot the 'torsion angle' defined as the rotation of the two dipole vectors around the distance vector between the two molecules in the [TT].xpm[tt] file from the [TT]-cmap[tt] option. By default the cosine of the angle between the dipoles is plotted." },
        { "-nlevels",  FALSE, etINT, {&nlevels},
          "Number of colors in the cmap output" },
        { "-ndegrees", FALSE, etINT, {&ndegrees},
          "Number of divisions on the [IT]y[it]-axis in the cmap output (for 180 degrees)" }
    };
    int          *gnx;
    int          nFF[2];
    atom_id      **grpindex;
    char         **grpname=NULL;
    gmx_bool     bCorr,bQuad,bGkr,bMU,bSlab;  
    t_filenm fnm[] = {
        { efEDR, "-en", NULL,         ffOPTRD },
        { efTRX, "-f", NULL,           ffREAD },
        { efTPX, NULL, NULL,           ffREAD },
        { efNDX, NULL, NULL,           ffOPTRD },
        { efXVG, "-o",   "Mtot",       ffWRITE },
        { efXVG, "-eps", "epsilon",    ffWRITE },
        { efXVG, "-a",   "aver",       ffWRITE },
        { efXVG, "-d",   "dipdist",    ffWRITE },
        { efXVG, "-c",   "dipcorr",    ffOPTWR },
        { efXVG, "-g",   "gkr",        ffOPTWR },
        { efXVG, "-adip","adip",       ffOPTWR },
        { efXVG, "-dip3d", "dip3d",    ffOPTWR },
        { efXVG, "-cos", "cosaver",    ffOPTWR },
        { efXPM, "-cmap","cmap",       ffOPTWR },
        { efXVG, "-q",   "quadrupole", ffOPTWR },
        { efXVG, "-slab","slab",       ffOPTWR }
    };
#define NFILE asize(fnm)
    int     npargs;
    t_pargs *ppa;
    t_topology *top;
    int     ePBC;
    int     k,natoms;
    matrix  box;
  
    CopyRight(stderr,argv[0]);
    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs,pa);
    parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
                      NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);

    printf("Using %g as mu_max and %g as the dipole moment.\n", 
           mu_max,mu_aver);
    if (epsilonRF == 0.0)
        printf("WARNING: EpsilonRF = 0.0, this really means EpsilonRF = infinity\n");

    bMU   = opt2bSet("-en",NFILE,fnm);
    if (bMU)
        gmx_fatal(FARGS,"Due to new ways of treating molecules in GROMACS the total dipole in the energy file may be incorrect, because molecules can be split over periodic boundary conditions before computing the dipole. Please use your trajectory file.");
    bQuad = opt2bSet("-q",NFILE,fnm);
    bGkr  = opt2bSet("-g",NFILE,fnm);
    if (opt2parg_bSet("-ncos",asize(pa),pa)) {
        if ((ncos != 1) && (ncos != 2)) 
            gmx_fatal(FARGS,"ncos has to be either 1 or 2");
        bGkr = TRUE;
    }
    bSlab = (opt2bSet("-slab",NFILE,fnm) || opt2parg_bSet("-sl",asize(pa),pa) ||
             opt2parg_bSet("-axis",asize(pa),pa));
    if (bMU) {
        bAverCorr = TRUE;
        if (bQuad) {
            printf("WARNING: Can not determine quadrupoles from energy file\n");
            bQuad = FALSE;
        }
        if (bGkr) {
            printf("WARNING: Can not determine Gk(r) from energy file\n");
            bGkr  = FALSE;
            ncos = 1;
        }
        if (mu_aver == -1) 
            printf("WARNING: Can not calculate Gk and gk, since you did\n"
                   "         not enter a valid dipole for the molecules\n");
    }

    snew(top,1);
    ePBC = read_tpx_top(ftp2fn(efTPX,NFILE,fnm),NULL,box,
                        &natoms,NULL,NULL,NULL,top);
  
    snew(gnx,ncos);
    snew(grpname,ncos);
    snew(grpindex,ncos);
    get_index(&top->atoms,ftp2fn_null(efNDX,NFILE,fnm),
              ncos,gnx,grpindex,grpname);
    for(k=0; (k<ncos); k++) 
    {
        dipole_atom2molindex(&gnx[k],grpindex[k],&(top->mols));
        neutralize_mols(gnx[k],grpindex[k],&(top->mols),top->atoms.atom);
    }
    nFF[0] = nFA;
    nFF[1] = nFB;
    do_dip(top,ePBC,det(box),ftp2fn(efTRX,NFILE,fnm),
           opt2fn("-o",NFILE,fnm),opt2fn("-eps",NFILE,fnm),
           opt2fn("-a",NFILE,fnm),opt2fn("-d",NFILE,fnm),
           opt2fn_null("-cos",NFILE,fnm),
           opt2fn_null("-dip3d",NFILE,fnm),opt2fn_null("-adip",NFILE,fnm),
           bPairs,corrtype[0],
           opt2fn("-c",NFILE,fnm),
           bGkr,    opt2fn("-g",NFILE,fnm),
           bPhi,    &nlevels,  ndegrees,
           ncos,
           opt2fn("-cmap",NFILE,fnm),rcmax,
           bQuad,   opt2fn("-q",NFILE,fnm),
           bMU,     opt2fn("-en",NFILE,fnm),
           gnx,grpindex,mu_max,mu_aver,epsilonRF,temp,nFF,skip,
           bSlab,nslices,axtitle,opt2fn("-slab",NFILE,fnm),oenv);
  
    do_view(oenv,opt2fn("-o",NFILE,fnm),"-autoscale xy -nxy");
    do_view(oenv,opt2fn("-eps",NFILE,fnm),"-autoscale xy -nxy");
    do_view(oenv,opt2fn("-a",NFILE,fnm),"-autoscale xy -nxy");
    do_view(oenv,opt2fn("-d",NFILE,fnm),"-autoscale xy");
    do_view(oenv,opt2fn("-c",NFILE,fnm),"-autoscale xy");

    thanx(stderr);
  
    return 0;
}
Exemple #13
0
int gmx_gyrate(int argc,char *argv[])
{
  const char *desc[] = {
    "g_gyrate computes the radius of gyration of a group of atoms",
    "and the radii of gyration about the x, y and z axes,",
    "as a function of time. The atoms are explicitly mass weighted.[PAR]",
    "With the [TT]-nmol[tt] option the radius of gyration will be calculated",
    "for multiple molecules by splitting the analysis group in equally",
    "sized parts.[PAR]",
    "With the option [TT]-nz[tt] 2D radii of gyration in the x-y plane",
    "of slices along the z-axis are calculated."
  };
  static int  nmol=1,nz=0;
  static bool bQ=FALSE,bRot=FALSE,bMOI=FALSE;
  t_pargs pa[] = {
    { "-nmol", FALSE, etINT, {&nmol},
      "The number of molecules to analyze" },
    { "-q", FALSE, etBOOL, {&bQ},
      "Use absolute value of the charge of an atom as weighting factor instead of mass" },
    { "-p", FALSE, etBOOL, {&bRot},
      "Calculate the radii of gyration about the principal axes." },
    { "-moi", FALSE, etBOOL, {&bMOI},
      "Calculate the moments of inertia (defined by the principal axes)." },
    { "-nz", FALSE, etINT, {&nz},
      "Calculate the 2D radii of gyration of # slices along the z-axis" },
  };
  FILE       *out;
  int        status;
  t_topology top;
  int        ePBC;
  rvec       *x,*x_s;
  rvec       xcm,gvec,gvec1;
  matrix     box,trans;
  bool       bACF;
  real       **moi_trans=NULL;
  int        max_moi=0,delta_moi=100;
  rvec       d,d1;         /* eigenvalues of inertia tensor */
  real       t,t0,tm,gyro;
  int        natoms;
  char       *grpname,title[256];
  int        i,j,m,gnx,nam,mol;
  atom_id    *index;
  char *leg[]  = { "Rg", "RgX", "RgY", "RgZ" }; 
  char *legI[] = { "Itot", "I1", "I2", "I3" }; 
#define NLEG asize(leg) 
  t_filenm fnm[] = {
    { efTRX, "-f",   NULL,       ffREAD }, 
    { efTPS, NULL,   NULL,       ffREAD },
    { efNDX, NULL,   NULL,       ffOPTRD },
    { efXVG, NULL,   "gyrate",   ffWRITE }, 
    { efXVG, "-acf", "moi-acf",  ffOPTWR },
  }; 
#define NFILE asize(fnm) 
  int     npargs;
  t_pargs *ppa;
  
  CopyRight(stderr,argv[0]);
  npargs = asize(pa);
  ppa    = add_acf_pargs(&npargs,pa);

  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
		    NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL); 
  bACF = opt2bSet("-acf",NFILE,fnm);
  if (bACF && nmol!=1)
    gmx_fatal(FARGS,"Can only do acf with nmol=1");
  bRot = bRot || bMOI || bACF;
  /*
    if (nz > 0)
    bMOI = TRUE;
  */
  if (bRot) {
    printf("Will rotate system along principal axes\n"); 
    snew(moi_trans,DIM);
  }
  if (bMOI) {
    printf("Will print moments of inertia\n");
    bQ = FALSE;
  }
  if (bQ) 
    printf("Will print radius normalised by charge\n"); 
    
  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,TRUE);
  get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpname);

  if (nmol > gnx || gnx % nmol != 0) {
    gmx_fatal(FARGS,"The number of atoms in the group (%d) is not a multiple of nmol (%d)",gnx,nmol);
  }
  nam = gnx/nmol;

  natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); 
  snew(x_s,natoms); 

  j  = 0; 
  t0 = t;
  if (bQ) 
    out=xvgropen(ftp2fn(efXVG,NFILE,fnm), 
		 "Radius of Charge","Time (ps)","Rg (nm)"); 
  else if (bMOI)
    out=xvgropen(ftp2fn(efXVG,NFILE,fnm), 
		 "Moments of inertia","Time (ps)","I (a.m.u. nm\\S2\\N)"); 
  else 
    out=xvgropen(ftp2fn(efXVG,NFILE,fnm), 
		 "Radius of gyration","Time (ps)","Rg (nm)"); 
  if (bMOI) 
    xvgr_legend(out,NLEG,legI);
  else {
    if (bRot)
      if (bPrintXvgrCodes())
	fprintf(out,"@ subtitle \"Axes are principal component axes\"\n");
    xvgr_legend(out,NLEG,leg);
  }
  do {
    if (nz == 0)
      rm_pbc(&top.idef,ePBC,natoms,box,x,x_s);
    gyro = 0;
    clear_rvec(gvec);
    clear_rvec(d);
    for(mol=0; mol<nmol; mol++) {
      tm    = sub_xcm(nz==0?x_s:x,nam,index+mol*nam,top.atoms.atom,xcm,bQ);
      if (nz == 0)
	gyro += calc_gyro(x_s,nam,index+mol*nam,top.atoms.atom,
			  tm,gvec1,d1,bQ,bRot,bMOI,trans);
      else
	calc_gyro_z(x,box,nam,index+mol*nam,top.atoms.atom,nz,t,out);
      rvec_inc(gvec,gvec1);
      rvec_inc(d,d1);
    }
    if (nmol > 0) {
      gyro /= nmol;
      svmul(1.0/nmol,gvec,gvec);
      svmul(1.0/nmol,d,d);
    }

    if (nz == 0) {
      if (bRot) {
	if (j >= max_moi) {
	  max_moi += delta_moi;
	  for(m=0; (m<DIM); m++)
	    srenew(moi_trans[m],max_moi*DIM);
	}
	for(m=0; (m<DIM); m++)
	  copy_rvec(trans[m],moi_trans[m]+DIM*j);
	fprintf(out,"%10g  %10g  %10g  %10g  %10g\n",
		t,gyro,d[XX],d[YY],d[ZZ]); }
      else {
	fprintf(out,"%10g  %10g  %10g  %10g  %10g\n",
		t,gyro,gvec[XX],gvec[YY],gvec[ZZ]); }
    }
    j++;
  } while(read_next_x(status,&t,natoms,x,box));
  close_trj(status);
  
  fclose(out);

  if (bACF) {
    int mode = eacVector;
  
    do_autocorr(opt2fn("-acf",NFILE,fnm),
		"Moment of inertia vector ACF",
		j,3,moi_trans,(t-t0)/j,mode,FALSE);
    do_view(opt2fn("-acf",NFILE,fnm),"-nxy");
  }
  
  do_view(ftp2fn(efXVG,NFILE,fnm),"-nxy");
  
  thanx(stderr);
  
  return 0;
}