From 5cd759f24e237f2e90e88895e5f0c4d37d421ea4 Mon Sep 17 00:00:00 2001 From: David van der Spoel Date: Tue, 28 Feb 2012 21:53:28 +0100 Subject: [PATCH] Vibration spectra from velocity ACF or Normal modes. The velocity autocorrelation function can be converted into a vibrational spectrum by performing a fourier transform and plotting the amplitude squared as a function of frequency or wavenumber. This has now been automated in g_velacc with the -os flag. Likewise, an option -os has been added to the g_nmeig program to produce a spectrum based on the harmonic approximation. Change-Id: I7e3d669b9108e3a91856ff20688f6216a035bf4a --- src/tools/gmx_nmeig.c | 56 +++++- src/tools/gmx_velacc.c | 390 ++++++++++++++++++++++++----------------- 2 files changed, 278 insertions(+), 168 deletions(-) diff --git a/src/tools/gmx_nmeig.c b/src/tools/gmx_nmeig.c index 13793d1809..febc81f5da 100644 --- a/src/tools/gmx_nmeig.c +++ b/src/tools/gmx_nmeig.c @@ -1,4 +1,4 @@ -/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*- +/* * * This source code is part of * @@ -284,8 +284,8 @@ int gmx_nmeig(int argc,char *argv[]) }; static gmx_bool bM=TRUE,bCons=FALSE; - static int begin=1,end=50; - static real T=298.15; + static int begin=1,end=50,maxspec=4000; + static real T=298.15,width=1; t_pargs pa[] = { { "-m", FALSE, etBOOL, {&bM}, @@ -296,12 +296,16 @@ int gmx_nmeig(int argc,char *argv[]) "First eigenvector to write away" }, { "-last", FALSE, etINT, {&end}, "Last eigenvector to write away" }, + { "-maxspec", FALSE, etINT, {&maxspec}, + "Highest frequency (1/cm) to consider in the spectrum" }, { "-T", FALSE, etREAL, {&T}, "Temperature for computing quantum heat capacity and enthalpy when using normal mode calculations to correct classical simulations" }, { "-constr", FALSE, etBOOL, {&bCons}, "If constraints were used in the simulation but not in the normal mode analysis (this is the recommended way of doing it) you will need to set this for computing the quantum corrections." }, + { "-width", FALSE, etREAL, {&width}, + "Width (sigma) of the gaussian peaks (1/cm) when generating a spectrum" } }; - FILE *out,*qc; + FILE *out,*qc,*spec; int status,trjout; t_topology top; gmx_mtop_t mtop; @@ -321,10 +325,12 @@ int gmx_nmeig(int argc,char *argv[]) real value,omega,nu; real factor_gmx_to_omega2; real factor_omega_to_wavenumber; + real *spectrum=NULL; + real wfac; t_commrec *cr; output_env_t oenv; const char *qcleg[] = { "Heat Capacity cV (J/mol K)", - "Enthalpy H (kJ/mol)" }; + "Enthalpy H (kJ/mol)" }; real * full_hessian = NULL; gmx_sparsematrix_t * sparse_hessian = NULL; @@ -333,9 +339,10 @@ int gmx_nmeig(int argc,char *argv[]) { efTPX, NULL, NULL, ffREAD }, { efXVG, "-of", "eigenfreq", ffWRITE }, { efXVG, "-ol", "eigenval", ffWRITE }, + { efXVG, "-os", "spectrum", ffOPTWR }, { efXVG, "-qc", "quant_corr", ffOPTWR }, { efTRN, "-v", "eigenvec", ffWRITE } - }; + }; #define NFILE asize(fnm) cr = init_par(&argc,&argv); @@ -449,7 +456,7 @@ int gmx_nmeig(int argc,char *argv[]) /* now write the output */ fprintf (stderr,"Writing eigenvalues...\n"); - out=xvgropen(opt2fn("-ol",NFILE,fnm), + out=xvgropen(opt2fn("-ol",NFILE,fnm), "Eigenvalues","Eigenvalue index","Eigenvalue [Gromacs units]", oenv); if (output_env_get_print_xvgr_codes(oenv)) { @@ -462,7 +469,7 @@ int gmx_nmeig(int argc,char *argv[]) for (i=0; i<=(end-begin); i++) fprintf (out,"%6d %15g\n",begin+i,eigenvalues[i]); ffclose(out); - + if (opt2bSet("-qc",NFILE,fnm)) { qc = xvgropen(opt2fn("-qc",NFILE,fnm),"Quantum Corrections","Eigenvector index","",oenv); @@ -482,7 +489,22 @@ int gmx_nmeig(int argc,char *argv[]) else fprintf(out,"@ subtitle \"not mass weighted\"\n"); } - + /* Spectrum ? */ + spec = NULL; + if (opt2bSet("-os",NFILE,fnm) && (maxspec > 0)) + { + snew(spectrum,maxspec); + spec=xvgropen(opt2fn("-os",NFILE,fnm), + "Vibrational spectrum based on harmonic approximation", + "\\f{12}w\\f{4} (cm\\S-1\\N)", + "Intensity [Gromacs units]", + oenv); + for(i=0; (i mols->index[mol]) { - mol++; - if (mol >= mols->nr) - gmx_fatal(FARGS,"Atom index out of range: %d",index[i]+1); - } - for(j=mols->index[mol]; jindex[mol+1]; j++) { - if (i >= nat || index[i] != j) - gmx_fatal(FARGS,"The index group does not consist of whole molecules"); - i++; + int nat,i,nmol,mol,j; + + nat = *n; + i = 0; + nmol = 0; + mol = 0; + while (i < nat) { + while (index[i] > mols->index[mol]) { + mol++; + if (mol >= mols->nr) + gmx_fatal(FARGS,"Atom index out of range: %d",index[i]+1); + } + for(j=mols->index[mol]; jindex[mol+1]; j++) { + if (i >= nat || index[i] != j) + gmx_fatal(FARGS,"The index group does not consist of whole molecules"); + i++; + } + index[nmol++] = mol; } - index[nmol++] = mol; - } - fprintf(stderr,"\nSplit group of %d atoms into %d molecules\n",nat,nmol); + fprintf(stderr,"\nSplit group of %d atoms into %d molecules\n",nat,nmol); - *n = nmol; + *n = nmol; } static void precalc(t_topology top,real normm[]){ - real mtot; - int i,j,k,l; + real mtot; + int i,j,k,l; - for(i=0;i= n_alloc) { - n_alloc+=100; - for(i=0; i= n_alloc) { + n_alloc+=100; + for(i=0; i= 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"); + } + + thanx(stderr); + + return 0; } -- 2.22.0