static void dump_slab_dipoles(const char *fn,int idim,int nslice, rvec slab_dipole[], matrix box,int nframes, const output_env_t oenv) { FILE *fp; char buf[STRLEN]; int i; real mutot; const char *leg_dim[4] = { "\\f{12}m\\f{4}\\sX\\N", "\\f{12}m\\f{4}\\sY\\N", "\\f{12}m\\f{4}\\sZ\\N", "\\f{12}m\\f{4}\\stot\\N" }; sprintf(buf,"Box-%c (nm)",'X'+idim); fp = xvgropen(fn,"Average dipole moment per slab",buf,"\\f{12}m\\f{4} (D)", oenv); xvgr_legend(fp,DIM,leg_dim,oenv); for(i=0; (i<nslice); i++) { mutot = norm(slab_dipole[i])/nframes; fprintf(fp,"%10.3f %10.3f %10.3f %10.3f %10.3f\n", ((i+0.5)*box[idim][idim])/nslice, slab_dipole[i][XX]/nframes, slab_dipole[i][YY]/nframes, slab_dipole[i][ZZ]/nframes, mutot); } ffclose(fp); do_view(oenv,fn,"-autoscale xy -nxy"); }
void view_all(const output_env_t oenv,int nf, t_filenm fnm[]) { int i; for(i=0; i<nf; i++) if ( can_view(fnm[i].ftp) && is_output(&(fnm[i])) && ( ! is_optional(&(fnm[i])) || is_set(&(fnm[i])) ) ) do_view(oenv,fnm[i].fns[0], NULL); }
void view_all(int nf, t_filenm fnm[]) { int i; for(i=0; i<nf; i++) if ( can_view(fnm[i].ftp) && is_output(&(fnm[i])) && ( ! is_optional(&(fnm[i])) || is_set(&(fnm[i])) ) ) do_view(fnm[i].fn, NULL); }
void view_all(const gmx_output_env_t *oenv, int nf, t_filenm fnm[]) { int i; for (i = 0; i < nf; i++) { if (can_view(fnm[i].ftp) && is_output(&(fnm[i])) && ( !is_optional(&(fnm[i])) || is_set(&(fnm[i])) ) ) { do_view(oenv, fnm[i].filenames[0].c_str(), nullptr); } } }
void plot_spectrum(char *noefn,int npair,t_pair pair[],t_sij *spec,real taum) { FILE *fp,*out; int i,j,m; t_rgb rlo = { 1,0,0 },rhi = {1,1,1}; real Sijmax,Sijmin,pow6,pow3,pp3,pp6,ppy,tauc; real *Sij; complex sij; snew(Sij,npair); Sijmax = -1000.0; Sijmin = 1000.0; fp=xvgropen(noefn,"Cross Relaxation","Pair Index","\\8s\\4\\sij\\N"); for(i=0; (i<npair); i++) { tauc = spec[i].tauc; sij.re = -0.4*((taum-tauc)*spec[i].y2.re + tauc*spec[i].rij_6); sij.im = -0.4* (taum-tauc)*spec[i].y2.im; Sij[i]=sij.re; Sijmax=max(Sijmax,sij.re); Sijmin=min(Sijmin,sij.re); fprintf(fp,"%5d %10g\n",i,sij.re); } fclose(fp); fprintf(stderr,"Sijmin: %g, Sijmax: %g\n",Sijmin,Sijmax); out=ffopen("spec.out","w"); pow6 = -1.0/6.0; pow3 = -1.0/3.0; fprintf(out,"%5s %5s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", "at i","at j","S^2","Sig S^2","tauc","Sig tauc", "<rij6>","<rij3>","<ylm>","rij3-6","ylm-rij6"); for(i=0; (i<npair); i++) { if (spec[i].bNOE) { pp6 = pow(spec[i].rij_6,pow6); pp3 = pow(spec[i].rij_3,pow3); if (spec[i].y2.re < 0) ppy = -pow(-spec[i].y2.re,pow6); else ppy = pow(spec[i].y2.re,pow6); fprintf(out,"%5d %5d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n", pair[i].ai,pair[i].aj, spec[i].S2,spec[i].dS2,spec[i].tauc,spec[i].dtauc, pp6,pp3,ppy,pp3-pp6,ppy-pp6); } } fclose(out); sfree(Sij); do_view(noefn,NULL); }
int gmx_rama(int argc,char *argv[]) { const char *desc[] = { "[TT]g_rama[tt] selects the [GRK]phi[grk]/[GRK]psi[grk] dihedral combinations from your topology file", "and computes these as a function of time.", "Using simple Unix tools such as [IT]grep[it] you can select out", "specific residues." }; FILE *out; t_xrama *xr; int j; output_env_t oenv; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPX, NULL, NULL, ffREAD }, { efXVG, NULL, "rama",ffWRITE } }; #define NFILE asize(fnm) parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,0,NULL,asize(desc),desc,0,NULL,&oenv); snew(xr,1); init_rama(oenv,ftp2fn(efTRX,NFILE,fnm),ftp2fn(efTPX,NFILE,fnm),xr,3); out=xvgropen(ftp2fn(efXVG,NFILE,fnm),"Ramachandran Plot","Phi","Psi",oenv); xvgr_line_props(out,0,elNone,ecFrank,oenv); xvgr_view(out,0.2,0.2,0.8,0.8,oenv); xvgr_world(out,-180,-180,180,180,oenv); fprintf(out,"@ xaxis tick on\n@ xaxis tick major 60\n@ xaxis tick minor 30\n"); fprintf(out,"@ yaxis tick on\n@ yaxis tick major 60\n@ yaxis tick minor 30\n"); fprintf(out,"@ s0 symbol 2\n@ s0 symbol size 0.4\n@ s0 symbol fill 1\n"); j=0; do { plot_rama(out,xr); j++; } while (new_data(xr)); fprintf(stderr,"\n"); ffclose(out); do_view(oenv,ftp2fn(efXVG,NFILE,fnm),NULL); thanx(stderr); return 0; }
int gmx_rms(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] compares two structures by computing the root mean square", "deviation (RMSD), the size-independent [GRK]rho[grk] similarity parameter", "([TT]rho[tt]) or the scaled [GRK]rho[grk] ([TT]rhosc[tt]), ", "see Maiorov & Crippen, Proteins [BB]22[bb], 273 (1995).", "This is selected by [TT]-what[tt].[PAR]" "Each structure from a trajectory ([TT]-f[tt]) is compared to a", "reference structure. The reference structure", "is taken from the structure file ([TT]-s[tt]).[PAR]", "With option [TT]-mir[tt] also a comparison with the mirror image of", "the reference structure is calculated.", "This is useful as a reference for 'significant' values, see", "Maiorov & Crippen, Proteins [BB]22[bb], 273 (1995).[PAR]", "Option [TT]-prev[tt] produces the comparison with a previous frame", "the specified number of frames ago.[PAR]", "Option [TT]-m[tt] produces a matrix in [TT].xpm[tt] format of", "comparison values of each structure in the trajectory with respect to", "each other structure. This file can be visualized with for instance", "[TT]xv[tt] and can be converted to postscript with [gmx-xpm2ps].[PAR]", "Option [TT]-fit[tt] controls the least-squares fitting of", "the structures on top of each other: complete fit (rotation and", "translation), translation only, or no fitting at all.[PAR]", "Option [TT]-mw[tt] controls whether mass weighting is done or not.", "If you select the option (default) and ", "supply a valid [TT].tpr[tt] file masses will be taken from there, ", "otherwise the masses will be deduced from the [TT]atommass.dat[tt] file in", "[TT]GMXLIB[tt]. This is fine for proteins, but not", "necessarily for other molecules. A default mass of 12.011 amu (carbon)", "is assigned to unknown atoms. You can check whether this happend by", "turning on the [TT]-debug[tt] flag and inspecting the log file.[PAR]", "With [TT]-f2[tt], the 'other structures' are taken from a second", "trajectory, this generates a comparison matrix of one trajectory", "versus the other.[PAR]", "Option [TT]-bin[tt] does a binary dump of the comparison matrix.[PAR]", "Option [TT]-bm[tt] produces a matrix of average bond angle deviations", "analogously to the [TT]-m[tt] option. Only bonds between atoms in the", "comparison group are considered." }; static gmx_bool bPBC = TRUE, bFitAll = TRUE, bSplit = FALSE; static gmx_bool bDeltaLog = FALSE; static int prev = 0, freq = 1, freq2 = 1, nlevels = 80, avl = 0; static real rmsd_user_max = -1, rmsd_user_min = -1, bond_user_max = -1, bond_user_min = -1, delta_maxy = 0.0; /* strings and things for selecting difference method */ enum { ewSel, ewRMSD, ewRho, ewRhoSc, ewNR }; int ewhat; const char *what[ewNR + 1] = { NULL, "rmsd", "rho", "rhosc", NULL }; const char *whatname[ewNR] = { NULL, "RMSD", "Rho", "Rho sc" }; const char *whatlabel[ewNR] = { NULL, "RMSD (nm)", "Rho", "Rho sc" }; const char *whatxvgname[ewNR] = { NULL, "RMSD", "\\8r\\4", "\\8r\\4\\ssc\\N" }; const char *whatxvglabel[ewNR] = { NULL, "RMSD (nm)", "\\8r\\4", "\\8r\\4\\ssc\\N" }; /* strings and things for fitting methods */ enum { efSel, efFit, efReset, efNone, efNR }; int efit; const char *fit[efNR + 1] = { NULL, "rot+trans", "translation", "none", NULL }; const char *fitgraphlabel[efNR + 1] = { NULL, "lsq fit", "translational fit", "no fit" }; static int nrms = 1; static gmx_bool bMassWeighted = TRUE; t_pargs pa[] = { { "-what", FALSE, etENUM, { what }, "Structural difference measure" }, { "-pbc", FALSE, etBOOL, { &bPBC }, "PBC check" }, { "-fit", FALSE, etENUM, { fit }, "Fit to reference structure" }, { "-prev", FALSE, etINT, { &prev }, "Compare with previous frame" }, { "-split", FALSE, etBOOL, { &bSplit }, "Split graph where time is zero" }, { "-fitall", FALSE, etBOOL, { &bFitAll }, "HIDDENFit all pairs of structures in matrix" }, { "-skip", FALSE, etINT, { &freq }, "Only write every nr-th frame to matrix" }, { "-skip2", FALSE, etINT, { &freq2 }, "Only write every nr-th frame to matrix" }, { "-max", FALSE, etREAL, { &rmsd_user_max }, "Maximum level in comparison matrix" }, { "-min", FALSE, etREAL, { &rmsd_user_min }, "Minimum level in comparison matrix" }, { "-bmax", FALSE, etREAL, { &bond_user_max }, "Maximum level in bond angle matrix" }, { "-bmin", FALSE, etREAL, { &bond_user_min }, "Minimum level in bond angle matrix" }, { "-mw", FALSE, etBOOL, { &bMassWeighted }, "Use mass weighting for superposition" }, { "-nlevels", FALSE, etINT, { &nlevels }, "Number of levels in the matrices" }, { "-ng", FALSE, etINT, { &nrms }, "Number of groups to compute RMS between" }, { "-dlog", FALSE, etBOOL, { &bDeltaLog }, "HIDDENUse a log x-axis in the delta t matrix" }, { "-dmax", FALSE, etREAL, { &delta_maxy }, "HIDDENMaximum level in delta matrix" }, { "-aver", FALSE, etINT, { &avl }, "HIDDENAverage over this distance in the RMSD matrix" } }; int natoms_trx, natoms_trx2, natoms; int i, j, k, m, teller, teller2, tel_mat, tel_mat2; #define NFRAME 5000 int maxframe = NFRAME, maxframe2 = NFRAME; real t, *w_rls, *w_rms, *w_rls_m = NULL, *w_rms_m = NULL; gmx_bool bNorm, bAv, bFreq2, bFile2, bMat, bBond, bDelta, bMirror, bMass; gmx_bool bFit, bReset; t_topology top; int ePBC; t_iatom *iatom = NULL; matrix box; rvec *x, *xp, *xm = NULL, **mat_x = NULL, **mat_x2, *mat_x2_j = NULL, vec1, vec2; t_trxstatus *status; char buf[256], buf2[256]; int ncons = 0; FILE *fp; real rlstot = 0, **rls, **rlsm = NULL, *time, *time2, *rlsnorm = NULL, **rmsd_mat = NULL, **bond_mat = NULL, *axis, *axis2, *del_xaxis, *del_yaxis, rmsd_max, rmsd_min, rmsd_avg, bond_max, bond_min, ang; real **rmsdav_mat = NULL, av_tot, weight, weight_tot; real **delta = NULL, delta_max, delta_scalex = 0, delta_scaley = 0, *delta_tot; int delta_xsize = 0, del_lev = 100, mx, my, abs_my; gmx_bool bA1, bA2, bPrev, bTop, *bInMat = NULL; int ifit, *irms, ibond = 0, *ind_bond1 = NULL, *ind_bond2 = NULL, n_ind_m = 0; atom_id *ind_fit, **ind_rms, *ind_m = NULL, *rev_ind_m = NULL, *ind_rms_m = NULL; char *gn_fit, **gn_rms; t_rgb rlo, rhi; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; t_filenm fnm[] = { { efTPS, NULL, NULL, ffREAD }, { efTRX, "-f", NULL, ffREAD }, { efTRX, "-f2", NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "rmsd", ffWRITE }, { efXVG, "-mir", "rmsdmir", ffOPTWR }, { efXVG, "-a", "avgrp", ffOPTWR }, { efXVG, "-dist", "rmsd-dist", ffOPTWR }, { efXPM, "-m", "rmsd", ffOPTWR }, { efDAT, "-bin", "rmsd", ffOPTWR }, { efXPM, "-bm", "bond", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } /* parse enumerated options: */ ewhat = nenum(what); if (ewhat == ewRho || ewhat == ewRhoSc) { please_cite(stdout, "Maiorov95"); } efit = nenum(fit); bFit = efit == efFit; bReset = efit == efReset; if (bFit) { bReset = TRUE; /* for fit, reset *must* be set */ } else { bFitAll = FALSE; } /* mark active cmdline options */ bMirror = opt2bSet("-mir", NFILE, fnm); /* calc RMSD vs mirror of ref. */ bFile2 = opt2bSet("-f2", NFILE, fnm); bMat = opt2bSet("-m", NFILE, fnm); bBond = opt2bSet("-bm", NFILE, fnm); bDelta = (delta_maxy > 0); /* calculate rmsd vs delta t matrix from * * your RMSD matrix (hidden option */ bNorm = opt2bSet("-a", NFILE, fnm); bFreq2 = opt2parg_bSet("-skip2", asize(pa), pa); if (freq <= 0) { fprintf(stderr, "The number of frames to skip is <= 0. " "Writing out all frames.\n\n"); freq = 1; } if (!bFreq2) { freq2 = freq; } else if (bFile2 && freq2 <= 0) { fprintf(stderr, "The number of frames to skip in second trajectory is <= 0.\n" " Writing out all frames.\n\n"); freq2 = 1; } bPrev = (prev > 0); if (bPrev) { prev = abs(prev); if (freq != 1) { fprintf(stderr, "WARNING: option -skip also applies to -prev\n"); } } if (bFile2 && !bMat && !bBond) { fprintf( stderr, "WARNING: second trajectory (-f2) useless when not calculating matrix (-m/-bm),\n" " will not read from %s\n", opt2fn("-f2", NFILE, fnm)); bFile2 = FALSE; } if (bDelta) { bMat = TRUE; if (bFile2) { fprintf(stderr, "WARNING: second trajectory (-f2) useless when making delta matrix,\n" " will not read from %s\n", opt2fn("-f2", NFILE, fnm)); bFile2 = FALSE; } } bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), buf, &top, &ePBC, &xp, NULL, box, TRUE); snew(w_rls, top.atoms.nr); snew(w_rms, top.atoms.nr); if (!bTop && bBond) { fprintf(stderr, "WARNING: Need a run input file for bond angle matrix,\n" " will not calculate bond angle matrix.\n"); bBond = FALSE; } if (bReset) { fprintf(stderr, "Select group for %s fit\n", bFit ? "least squares" : "translational"); get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &ifit, &ind_fit, &gn_fit); } else { ifit = 0; } if (bReset) { if (bFit && ifit < 3) { gmx_fatal(FARGS, "Need >= 3 points to fit!\n" ); } bMass = FALSE; for (i = 0; i < ifit; i++) { if (bMassWeighted) { w_rls[ind_fit[i]] = top.atoms.atom[ind_fit[i]].m; } else { w_rls[ind_fit[i]] = 1; } bMass = bMass || (top.atoms.atom[ind_fit[i]].m != 0); } if (!bMass) { fprintf(stderr, "All masses in the fit group are 0, using masses of 1\n"); for (i = 0; i < ifit; i++) { w_rls[ind_fit[i]] = 1; } } } if (bMat || bBond) { nrms = 1; } snew(gn_rms, nrms); snew(ind_rms, nrms); snew(irms, nrms); fprintf(stderr, "Select group%s for %s calculation\n", (nrms > 1) ? "s" : "", whatname[ewhat]); get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm), nrms, irms, ind_rms, gn_rms); if (bNorm) { snew(rlsnorm, irms[0]); } snew(rls, nrms); for (j = 0; j < nrms; j++) { snew(rls[j], maxframe); } if (bMirror) { snew(rlsm, nrms); for (j = 0; j < nrms; j++) { snew(rlsm[j], maxframe); } } snew(time, maxframe); for (j = 0; j < nrms; j++) { bMass = FALSE; for (i = 0; i < irms[j]; i++) { if (bMassWeighted) { w_rms[ind_rms[j][i]] = top.atoms.atom[ind_rms[j][i]].m; } else { w_rms[ind_rms[j][i]] = 1.0; } bMass = bMass || (top.atoms.atom[ind_rms[j][i]].m != 0); } if (!bMass) { fprintf(stderr, "All masses in group %d are 0, using masses of 1\n", j); for (i = 0; i < irms[j]; i++) { w_rms[ind_rms[j][i]] = 1; } } } /* Prepare reference frame */ if (bPBC) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr); gmx_rmpbc(gpbc, top.atoms.nr, box, xp); } if (bReset) { reset_x(ifit, ind_fit, top.atoms.nr, NULL, xp, w_rls); } if (bMirror) { /* generate reference structure mirror image: */ snew(xm, top.atoms.nr); for (i = 0; i < top.atoms.nr; i++) { copy_rvec(xp[i], xm[i]); xm[i][XX] = -xm[i][XX]; } } if (ewhat == ewRhoSc) { norm_princ(&top.atoms, ifit, ind_fit, top.atoms.nr, xp); } /* read first frame */ natoms_trx = read_first_x(oenv, &status, opt2fn("-f", NFILE, fnm), &t, &x, box); if (natoms_trx != top.atoms.nr) { fprintf(stderr, "\nWARNING: topology has %d atoms, whereas trajectory has %d\n", top.atoms.nr, natoms_trx); } natoms = min(top.atoms.nr, natoms_trx); if (bMat || bBond || bPrev) { snew(mat_x, NFRAME); if (bPrev) { /* With -prev we use all atoms for simplicity */ n_ind_m = natoms; } else { /* Check which atoms we need (fit/rms) */ snew(bInMat, natoms); for (i = 0; i < ifit; i++) { bInMat[ind_fit[i]] = TRUE; } n_ind_m = ifit; for (i = 0; i < irms[0]; i++) { if (!bInMat[ind_rms[0][i]]) { bInMat[ind_rms[0][i]] = TRUE; n_ind_m++; } } } /* Make an index of needed atoms */ snew(ind_m, n_ind_m); snew(rev_ind_m, natoms); j = 0; for (i = 0; i < natoms; i++) { if (bPrev || bInMat[i]) { ind_m[j] = i; rev_ind_m[i] = j; j++; } } snew(w_rls_m, n_ind_m); snew(ind_rms_m, irms[0]); snew(w_rms_m, n_ind_m); for (i = 0; i < ifit; i++) { w_rls_m[rev_ind_m[ind_fit[i]]] = w_rls[ind_fit[i]]; } for (i = 0; i < irms[0]; i++) { ind_rms_m[i] = rev_ind_m[ind_rms[0][i]]; w_rms_m[ind_rms_m[i]] = w_rms[ind_rms[0][i]]; } sfree(bInMat); } if (bBond) { ncons = 0; for (k = 0; k < F_NRE; k++) { if (IS_CHEMBOND(k)) { iatom = top.idef.il[k].iatoms; ncons += top.idef.il[k].nr/3; } } fprintf(stderr, "Found %d bonds in topology\n", ncons); snew(ind_bond1, ncons); snew(ind_bond2, ncons); ibond = 0; for (k = 0; k < F_NRE; k++) { if (IS_CHEMBOND(k)) { iatom = top.idef.il[k].iatoms; ncons = top.idef.il[k].nr/3; for (i = 0; i < ncons; i++) { bA1 = FALSE; bA2 = FALSE; for (j = 0; j < irms[0]; j++) { if (iatom[3*i+1] == ind_rms[0][j]) { bA1 = TRUE; } if (iatom[3*i+2] == ind_rms[0][j]) { bA2 = TRUE; } } if (bA1 && bA2) { ind_bond1[ibond] = rev_ind_m[iatom[3*i+1]]; ind_bond2[ibond] = rev_ind_m[iatom[3*i+2]]; ibond++; } } } } fprintf(stderr, "Using %d bonds for bond angle matrix\n", ibond); if (ibond == 0) { gmx_fatal(FARGS, "0 bonds found"); } } /* start looping over frames: */ tel_mat = 0; teller = 0; do { if (bPBC) { gmx_rmpbc(gpbc, natoms, box, x); } if (bReset) { reset_x(ifit, ind_fit, natoms, NULL, x, w_rls); } if (ewhat == ewRhoSc) { norm_princ(&top.atoms, ifit, ind_fit, natoms, x); } if (bFit) { /*do the least squares fit to original structure*/ do_fit(natoms, w_rls, xp, x); } if (teller % freq == 0) { /* keep frame for matrix calculation */ if (bMat || bBond || bPrev) { if (tel_mat >= NFRAME) { srenew(mat_x, tel_mat+1); } snew(mat_x[tel_mat], n_ind_m); for (i = 0; i < n_ind_m; i++) { copy_rvec(x[ind_m[i]], mat_x[tel_mat][i]); } } tel_mat++; } /*calculate energy of root_least_squares*/ if (bPrev) { j = tel_mat-prev-1; if (j < 0) { j = 0; } for (i = 0; i < n_ind_m; i++) { copy_rvec(mat_x[j][i], xp[ind_m[i]]); } if (bReset) { reset_x(ifit, ind_fit, natoms, NULL, xp, w_rls); } if (bFit) { do_fit(natoms, w_rls, x, xp); } } for (j = 0; (j < nrms); j++) { rls[j][teller] = calc_similar_ind(ewhat != ewRMSD, irms[j], ind_rms[j], w_rms, x, xp); } if (bNorm) { for (j = 0; (j < irms[0]); j++) { rlsnorm[j] += calc_similar_ind(ewhat != ewRMSD, 1, &(ind_rms[0][j]), w_rms, x, xp); } } if (bMirror) { if (bFit) { /*do the least squares fit to mirror of original structure*/ do_fit(natoms, w_rls, xm, x); } for (j = 0; j < nrms; j++) { rlsm[j][teller] = calc_similar_ind(ewhat != ewRMSD, irms[j], ind_rms[j], w_rms, x, xm); } } time[teller] = output_env_conv_time(oenv, t); teller++; if (teller >= maxframe) { maxframe += NFRAME; srenew(time, maxframe); for (j = 0; (j < nrms); j++) { srenew(rls[j], maxframe); } if (bMirror) { for (j = 0; (j < nrms); j++) { srenew(rlsm[j], maxframe); } } } } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); if (bFile2) { snew(time2, maxframe2); fprintf(stderr, "\nWill read second trajectory file\n"); snew(mat_x2, NFRAME); natoms_trx2 = read_first_x(oenv, &status, opt2fn("-f2", NFILE, fnm), &t, &x, box); if (natoms_trx2 != natoms_trx) { gmx_fatal(FARGS, "Second trajectory (%d atoms) does not match the first one" " (%d atoms)", natoms_trx2, natoms_trx); } tel_mat2 = 0; teller2 = 0; do { if (bPBC) { gmx_rmpbc(gpbc, natoms, box, x); } if (bReset) { reset_x(ifit, ind_fit, natoms, NULL, x, w_rls); } if (ewhat == ewRhoSc) { norm_princ(&top.atoms, ifit, ind_fit, natoms, x); } if (bFit) { /*do the least squares fit to original structure*/ do_fit(natoms, w_rls, xp, x); } if (teller2 % freq2 == 0) { /* keep frame for matrix calculation */ if (bMat) { if (tel_mat2 >= NFRAME) { srenew(mat_x2, tel_mat2+1); } snew(mat_x2[tel_mat2], n_ind_m); for (i = 0; i < n_ind_m; i++) { copy_rvec(x[ind_m[i]], mat_x2[tel_mat2][i]); } } tel_mat2++; } time2[teller2] = output_env_conv_time(oenv, t); teller2++; if (teller2 >= maxframe2) { maxframe2 += NFRAME; srenew(time2, maxframe2); } } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); } else { mat_x2 = mat_x; time2 = time; tel_mat2 = tel_mat; freq2 = freq; } gmx_rmpbc_done(gpbc); if (bMat || bBond) { /* calculate RMS matrix */ fprintf(stderr, "\n"); if (bMat) { fprintf(stderr, "Building %s matrix, %dx%d elements\n", whatname[ewhat], tel_mat, tel_mat2); snew(rmsd_mat, tel_mat); } if (bBond) { fprintf(stderr, "Building bond angle matrix, %dx%d elements\n", tel_mat, tel_mat2); snew(bond_mat, tel_mat); } snew(axis, tel_mat); snew(axis2, tel_mat2); rmsd_max = 0; if (bFile2) { rmsd_min = 1e10; } else { rmsd_min = 0; } rmsd_avg = 0; bond_max = 0; bond_min = 1e10; for (j = 0; j < tel_mat2; j++) { axis2[j] = time2[freq2*j]; } if (bDelta) { if (bDeltaLog) { delta_scalex = 8.0/log(2.0); delta_xsize = (int)(log(tel_mat/2)*delta_scalex+0.5)+1; } else { delta_xsize = tel_mat/2; } delta_scaley = 1.0/delta_maxy; snew(delta, delta_xsize); for (j = 0; j < delta_xsize; j++) { snew(delta[j], del_lev+1); } if (avl > 0) { snew(rmsdav_mat, tel_mat); for (j = 0; j < tel_mat; j++) { snew(rmsdav_mat[j], tel_mat); } } } if (bFitAll) { snew(mat_x2_j, natoms); } for (i = 0; i < tel_mat; i++) { axis[i] = time[freq*i]; fprintf(stderr, "\r element %5d; time %5.2f ", i, axis[i]); if (bMat) { snew(rmsd_mat[i], tel_mat2); } if (bBond) { snew(bond_mat[i], tel_mat2); } for (j = 0; j < tel_mat2; j++) { if (bFitAll) { for (k = 0; k < n_ind_m; k++) { copy_rvec(mat_x2[j][k], mat_x2_j[k]); } do_fit(n_ind_m, w_rls_m, mat_x[i], mat_x2_j); } else { mat_x2_j = mat_x2[j]; } if (bMat) { if (bFile2 || (i < j)) { rmsd_mat[i][j] = calc_similar_ind(ewhat != ewRMSD, irms[0], ind_rms_m, w_rms_m, mat_x[i], mat_x2_j); if (rmsd_mat[i][j] > rmsd_max) { rmsd_max = rmsd_mat[i][j]; } if (rmsd_mat[i][j] < rmsd_min) { rmsd_min = rmsd_mat[i][j]; } rmsd_avg += rmsd_mat[i][j]; } else { rmsd_mat[i][j] = rmsd_mat[j][i]; } } if (bBond) { if (bFile2 || (i <= j)) { ang = 0.0; for (m = 0; m < ibond; m++) { rvec_sub(mat_x[i][ind_bond1[m]], mat_x[i][ind_bond2[m]], vec1); rvec_sub(mat_x2_j[ind_bond1[m]], mat_x2_j[ind_bond2[m]], vec2); ang += acos(cos_angle(vec1, vec2)); } bond_mat[i][j] = ang*180.0/(M_PI*ibond); if (bond_mat[i][j] > bond_max) { bond_max = bond_mat[i][j]; } if (bond_mat[i][j] < bond_min) { bond_min = bond_mat[i][j]; } } else { bond_mat[i][j] = bond_mat[j][i]; } } } } if (bFile2) { rmsd_avg /= tel_mat*tel_mat2; } else { rmsd_avg /= tel_mat*(tel_mat - 1)/2; } if (bMat && (avl > 0)) { rmsd_max = 0.0; rmsd_min = 0.0; rmsd_avg = 0.0; for (j = 0; j < tel_mat-1; j++) { for (i = j+1; i < tel_mat; i++) { av_tot = 0; weight_tot = 0; for (my = -avl; my <= avl; my++) { if ((j+my >= 0) && (j+my < tel_mat)) { abs_my = abs(my); for (mx = -avl; mx <= avl; mx++) { if ((i+mx >= 0) && (i+mx < tel_mat)) { weight = (real)(avl+1-max(abs(mx), abs_my)); av_tot += weight*rmsd_mat[i+mx][j+my]; weight_tot += weight; } } } } rmsdav_mat[i][j] = av_tot/weight_tot; rmsdav_mat[j][i] = rmsdav_mat[i][j]; if (rmsdav_mat[i][j] > rmsd_max) { rmsd_max = rmsdav_mat[i][j]; } } } rmsd_mat = rmsdav_mat; } if (bMat) { fprintf(stderr, "\n%s: Min %f, Max %f, Avg %f\n", whatname[ewhat], rmsd_min, rmsd_max, rmsd_avg); rlo.r = 1; rlo.g = 1; rlo.b = 1; rhi.r = 0; rhi.g = 0; rhi.b = 0; if (rmsd_user_max != -1) { rmsd_max = rmsd_user_max; } if (rmsd_user_min != -1) { rmsd_min = rmsd_user_min; } if ((rmsd_user_max != -1) || (rmsd_user_min != -1)) { fprintf(stderr, "Min and Max value set to resp. %f and %f\n", rmsd_min, rmsd_max); } sprintf(buf, "%s %s matrix", gn_rms[0], whatname[ewhat]); write_xpm(opt2FILE("-m", NFILE, fnm, "w"), 0, buf, whatlabel[ewhat], output_env_get_time_label(oenv), output_env_get_time_label(oenv), tel_mat, tel_mat2, axis, axis2, rmsd_mat, rmsd_min, rmsd_max, rlo, rhi, &nlevels); /* Print the distribution of RMSD values */ if (opt2bSet("-dist", NFILE, fnm)) { low_rmsd_dist(opt2fn("-dist", NFILE, fnm), rmsd_max, tel_mat, rmsd_mat, oenv); } if (bDelta) { snew(delta_tot, delta_xsize); for (j = 0; j < tel_mat-1; j++) { for (i = j+1; i < tel_mat; i++) { mx = i-j; if (mx < tel_mat/2) { if (bDeltaLog) { mx = (int)(log(mx)*delta_scalex+0.5); } my = (int)(rmsd_mat[i][j]*delta_scaley*del_lev+0.5); delta_tot[mx] += 1.0; if ((rmsd_mat[i][j] >= 0) && (rmsd_mat[i][j] <= delta_maxy)) { delta[mx][my] += 1.0; } } } } delta_max = 0; for (i = 0; i < delta_xsize; i++) { if (delta_tot[i] > 0.0) { delta_tot[i] = 1.0/delta_tot[i]; for (j = 0; j <= del_lev; j++) { delta[i][j] *= delta_tot[i]; if (delta[i][j] > delta_max) { delta_max = delta[i][j]; } } } } fprintf(stderr, "Maximum in delta matrix: %f\n", delta_max); snew(del_xaxis, delta_xsize); snew(del_yaxis, del_lev+1); for (i = 0; i < delta_xsize; i++) { del_xaxis[i] = axis[i]-axis[0]; } for (i = 0; i < del_lev+1; i++) { del_yaxis[i] = delta_maxy*i/del_lev; } sprintf(buf, "%s %s vs. delta t", gn_rms[0], whatname[ewhat]); fp = gmx_ffopen("delta.xpm", "w"); write_xpm(fp, 0, buf, "density", output_env_get_time_label(oenv), whatlabel[ewhat], delta_xsize, del_lev+1, del_xaxis, del_yaxis, delta, 0.0, delta_max, rlo, rhi, &nlevels); gmx_ffclose(fp); } if (opt2bSet("-bin", NFILE, fnm)) { /* NB: File must be binary if we use fwrite */ fp = ftp2FILE(efDAT, NFILE, fnm, "wb"); for (i = 0; i < tel_mat; i++) { if (fwrite(rmsd_mat[i], sizeof(**rmsd_mat), tel_mat2, fp) != tel_mat2) { gmx_fatal(FARGS, "Error writing to output file"); } } gmx_ffclose(fp); } } if (bBond) { fprintf(stderr, "\nMin. angle: %f, Max. angle: %f\n", bond_min, bond_max); if (bond_user_max != -1) { bond_max = bond_user_max; } if (bond_user_min != -1) { bond_min = bond_user_min; } if ((bond_user_max != -1) || (bond_user_min != -1)) { fprintf(stderr, "Bond angle Min and Max set to:\n" "Min. angle: %f, Max. angle: %f\n", bond_min, bond_max); } rlo.r = 1; rlo.g = 1; rlo.b = 1; rhi.r = 0; rhi.g = 0; rhi.b = 0; sprintf(buf, "%s av. bond angle deviation", gn_rms[0]); write_xpm(opt2FILE("-bm", NFILE, fnm, "w"), 0, buf, "degrees", output_env_get_time_label(oenv), output_env_get_time_label(oenv), tel_mat, tel_mat2, axis, axis2, bond_mat, bond_min, bond_max, rlo, rhi, &nlevels); } } bAv = opt2bSet("-a", NFILE, fnm); /* Write the RMSD's to file */ if (!bPrev) { sprintf(buf, "%s", whatxvgname[ewhat]); } else { sprintf(buf, "%s with frame %g %s ago", whatxvgname[ewhat], time[prev*freq]-time[0], output_env_get_time_label(oenv)); } fp = xvgropen(opt2fn("-o", NFILE, fnm), buf, output_env_get_xvgr_tlabel(oenv), whatxvglabel[ewhat], oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"%s%s after %s%s%s\"\n", (nrms == 1) ? "" : "of ", gn_rms[0], fitgraphlabel[efit], bFit ? " to " : "", bFit ? gn_fit : ""); } if (nrms != 1) { xvgr_legend(fp, nrms, (const char**)gn_rms, oenv); } for (i = 0; (i < teller); i++) { if (bSplit && i > 0 && abs(time[bPrev ? freq*i : i]/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(fp, "&\n"); } fprintf(fp, "%12.7f", time[bPrev ? freq*i : i]); for (j = 0; (j < nrms); j++) { fprintf(fp, " %12.7f", rls[j][i]); if (bAv) { rlstot += rls[j][i]; } } fprintf(fp, "\n"); } gmx_ffclose(fp); if (bMirror) { /* Write the mirror RMSD's to file */ sprintf(buf, "%s with Mirror", whatxvgname[ewhat]); sprintf(buf2, "Mirror %s", whatxvglabel[ewhat]); fp = xvgropen(opt2fn("-mir", NFILE, fnm), buf, output_env_get_xvgr_tlabel(oenv), buf2, oenv); if (nrms == 1) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"of %s after lsq fit to mirror of %s\"\n", gn_rms[0], gn_fit); } } else { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"after lsq fit to mirror %s\"\n", gn_fit); } xvgr_legend(fp, nrms, (const char**)gn_rms, oenv); } for (i = 0; (i < teller); i++) { if (bSplit && i > 0 && abs(time[i]) < 1e-5) { fprintf(fp, "&\n"); } fprintf(fp, "%12.7f", time[i]); for (j = 0; (j < nrms); j++) { fprintf(fp, " %12.7f", rlsm[j][i]); } fprintf(fp, "\n"); } gmx_ffclose(fp); } if (bAv) { sprintf(buf, "Average %s", whatxvgname[ewhat]); sprintf(buf2, "Average %s", whatxvglabel[ewhat]); fp = xvgropen(opt2fn("-a", NFILE, fnm), buf, "Residue", buf2, oenv); for (j = 0; (j < nrms); j++) { fprintf(fp, "%10d %10g\n", j, rlstot/teller); } gmx_ffclose(fp); } if (bNorm) { fp = xvgropen("aver.xvg", gn_rms[0], "Residue", whatxvglabel[ewhat], oenv); for (j = 0; (j < irms[0]); j++) { fprintf(fp, "%10d %10g\n", j, rlsnorm[j]/teller); } gmx_ffclose(fp); } do_view(oenv, opt2fn_null("-a", NFILE, fnm), "-graphtype bar"); do_view(oenv, opt2fn("-o", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-mir", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-m", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-bm", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-dist", NFILE, fnm), NULL); return 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; }
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_rmsf(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the root mean square fluctuation (RMSF, i.e. standard ", "deviation) of atomic positions in the trajectory (supplied with [TT]-f[tt])", "after (optionally) fitting to a reference frame (supplied with [TT]-s[tt]).[PAR]", "With option [TT]-oq[tt] the RMSF values are converted to B-factor", "values, which are written to a [REF].pdb[ref] file with the coordinates, of the", "structure file, or of a [REF].pdb[ref] file when [TT]-q[tt] is specified.", "Option [TT]-ox[tt] writes the B-factors to a file with the average", "coordinates.[PAR]", "With the option [TT]-od[tt] the root mean square deviation with", "respect to the reference structure is calculated.[PAR]", "With the option [TT]-aniso[tt], [THISMODULE] will compute anisotropic", "temperature factors and then it will also output average coordinates", "and a [REF].pdb[ref] file with ANISOU records (corresonding to the [TT]-oq[tt]", "or [TT]-ox[tt] option). Please note that the U values", "are orientation-dependent, so before comparison with experimental data", "you should verify that you fit to the experimental coordinates.[PAR]", "When a [REF].pdb[ref] input file is passed to the program and the [TT]-aniso[tt]", "flag is set", "a correlation plot of the Uij will be created, if any anisotropic", "temperature factors are present in the [REF].pdb[ref] file.[PAR]", "With option [TT]-dir[tt] the average MSF (3x3) matrix is diagonalized.", "This shows the directions in which the atoms fluctuate the most and", "the least." }; static gmx_bool bRes = FALSE, bAniso = FALSE, bFit = TRUE; t_pargs pargs[] = { { "-res", FALSE, etBOOL, {&bRes}, "Calculate averages for each residue" }, { "-aniso", FALSE, etBOOL, {&bAniso}, "Compute anisotropic termperature factors" }, { "-fit", FALSE, etBOOL, {&bFit}, "Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." } }; int natom; int i, m, teller = 0; real t, *w_rls; t_topology top; int ePBC; t_atoms *pdbatoms, *refatoms; matrix box, pdbbox; rvec *x, *pdbx, *xref; t_trxstatus *status; const char *label; FILE *fp; /* the graphics file */ const char *devfn, *dirfn; int resind; gmx_bool bReadPDB; int *index; int isize; char *grpnames; real bfac, pdb_bfac, *Uaver; double **U, *xav; int aid; rvec *rmsd_x = nullptr; double *rmsf, invcount, totmass; int d; real count = 0; rvec xcm; gmx_rmpbc_t gpbc = nullptr; gmx_output_env_t *oenv; const char *leg[2] = { "MD", "X-Ray" }; t_filenm fnm[] = { { efTRX, "-f", nullptr, ffREAD }, { efTPS, nullptr, nullptr, ffREAD }, { efNDX, nullptr, nullptr, ffOPTRD }, { efPDB, "-q", nullptr, ffOPTRD }, { efPDB, "-oq", "bfac", ffOPTWR }, { efPDB, "-ox", "xaver", ffOPTWR }, { efXVG, "-o", "rmsf", ffWRITE }, { efXVG, "-od", "rmsdev", ffOPTWR }, { efXVG, "-oc", "correl", ffOPTWR }, { efLOG, "-dir", "rmsf", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pargs), pargs, asize(desc), desc, 0, nullptr, &oenv)) { return 0; } bReadPDB = ftp2bSet(efPDB, NFILE, fnm); devfn = opt2fn_null("-od", NFILE, fnm); dirfn = opt2fn_null("-dir", NFILE, fnm); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xref, nullptr, box, TRUE); const char *title = *top.name; snew(w_rls, top.atoms.nr); fprintf(stderr, "Select group(s) for root mean square calculation\n"); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpnames); /* Set the weight */ for (i = 0; i < isize; i++) { w_rls[index[i]] = top.atoms.atom[index[i]].m; } /* Malloc the rmsf arrays */ snew(xav, isize*DIM); snew(U, isize); for (i = 0; i < isize; i++) { snew(U[i], DIM*DIM); } snew(rmsf, isize); if (devfn) { snew(rmsd_x, isize); } if (bReadPDB) { t_topology *top_pdb; snew(top_pdb, 1); /* Read coordinates twice */ read_tps_conf(opt2fn("-q", NFILE, fnm), top_pdb, nullptr, nullptr, nullptr, pdbbox, FALSE); snew(pdbatoms, 1); *pdbatoms = top_pdb->atoms; read_tps_conf(opt2fn("-q", NFILE, fnm), top_pdb, nullptr, &pdbx, nullptr, pdbbox, FALSE); /* TODO Should this assert that top_pdb->atoms.nr == top.atoms.nr? * See discussion at https://gerrit.gromacs.org/#/c/6430/1 */ title = *top_pdb->name; snew(refatoms, 1); *refatoms = top_pdb->atoms; sfree(top_pdb); } else { pdbatoms = &top.atoms; refatoms = &top.atoms; pdbx = xref; snew(pdbatoms->pdbinfo, pdbatoms->nr); pdbatoms->havePdbInfo = TRUE; copy_mat(box, pdbbox); } if (bFit) { sub_xcm(xref, isize, index, top.atoms.atom, xcm, FALSE); } natom = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); if (bFit) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, natom); } /* Now read the trj again to compute fluctuations */ teller = 0; do { if (bFit) { /* Remove periodic boundary */ gmx_rmpbc(gpbc, natom, box, x); /* Set center of mass to zero */ sub_xcm(x, isize, index, top.atoms.atom, xcm, FALSE); /* Fit to reference structure */ do_fit(natom, w_rls, xref, x); } /* Calculate Anisotropic U Tensor */ for (i = 0; i < isize; i++) { aid = index[i]; for (d = 0; d < DIM; d++) { xav[i*DIM + d] += x[aid][d]; for (m = 0; m < DIM; m++) { U[i][d*DIM + m] += x[aid][d]*x[aid][m]; } } } if (devfn) { /* Calculate RMS Deviation */ for (i = 0; (i < isize); i++) { aid = index[i]; for (d = 0; (d < DIM); d++) { rmsd_x[i][d] += gmx::square(x[aid][d]-xref[aid][d]); } } } count += 1.0; teller++; } while (read_next_x(oenv, status, &t, x, box)); close_trx(status); if (bFit) { gmx_rmpbc_done(gpbc); } invcount = 1.0/count; snew(Uaver, DIM*DIM); totmass = 0; for (i = 0; i < isize; i++) { for (d = 0; d < DIM; d++) { xav[i*DIM + d] *= invcount; } for (d = 0; d < DIM; d++) { for (m = 0; m < DIM; m++) { U[i][d*DIM + m] = U[i][d*DIM + m]*invcount - xav[i*DIM + d]*xav[i*DIM + m]; Uaver[3*d+m] += top.atoms.atom[index[i]].m*U[i][d*DIM + m]; } } totmass += top.atoms.atom[index[i]].m; } for (d = 0; d < DIM*DIM; d++) { Uaver[d] /= totmass; } if (bRes) { for (d = 0; d < DIM*DIM; d++) { average_residues(nullptr, U, d, isize, index, w_rls, &top.atoms); } } if (bAniso) { for (i = 0; i < isize; i++) { aid = index[i]; pdbatoms->pdbinfo[aid].bAnisotropic = TRUE; pdbatoms->pdbinfo[aid].uij[U11] = static_cast<int>(1e6*U[i][XX*DIM + XX]); pdbatoms->pdbinfo[aid].uij[U22] = static_cast<int>(1e6*U[i][YY*DIM + YY]); pdbatoms->pdbinfo[aid].uij[U33] = static_cast<int>(1e6*U[i][ZZ*DIM + ZZ]); pdbatoms->pdbinfo[aid].uij[U12] = static_cast<int>(1e6*U[i][XX*DIM + YY]); pdbatoms->pdbinfo[aid].uij[U13] = static_cast<int>(1e6*U[i][XX*DIM + ZZ]); pdbatoms->pdbinfo[aid].uij[U23] = static_cast<int>(1e6*U[i][YY*DIM + ZZ]); } } if (bRes) { label = "Residue"; } else { label = "Atom"; } for (i = 0; i < isize; i++) { rmsf[i] = U[i][XX*DIM + XX] + U[i][YY*DIM + YY] + U[i][ZZ*DIM + ZZ]; } if (dirfn) { fprintf(stdout, "\n"); print_dir(stdout, Uaver); fp = gmx_ffopen(dirfn, "w"); print_dir(fp, Uaver); gmx_ffclose(fp); } for (i = 0; i < isize; i++) { sfree(U[i]); } sfree(U); /* Write RMSF output */ if (bReadPDB) { bfac = 8.0*M_PI*M_PI/3.0*100; fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "B-Factors", label, "(A\\b\\S\\So\\N\\S2\\N)", oenv); xvgr_legend(fp, 2, leg, oenv); for (i = 0; (i < isize); i++) { if (!bRes || i+1 == isize || top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind) { resind = top.atoms.atom[index[i]].resind; pdb_bfac = find_pdb_bfac(pdbatoms, &top.atoms.resinfo[resind], *(top.atoms.atomname[index[i]])); fprintf(fp, "%5d %10.5f %10.5f\n", bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, rmsf[i]*bfac, pdb_bfac); } } xvgrclose(fp); } else { fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "RMS fluctuation", label, "(nm)", oenv); for (i = 0; i < isize; i++) { if (!bRes || i+1 == isize || top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind) { fprintf(fp, "%5d %8.4f\n", bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, std::sqrt(rmsf[i])); } } xvgrclose(fp); } for (i = 0; i < isize; i++) { pdbatoms->pdbinfo[index[i]].bfac = 800*M_PI*M_PI/3.0*rmsf[i]; } if (devfn) { for (i = 0; i < isize; i++) { rmsf[i] = (rmsd_x[i][XX]+rmsd_x[i][YY]+rmsd_x[i][ZZ])/count; } if (bRes) { average_residues(rmsf, nullptr, 0, isize, index, w_rls, &top.atoms); } /* Write RMSD output */ fp = xvgropen(devfn, "RMS Deviation", label, "(nm)", oenv); for (i = 0; i < isize; i++) { if (!bRes || i+1 == isize || top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind) { fprintf(fp, "%5d %8.4f\n", bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, std::sqrt(rmsf[i])); } } xvgrclose(fp); } if (opt2bSet("-oq", NFILE, fnm)) { /* Write a .pdb file with B-factors and optionally anisou records */ for (i = 0; i < isize; i++) { rvec_inc(pdbx[index[i]], xcm); } write_sto_conf_indexed(opt2fn("-oq", NFILE, fnm), title, pdbatoms, pdbx, nullptr, ePBC, pdbbox, isize, index); } if (opt2bSet("-ox", NFILE, fnm)) { rvec *bFactorX; snew(bFactorX, top.atoms.nr); for (i = 0; i < isize; i++) { for (d = 0; d < DIM; d++) { bFactorX[index[i]][d] = xcm[d] + xav[i*DIM + d]; } } /* Write a .pdb file with B-factors and optionally anisou records */ write_sto_conf_indexed(opt2fn("-ox", NFILE, fnm), title, pdbatoms, bFactorX, nullptr, ePBC, pdbbox, isize, index); sfree(bFactorX); } if (bAniso) { correlate_aniso(opt2fn("-oc", NFILE, fnm), refatoms, pdbatoms, oenv); do_view(oenv, opt2fn("-oc", NFILE, fnm), "-nxy"); } do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); if (devfn) { do_view(oenv, opt2fn("-od", NFILE, fnm), "-nxy"); } 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; }
int gmx_densmap(int argc,char *argv[]) { const char *desc[] = { "[TT]g_densmap[tt] computes 2D number-density maps.", "It can make planar and axial-radial density maps.", "The output [TT].xpm[tt] file can be visualized with for instance xv", "and can be converted to postscript with [TT]xpm2ps[tt].", "Optionally, output can be in text form to a [TT].dat[tt] file with [TT]-od[tt], instead of the usual [TT].xpm[tt] file with [TT]-o[tt].", "[PAR]", "The default analysis is a 2-D number-density map for a selected", "group of atoms in the x-y plane.", "The averaging direction can be changed with the option [TT]-aver[tt].", "When [TT]-xmin[tt] and/or [TT]-xmax[tt] are set only atoms that are", "within the limit(s) in the averaging direction are taken into account.", "The grid spacing is set with the option [TT]-bin[tt].", "When [TT]-n1[tt] or [TT]-n2[tt] is non-zero, the grid", "size is set by this option.", "Box size fluctuations are properly taken into account.", "[PAR]", "When options [TT]-amax[tt] and [TT]-rmax[tt] are set, an axial-radial", "number-density map is made. Three groups should be supplied, the centers", "of mass of the first two groups define the axis, the third defines the", "analysis group. The axial direction goes from -amax to +amax, where", "the center is defined as the midpoint between the centers of mass and", "the positive direction goes from the first to the second center of mass.", "The radial direction goes from 0 to rmax or from -rmax to +rmax", "when the [TT]-mirror[tt] option has been set.", "[PAR]", "The normalization of the output is set with the [TT]-unit[tt] option.", "The default produces a true number density. Unit [TT]nm-2[tt] leaves out", "the normalization for the averaging or the angular direction.", "Option [TT]count[tt] produces the count for each grid cell.", "When you do not want the scale in the output to go", "from zero to the maximum density, you can set the maximum", "with the option [TT]-dmax[tt]." }; static int n1=0,n2=0; static real xmin=-1,xmax=-1,bin=0.02,dmin=0,dmax=0,amax=0,rmax=0; static gmx_bool bMirror=FALSE, bSums=FALSE; static const char *eaver[]= { NULL, "z", "y", "x", NULL }; static const char *eunit[]= { NULL, "nm-3", "nm-2", "count", NULL }; t_pargs pa[] = { { "-bin", FALSE, etREAL, {&bin}, "Grid size (nm)" }, { "-aver", FALSE, etENUM, {eaver}, "The direction to average over" }, { "-xmin", FALSE, etREAL, {&xmin}, "Minimum coordinate for averaging" }, { "-xmax", FALSE, etREAL, {&xmax}, "Maximum coordinate for averaging" }, { "-n1", FALSE, etINT, {&n1}, "Number of grid cells in the first direction" }, { "-n2", FALSE, etINT, {&n2}, "Number of grid cells in the second direction" }, { "-amax", FALSE, etREAL, {&amax}, "Maximum axial distance from the center" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum radial distance" }, { "-mirror", FALSE, etBOOL, {&bMirror}, "Add the mirror image below the axial axis" }, { "-sums", FALSE, etBOOL, {&bSums}, "Print density sums (1D map) to stdout" }, { "-unit", FALSE, etENUM, {eunit}, "Unit for the output" }, { "-dmin", FALSE, etREAL, {&dmin}, "Minimum density in output" }, { "-dmax", FALSE, etREAL, {&dmax}, "Maximum density in output (0 means calculate it)" }, }; gmx_bool bXmin,bXmax,bRadial; FILE *fp; t_trxstatus *status; t_topology top; int ePBC=-1; rvec *x,xcom[2],direction,center,dx; matrix box; real t,m,mtot; t_pbc pbc; int cav=0,c1=0,c2=0,natoms; char **grpname,title[256],buf[STRLEN]; const char *unit; int i,j,k,l,ngrps,anagrp,*gnx=NULL,nindex,nradial=0,nfr,nmpower; atom_id **ind=NULL,*index; real **grid,maxgrid,m1,m2,box1,box2,*tickx,*tickz,invcellvol; real invspa=0,invspz=0,axial,r,vol_old,vol,rowsum; int nlev=51; t_rgb rlo= {1,1,1}, rhi= {0,0,0}; output_env_t oenv; const char *label[]= { "x (nm)", "y (nm)", "z (nm)" }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-od", "densmap", ffOPTWR }, { efXPM, "-o", "densmap", ffWRITE } }; #define NFILE asize(fnm) int npargs; CopyRight(stderr,argv[0]); npargs = asize(pa); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE,fnm,npargs,pa,asize(desc),desc,0,NULL,&oenv); bXmin = opt2parg_bSet("-xmin",npargs,pa); bXmax = opt2parg_bSet("-xmax",npargs,pa); bRadial = (amax>0 || rmax>0); if (bRadial) { if (amax<=0 || rmax<=0) gmx_fatal(FARGS,"Both amax and rmax should be larger than zero"); } if (strcmp(eunit[0],"nm-3") == 0) { nmpower = -3; unit = "(nm^-3)"; } else if (strcmp(eunit[0],"nm-2") == 0) { nmpower = -2; unit = "(nm^-2)"; } else { nmpower = 0; unit = "count"; } if (ftp2bSet(efTPS,NFILE,fnm) || !ftp2bSet(efNDX,NFILE,fnm)) read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box, bRadial); if (!bRadial) { ngrps = 1; fprintf(stderr,"\nSelect an analysis group\n"); } else { ngrps = 3; fprintf(stderr, "\nSelect two groups to define the axis and an analysis group\n"); } snew(gnx,ngrps); snew(grpname,ngrps); snew(ind,ngrps); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),ngrps,gnx,ind,grpname); anagrp = ngrps - 1; nindex = gnx[anagrp]; index = ind[anagrp]; if (bRadial) { if ((gnx[0]>1 || gnx[1]>1) && !ftp2bSet(efTPS,NFILE,fnm)) gmx_fatal(FARGS,"No run input file was supplied (option -s), this is required for the center of mass calculation"); } switch (eaver[0][0]) { case 'x': cav = XX; c1 = YY; c2 = ZZ; break; case 'y': cav = YY; c1 = XX; c2 = ZZ; break; case 'z': cav = ZZ; c1 = XX; c2 = YY; break; } natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (!bRadial) { if (n1 == 0) n1 = (int)(box[c1][c1]/bin + 0.5); if (n2 == 0) n2 = (int)(box[c2][c2]/bin + 0.5); } else { n1 = (int)(2*amax/bin + 0.5); nradial = (int)(rmax/bin + 0.5); invspa = n1/(2*amax); invspz = nradial/rmax; if (bMirror) n2 = 2*nradial; else n2 = nradial; } snew(grid,n1); for(i=0; i<n1; i++) snew(grid[i],n2); box1 = 0; box2 = 0; nfr = 0; do { if (!bRadial) { box1 += box[c1][c1]; box2 += box[c2][c2]; invcellvol = n1*n2; if (nmpower == -3) invcellvol /= det(box); else if (nmpower == -2) invcellvol /= box[c1][c1]*box[c2][c2]; for(i=0; i<nindex; i++) { j = index[i]; if ((!bXmin || x[j][cav] >= xmin) && (!bXmax || x[j][cav] <= xmax)) { m1 = x[j][c1]/box[c1][c1]; if (m1 >= 1) m1 -= 1; if (m1 < 0) m1 += 1; m2 = x[j][c2]/box[c2][c2]; if (m2 >= 1) m2 -= 1; if (m2 < 0) m2 += 1; grid[(int)(m1*n1)][(int)(m2*n2)] += invcellvol; } } } else { set_pbc(&pbc,ePBC,box); for(i=0; i<2; i++) { if (gnx[i] == 1) { /* One atom, just copy the coordinates */ copy_rvec(x[ind[i][0]],xcom[i]); } else { /* Calculate the center of mass */ clear_rvec(xcom[i]); mtot = 0; for(j=0; j<gnx[i]; j++) { k = ind[i][j]; m = top.atoms.atom[k].m; for(l=0; l<DIM; l++) xcom[i][l] += m*x[k][l]; mtot += m; } svmul(1/mtot,xcom[i],xcom[i]); } } pbc_dx(&pbc,xcom[1],xcom[0],direction); for(i=0; i<DIM; i++) center[i] = xcom[0][i] + 0.5*direction[i]; unitv(direction,direction); for(i=0; i<nindex; i++) { j = index[i]; pbc_dx(&pbc,x[j],center,dx); axial = iprod(dx,direction); r = sqrt(norm2(dx) - axial*axial); if (axial>=-amax && axial<amax && r<rmax) { if (bMirror) r += rmax; grid[(int)((axial + amax)*invspa)][(int)(r*invspz)] += 1; } } } nfr++; } while(read_next_x(oenv,status,&t,natoms,x,box)); close_trj(status); /* normalize gridpoints */ maxgrid = 0; if (!bRadial) { for (i=0; i<n1; i++) { for (j=0; j<n2; j++) { grid[i][j] /= nfr; if (grid[i][j] > maxgrid) maxgrid = grid[i][j]; } } } else { for (i=0; i<n1; i++) { vol_old = 0; for (j=0; j<nradial; j++) { switch (nmpower) { case -3: vol = M_PI*(j+1)*(j+1)/(invspz*invspz*invspa); break; case -2: vol = (j+1)/(invspz*invspa); break; default: vol = j+1; break; } if (bMirror) k = j + nradial; else k = j; grid[i][k] /= nfr*(vol - vol_old); if (bMirror) grid[i][nradial-1-j] = grid[i][k]; vol_old = vol; if (grid[i][k] > maxgrid) maxgrid = grid[i][k]; } } } fprintf(stdout,"\n The maximum density is %f %s\n",maxgrid,unit); if (dmax > 0) maxgrid = dmax; snew(tickx,n1+1); snew(tickz,n2+1); if (!bRadial) { /* normalize box-axes */ box1 /= nfr; box2 /= nfr; for (i=0; i<=n1; i++) tickx[i] = i*box1/n1; for (i=0; i<=n2; i++) tickz[i] = i*box2/n2; } else { for (i=0; i<=n1; i++) tickx[i] = i/invspa - amax; if (bMirror) { for (i=0; i<=n2; i++) tickz[i] = i/invspz - rmax; } else { for (i=0; i<=n2; i++) tickz[i] = i/invspz; } } if (bSums) { for (i=0; i<n1; ++i) { fprintf(stdout,"Density sums:\n"); rowsum=0; for (j=0; j<n2; ++j) rowsum+=grid[i][j]; fprintf(stdout,"%g\t",rowsum); } fprintf(stdout,"\n"); } sprintf(buf,"%s number density",grpname[anagrp]); if (!bRadial && (bXmin || bXmax)) { if (!bXmax) sprintf(buf+strlen(buf),", %c > %g nm",eaver[0][0],xmin); else if (!bXmin) sprintf(buf+strlen(buf),", %c < %g nm",eaver[0][0],xmax); else sprintf(buf+strlen(buf),", %c: %g - %g nm",eaver[0][0],xmin,xmax); } if (ftp2bSet(efDAT,NFILE,fnm)) { fp = ffopen(ftp2fn(efDAT,NFILE,fnm),"w"); /*optional text form output: first row is tickz; first col is tickx */ fprintf(fp,"0\t"); for(j=0; j<n2; ++j) fprintf(fp,"%g\t",tickz[j]); fprintf(fp,"\n"); for (i=0; i<n1; ++i) { fprintf(fp,"%g\t",tickx[i]); for (j=0; j<n2; ++j) fprintf(fp,"%g\t",grid[i][j]); fprintf(fp,"\n"); } ffclose(fp); } else { fp = ffopen(ftp2fn(efXPM,NFILE,fnm),"w"); write_xpm(fp,MAT_SPATIAL_X | MAT_SPATIAL_Y,buf,unit, bRadial ? "axial (nm)" : label[c1],bRadial ? "r (nm)" : label[c2], n1,n2,tickx,tickz,grid,dmin,maxgrid,rlo,rhi,&nlev); ffclose(fp); } thanx(stderr); do_view(oenv,opt2fn("-o",NFILE,fnm),NULL); return 0; }
int gmx_polystat(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots static properties of polymers as a function of time", "and prints the average.[PAR]", "By default it determines the average end-to-end distance and radii", "of gyration of polymers. It asks for an index group and split this", "into molecules. The end-to-end distance is then determined using", "the first and the last atom in the index group for each molecules.", "For the radius of gyration the total and the three principal components", "for the average gyration tensor are written.", "With option [TT]-v[tt] the eigenvectors are written.", "With option [TT]-pc[tt] also the average eigenvalues of the individual", "gyration tensors are written.", "With option [TT]-i[tt] the mean square internal distances are", "written.[PAR]", "With option [TT]-p[tt] the persistence length is determined.", "The chosen index group should consist of atoms that are", "consecutively bonded in the polymer mainchains.", "The persistence length is then determined from the cosine of", "the angles between bonds with an index difference that is even,", "the odd pairs are not used, because straight polymer backbones", "are usually all trans and therefore only every second bond aligns.", "The persistence length is defined as number of bonds where", "the average cos reaches a value of 1/e. This point is determined", "by a linear interpolation of [LOG]<cos>[log]." }; static gmx_bool bMW = TRUE, bPC = FALSE; t_pargs pa[] = { { "-mw", FALSE, etBOOL, {&bMW}, "Use the mass weighting for radii of gyration" }, { "-pc", FALSE, etBOOL, {&bPC}, "Plot average eigenvalues" } }; t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD }, { efTRX, "-f", nullptr, ffREAD }, { efNDX, nullptr, nullptr, ffOPTRD }, { efXVG, "-o", "polystat", ffWRITE }, { efXVG, "-v", "polyvec", ffOPTWR }, { efXVG, "-p", "persist", ffOPTWR }, { efXVG, "-i", "intdist", ffOPTWR } }; #define NFILE asize(fnm) t_topology *top; gmx_output_env_t *oenv; int ePBC; int isize, *index, nmol, *molind, mol, nat_min = 0, nat_max = 0; char *grpname; t_trxstatus *status; real t; rvec *x, *bond = nullptr; matrix box; int natoms, i, j, frame, ind0, ind1, a, d, d2, ord[DIM] = {0}; dvec cm, sum_eig = {0, 0, 0}; double **gyr, **gyr_all, eig[DIM], **eigv; double sum_eed2, sum_eed2_tot, sum_gyro, sum_gyro_tot, sum_pers_tot; int *ninp = nullptr; double *sum_inp = nullptr, pers; double *intd, ymax, ymin; double mmol, m; char title[STRLEN]; FILE *out, *outv, *outp, *outi; const char *leg[8] = { "end to end", "<R\\sg\\N>", "<R\\sg\\N> eig1", "<R\\sg\\N> eig2", "<R\\sg\\N> eig3", "<R\\sg\\N eig1>", "<R\\sg\\N eig2>", "<R\\sg\\N eig3>" }; char **legp, buf[STRLEN]; gmx_rmpbc_t gpbc = nullptr; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_TIME_UNIT, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv)) { return 0; } snew(top, 1); ePBC = read_tpx_top(ftp2fn(efTPR, NFILE, fnm), nullptr, box, &natoms, nullptr, nullptr, top); fprintf(stderr, "Select a group of polymer mainchain atoms:\n"); get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); snew(molind, top->mols.nr+1); nmol = 0; mol = -1; for (i = 0; i < isize; i++) { if (i == 0 || index[i] >= top->mols.index[mol+1]) { molind[nmol++] = i; do { mol++; } while (index[i] >= top->mols.index[mol+1]); } } molind[nmol] = i; nat_min = top->atoms.nr; nat_max = 0; for (mol = 0; mol < nmol; mol++) { nat_min = std::min(nat_min, molind[mol+1]-molind[mol]); nat_max = std::max(nat_max, molind[mol+1]-molind[mol]); } fprintf(stderr, "Group %s consists of %d molecules\n", grpname, nmol); fprintf(stderr, "Group size per molecule, min: %d atoms, max %d atoms\n", nat_min, nat_max); sprintf(title, "Size of %d polymers", nmol); out = xvgropen(opt2fn("-o", NFILE, fnm), title, output_env_get_xvgr_tlabel(oenv), "(nm)", oenv); xvgr_legend(out, bPC ? 8 : 5, leg, oenv); if (opt2bSet("-v", NFILE, fnm)) { outv = xvgropen(opt2fn("-v", NFILE, fnm), "Principal components", output_env_get_xvgr_tlabel(oenv), "(nm)", oenv); snew(legp, DIM*DIM); for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { sprintf(buf, "eig%d %c", d+1, 'x'+d2); legp[d*DIM+d2] = gmx_strdup(buf); } } xvgr_legend(outv, DIM*DIM, (const char**)legp, oenv); } else { outv = nullptr; } if (opt2bSet("-p", NFILE, fnm)) { outp = xvgropen(opt2fn("-p", NFILE, fnm), "Persistence length", output_env_get_xvgr_tlabel(oenv), "bonds", oenv); snew(bond, nat_max-1); snew(sum_inp, nat_min/2); snew(ninp, nat_min/2); } else { outp = nullptr; } if (opt2bSet("-i", NFILE, fnm)) { outi = xvgropen(opt2fn("-i", NFILE, fnm), "Internal distances", "n", "<R\\S2\\N(n)>/n (nm\\S2\\N)", oenv); i = index[molind[1]-1] - index[molind[0]]; /* Length of polymer -1 */ snew(intd, i); } else { intd = nullptr; outi = nullptr; } natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); snew(gyr, DIM); snew(gyr_all, DIM); snew(eigv, DIM); for (d = 0; d < DIM; d++) { snew(gyr[d], DIM); snew(gyr_all[d], DIM); snew(eigv[d], DIM); } frame = 0; sum_eed2_tot = 0; sum_gyro_tot = 0; sum_pers_tot = 0; gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); do { gmx_rmpbc(gpbc, natoms, box, x); sum_eed2 = 0; for (d = 0; d < DIM; d++) { clear_dvec(gyr_all[d]); } if (bPC) { clear_dvec(sum_eig); } if (outp) { for (i = 0; i < nat_min/2; i++) { sum_inp[i] = 0; ninp[i] = 0; } } for (mol = 0; mol < nmol; mol++) { ind0 = molind[mol]; ind1 = molind[mol+1]; /* Determine end to end distance */ sum_eed2 += distance2(x[index[ind0]], x[index[ind1-1]]); /* Determine internal distances */ if (outi) { calc_int_dist(intd, x, index[ind0], index[ind1-1]); } /* Determine the radius of gyration */ clear_dvec(cm); for (d = 0; d < DIM; d++) { clear_dvec(gyr[d]); } mmol = 0; for (i = ind0; i < ind1; i++) { a = index[i]; if (bMW) { m = top->atoms.atom[a].m; } else { m = 1; } mmol += m; for (d = 0; d < DIM; d++) { cm[d] += m*x[a][d]; for (d2 = 0; d2 < DIM; d2++) { gyr[d][d2] += m*x[a][d]*x[a][d2]; } } } dsvmul(1/mmol, cm, cm); for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { gyr[d][d2] = gyr[d][d2]/mmol - cm[d]*cm[d2]; gyr_all[d][d2] += gyr[d][d2]; } } if (bPC) { gyro_eigen(gyr, eig, eigv, ord); for (d = 0; d < DIM; d++) { sum_eig[d] += eig[ord[d]]; } } if (outp) { for (i = ind0; i < ind1-1; i++) { rvec_sub(x[index[i+1]], x[index[i]], bond[i-ind0]); unitv(bond[i-ind0], bond[i-ind0]); } for (i = ind0; i < ind1-1; i++) { for (j = 0; (i+j < ind1-1 && j < nat_min/2); j += 2) { sum_inp[j] += iprod(bond[i-ind0], bond[i-ind0+j]); ninp[j]++; } } } } sum_eed2 /= nmol; sum_gyro = 0; for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { gyr_all[d][d2] /= nmol; } sum_gyro += gyr_all[d][d]; } gyro_eigen(gyr_all, eig, eigv, ord); fprintf(out, "%10.3f %8.4f %8.4f %8.4f %8.4f %8.4f", t*output_env_get_time_factor(oenv), std::sqrt(sum_eed2), sqrt(sum_gyro), std::sqrt(eig[ord[0]]), std::sqrt(eig[ord[1]]), std::sqrt(eig[ord[2]])); if (bPC) { for (d = 0; d < DIM; d++) { fprintf(out, " %8.4f", std::sqrt(sum_eig[d]/nmol)); } } fprintf(out, "\n"); if (outv) { fprintf(outv, "%10.3f", t*output_env_get_time_factor(oenv)); for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { fprintf(outv, " %6.3f", eigv[ord[d]][d2]); } } fprintf(outv, "\n"); } sum_eed2_tot += sum_eed2; sum_gyro_tot += sum_gyro; if (outp) { i = -1; for (j = 0; j < nat_min/2; j += 2) { sum_inp[j] /= ninp[j]; if (i == -1 && sum_inp[j] <= std::exp(-1.0)) { i = j; } } if (i == -1) { pers = j; } else { /* Do linear interpolation on a log scale */ pers = i - 2.0 + 2.0*(std::log(sum_inp[i-2]) + 1.0)/(std::log(sum_inp[i-2]) - std::log(sum_inp[i])); } fprintf(outp, "%10.3f %8.4f\n", t*output_env_get_time_factor(oenv), pers); sum_pers_tot += pers; } frame++; } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); close_trx(status); xvgrclose(out); if (outv) { xvgrclose(outv); } if (outp) { xvgrclose(outp); } sum_eed2_tot /= frame; sum_gyro_tot /= frame; sum_pers_tot /= frame; fprintf(stdout, "\nAverage end to end distance: %.3f (nm)\n", std::sqrt(sum_eed2_tot)); fprintf(stdout, "\nAverage radius of gyration: %.3f (nm)\n", std::sqrt(sum_gyro_tot)); if (opt2bSet("-p", NFILE, fnm)) { fprintf(stdout, "\nAverage persistence length: %.2f bonds\n", sum_pers_tot); } /* Handle printing of internal distances. */ if (outi) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(outi, "@ xaxes scale Logarithmic\n"); } ymax = -1; ymin = 1e300; j = index[molind[1]-1] - index[molind[0]]; /* Polymer length -1. */ for (i = 0; i < j; i++) { intd[i] /= (i + 1) * frame * nmol; if (intd[i] > ymax) { ymax = intd[i]; } if (intd[i] < ymin) { ymin = intd[i]; } } xvgr_world(outi, 1, ymin, j, ymax, oenv); for (i = 0; i < j; i++) { fprintf(outi, "%d %8.4f\n", i+1, intd[i]); } xvgrclose(outi); } do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); if (opt2bSet("-v", NFILE, fnm)) { do_view(oenv, opt2fn("-v", NFILE, fnm), "-nxy"); } if (opt2bSet("-p", NFILE, fnm)) { do_view(oenv, opt2fn("-p", NFILE, fnm), "-nxy"); } return 0; }
int gmx_editconf(int argc, char *argv[]) { const char *desc[] = { "editconf converts generic structure format to [TT].gro[tt], [TT].g96[tt]", "or [TT].pdb[tt].", "[PAR]", "The box can be modified with options [TT]-box[tt], [TT]-d[tt] and", "[TT]-angles[tt]. Both [TT]-box[tt] and [TT]-d[tt]", "will center the system in the box, unless [TT]-noc[tt] is used.", "[PAR]", "Option [TT]-bt[tt] determines the box type: [TT]triclinic[tt] is a", "triclinic box, [TT]cubic[tt] is a rectangular box with all sides equal", "[TT]dodecahedron[tt] represents a rhombic dodecahedron and", "[TT]octahedron[tt] is a truncated octahedron.", "The last two are special cases of a triclinic box.", "The length of the three box vectors of the truncated octahedron is the", "shortest distance between two opposite hexagons.", "The volume of a dodecahedron is 0.71 and that of a truncated octahedron", "is 0.77 of that of a cubic box with the same periodic image distance.", "[PAR]", "Option [TT]-box[tt] requires only", "one value for a cubic box, dodecahedron and a truncated octahedron.", "[PAR]", "With [TT]-d[tt] and a [TT]triclinic[tt] box the size of the system in the x, y", "and z directions is used. With [TT]-d[tt] and [TT]cubic[tt],", "[TT]dodecahedron[tt] or [TT]octahedron[tt] boxes, the dimensions are set", "to the diameter of the system (largest distance between atoms) plus twice", "the specified distance.", "[PAR]", "Option [TT]-angles[tt] is only meaningful with option [TT]-box[tt] and", "a triclinic box and can not be used with option [TT]-d[tt].", "[PAR]", "When [TT]-n[tt] or [TT]-ndef[tt] is set, a group", "can be selected for calculating the size and the geometric center,", "otherwise the whole system is used.", "[PAR]", "[TT]-rotate[tt] rotates the coordinates and velocities.", "[PAR]", "[TT]-princ[tt] aligns the principal axes of the system along the", "coordinate axes, this may allow you to decrease the box volume,", "but beware that molecules can rotate significantly in a nanosecond.", "[PAR]", "Scaling is applied before any of the other operations are", "performed. Boxes and coordinates can be scaled to give a certain density (option", "[TT]-density[tt]). Note that this may be inaccurate in case a gro", "file is given as input. A special feature of the scaling option, when the", "factor -1 is given in one dimension, one obtains a mirror image,", "mirrored in one of the plains, when one uses -1 in three dimensions", "a point-mirror image is obtained.[PAR]", "Groups are selected after all operations have been applied.[PAR]", "Periodicity can be removed in a crude manner.", "It is important that the box sizes at the bottom of your input file", "are correct when the periodicity is to be removed.", "[PAR]", "When writing [TT].pdb[tt] files, B-factors can be", "added with the [TT]-bf[tt] option. B-factors are read", "from a file with with following format: first line states number of", "entries in the file, next lines state an index", "followed by a B-factor. The B-factors will be attached per residue", "unless an index is larger than the number of residues or unless the", "[TT]-atom[tt] option is set. Obviously, any type of numeric data can", "be added instead of B-factors. [TT]-legend[tt] will produce", "a row of CA atoms with B-factors ranging from the minimum to the", "maximum value found, effectively making a legend for viewing.", "[PAR]", "With the option -mead a special pdb (pqr) file for the MEAD electrostatics", "program (Poisson-Boltzmann solver) can be made. A further prerequisite", "is that the input file is a run input file.", "The B-factor field is then filled with the Van der Waals radius", "of the atoms while the occupancy field will hold the charge.", "[PAR]", "The option -grasp is similar, but it puts the charges in the B-factor", "and the radius in the occupancy.", "[PAR]", "Option [TT]-align[tt] allows alignment", "of the principal axis of a specified group against the given vector, ", "with an optional center of rotation specified by [TT]-aligncenter[tt].", "[PAR]", "Finally with option [TT]-label[tt] editconf can add a chain identifier", "to a pdb file, which can be useful for analysis with e.g. rasmol.", "[PAR]", "To convert a truncated octrahedron file produced by a package which uses", "a cubic box with the corners cut off (such as Gromos) use:[BR]", "[TT]editconf -f <in> -rotate 0 45 35.264 -bt o -box <veclen> -o <out>[tt][BR]", "where [TT]veclen[tt] is the size of the cubic box times sqrt(3)/2." }; const char *bugs[] = { "For complex molecules, the periodicity removal routine may break down, ", "in that case you can use trjconv." }; static real dist = 0.0, rbox = 0.0, to_diam = 0.0; static gmx_bool bNDEF = FALSE, bRMPBC = FALSE, bCenter = FALSE, bReadVDW = FALSE, bCONECT = FALSE; static gmx_bool peratom = FALSE, bLegend = FALSE, bOrient = FALSE, bMead = FALSE, bGrasp = FALSE, bSig56 = FALSE; static rvec scale = { 1, 1, 1 }, newbox = { 0, 0, 0 }, newang = { 90, 90, 90 }; static real rho = 1000.0, rvdw = 0.12; static rvec center = { 0, 0, 0 }, translation = { 0, 0, 0 }, rotangles = { 0, 0, 0 }, aligncenter = { 0, 0, 0 }, targetvec = { 0, 0, 0 }; static const char *btype[] = { NULL, "triclinic", "cubic", "dodecahedron", "octahedron", NULL }, *label = "A"; static rvec visbox = { 0, 0, 0 }; t_pargs pa[] = { { "-ndef", FALSE, etBOOL, { &bNDEF }, "Choose output from default index groups" }, { "-visbox", FALSE, etRVEC, { visbox }, "HIDDENVisualize a grid of boxes, -1 visualizes the 14 box images" }, { "-bt", FALSE, etENUM, { btype }, "Box type for -box and -d" }, { "-box", FALSE, etRVEC, { newbox }, "Box vector lengths (a,b,c)" }, { "-angles", FALSE, etRVEC, { newang }, "Angles between the box vectors (bc,ac,ab)" }, { "-d", FALSE, etREAL, { &dist }, "Distance between the solute and the box" }, { "-c", FALSE, etBOOL, { &bCenter }, "Center molecule in box (implied by -box and -d)" }, { "-center", FALSE, etRVEC, { center }, "Coordinates of geometrical center" }, { "-aligncenter", FALSE, etRVEC, { aligncenter }, "Center of rotation for alignment" }, { "-align", FALSE, etRVEC, { targetvec }, "Align to target vector" }, { "-translate", FALSE, etRVEC, { translation }, "Translation" }, { "-rotate", FALSE, etRVEC, { rotangles }, "Rotation around the X, Y and Z axes in degrees" }, { "-princ", FALSE, etBOOL, { &bOrient }, "Orient molecule(s) along their principal axes" }, { "-scale", FALSE, etRVEC, { scale }, "Scaling factor" }, { "-density", FALSE, etREAL, { &rho }, "Density (g/l) of the output box achieved by scaling" }, { "-pbc", FALSE, etBOOL, { &bRMPBC }, "Remove the periodicity (make molecule whole again)" }, { "-grasp", FALSE, etBOOL, { &bGrasp }, "Store the charge of the atom in the B-factor field and the radius of the atom in the occupancy field" }, { "-rvdw", FALSE, etREAL, { &rvdw }, "Default Van der Waals radius (in nm) if one can not be found in the database or if no parameters are present in the topology file" }, { "-sig56", FALSE, etREAL, { &bSig56 }, "Use rmin/2 (minimum in the Van der Waals potential) rather than sigma/2 " }, { "-vdwread", FALSE, etBOOL, { &bReadVDW }, "Read the Van der Waals radii from the file vdwradii.dat rather than computing the radii based on the force field" }, { "-atom", FALSE, etBOOL, { &peratom }, "Force B-factor attachment per atom" }, { "-legend", FALSE, etBOOL, { &bLegend }, "Make B-factor legend" }, { "-label", FALSE, etSTR, { &label }, "Add chain label for all residues" }, { "-conect", FALSE, etBOOL, { &bCONECT }, "Add CONECT records to a pdb file when written. Can only be done when a topology is present" } }; #define NPA asize(pa) FILE *out; const char *infile, *outfile; char title[STRLEN]; int outftp, inftp, natom, i, j, n_bfac, itype, ntype; double *bfac = NULL, c6, c12; int *bfac_nr = NULL; t_topology *top = NULL; t_atoms atoms; char *grpname, *sgrpname, *agrpname; int isize, ssize, tsize, asize; atom_id *index, *sindex, *tindex, *aindex; rvec *x, *v, gc, min, max, size; int ePBC; matrix box,rotmatrix,trans; rvec princd,tmpvec; gmx_bool bIndex, bSetSize, bSetAng, bCubic, bDist, bSetCenter, bAlign; gmx_bool bHaveV, bScale, bRho, bTranslate, bRotate, bCalcGeom, bCalcDiam; real xs, ys, zs, xcent, ycent, zcent, diam = 0, mass = 0, d, vdw; gmx_atomprop_t aps; gmx_conect conect; output_env_t oenv; t_filenm fnm[] = { { efSTX, "-f", NULL, ffREAD }, { efNDX, "-n", NULL, ffOPTRD }, { efSTO, NULL, NULL, ffOPTWR }, { efPQR, "-mead", "mead", ffOPTWR }, { efDAT, "-bf", "bfact", ffOPTRD } }; #define NFILE asize(fnm) CopyRight(stderr, argv[0]); parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, NPA, pa, asize(desc), desc, asize(bugs), bugs, &oenv); bIndex = opt2bSet("-n", NFILE, fnm) || bNDEF; bMead = opt2bSet("-mead", NFILE, fnm); bSetSize = opt2parg_bSet("-box", NPA, pa); bSetAng = opt2parg_bSet("-angles", NPA, pa); bSetCenter = opt2parg_bSet("-center", NPA, pa); bDist = opt2parg_bSet("-d", NPA, pa); bAlign = opt2parg_bSet("-align", NPA, pa); /* Only automatically turn on centering without -noc */ if ((bDist || bSetSize || bSetCenter) && !opt2parg_bSet("-c", NPA, pa)) { bCenter = TRUE; } bScale = opt2parg_bSet("-scale", NPA, pa); bRho = opt2parg_bSet("-density", NPA, pa); bTranslate = opt2parg_bSet("-translate", NPA, pa); bRotate = opt2parg_bSet("-rotate", NPA, pa); if (bScale && bRho) fprintf(stderr, "WARNING: setting -density overrides -scale\n"); bScale = bScale || bRho; bCalcGeom = bCenter || bRotate || bOrient || bScale; bCalcDiam = btype[0][0] == 'c' || btype[0][0] == 'd' || btype[0][0] == 'o'; infile = ftp2fn(efSTX, NFILE, fnm); if (bMead) outfile = ftp2fn(efPQR, NFILE, fnm); else outfile = ftp2fn(efSTO, NFILE, fnm); outftp = fn2ftp(outfile); inftp = fn2ftp(infile); aps = gmx_atomprop_init(); if (bMead && bGrasp) { printf("Incompatible options -mead and -grasp. Turning off -grasp\n"); bGrasp = FALSE; } if (bGrasp && (outftp != efPDB)) gmx_fatal(FARGS, "Output file should be a .pdb file" " when using the -grasp option\n"); if ((bMead || bGrasp) && !((fn2ftp(infile) == efTPR) || (fn2ftp(infile) == efTPA) || (fn2ftp(infile) == efTPB))) gmx_fatal(FARGS,"Input file should be a .tp[abr] file" " when using the -mead option\n"); get_stx_coordnum(infile,&natom); init_t_atoms(&atoms,natom,TRUE); snew(x,natom); snew(v,natom); read_stx_conf(infile,title,&atoms,x,v,&ePBC,box); if (fn2ftp(infile) == efPDB) { get_pdb_atomnumber(&atoms,aps); } printf("Read %d atoms\n",atoms.nr); /* Get the element numbers if available in a pdb file */ if (fn2ftp(infile) == efPDB) get_pdb_atomnumber(&atoms,aps); if (ePBC != epbcNONE) { real vol = det(box); printf("Volume: %g nm^3, corresponds to roughly %d electrons\n", vol,100*((int)(vol*4.5))); } if (bMead || bGrasp || bCONECT) top = read_top(infile,NULL); if (bMead || bGrasp) { if (atoms.nr != top->atoms.nr) gmx_fatal(FARGS,"Atom numbers don't match (%d vs. %d)",atoms.nr,top->atoms.nr); snew(atoms.pdbinfo,top->atoms.nr); ntype = top->idef.atnr; for(i=0; (i<atoms.nr); i++) { /* Determine the Van der Waals radius from the force field */ if (bReadVDW) { if (!gmx_atomprop_query(aps,epropVDW, *top->atoms.resinfo[top->atoms.atom[i].resind].name, *top->atoms.atomname[i],&vdw)) vdw = rvdw; } else { itype = top->atoms.atom[i].type; c12 = top->idef.iparams[itype*ntype+itype].lj.c12; c6 = top->idef.iparams[itype*ntype+itype].lj.c6; if ((c6 != 0) && (c12 != 0)) { real sig6; if (bSig56) sig6 = 2*c12/c6; else sig6 = c12/c6; vdw = 0.5*pow(sig6,1.0/6.0); } else vdw = rvdw; } /* Factor of 10 for nm -> Angstroms */ vdw *= 10; if (bMead) { atoms.pdbinfo[i].occup = top->atoms.atom[i].q; atoms.pdbinfo[i].bfac = vdw; } else { atoms.pdbinfo[i].occup = vdw; atoms.pdbinfo[i].bfac = top->atoms.atom[i].q; } } } bHaveV=FALSE; for (i=0; (i<natom) && !bHaveV; i++) for (j=0; (j<DIM) && !bHaveV; j++) bHaveV=bHaveV || (v[i][j]!=0); printf("%selocities found\n",bHaveV?"V":"No v"); if (visbox[0] > 0) { if (bIndex) gmx_fatal(FARGS,"Sorry, can not visualize box with index groups"); if (outftp != efPDB) gmx_fatal(FARGS,"Sorry, can only visualize box with a pdb file"); } else if (visbox[0] == -1) visualize_images("images.pdb",ePBC,box); /* remove pbc */ if (bRMPBC) rm_gropbc(&atoms,x,box); if (bCalcGeom) { if (bIndex) { fprintf(stderr,"\nSelect a group for determining the system size:\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm), 1,&ssize,&sindex,&sgrpname); } else { ssize = atoms.nr; sindex = NULL; } diam=calc_geom(ssize,sindex,x,gc,min,max,bCalcDiam); rvec_sub(max, min, size); printf(" system size :%7.3f%7.3f%7.3f (nm)\n", size[XX], size[YY], size[ZZ]); if (bCalcDiam) printf(" diameter :%7.3f (nm)\n",diam); printf(" center :%7.3f%7.3f%7.3f (nm)\n", gc[XX], gc[YY], gc[ZZ]); printf(" box vectors :%7.3f%7.3f%7.3f (nm)\n", norm(box[XX]), norm(box[YY]), norm(box[ZZ])); printf(" box angles :%7.2f%7.2f%7.2f (degrees)\n", norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[YY],box[ZZ])), norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[ZZ])), norm2(box[YY])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[YY]))); printf(" box volume :%7.2f (nm^3)\n",det(box)); } if (bRho || bOrient || bAlign) mass = calc_mass(&atoms,!fn2bTPX(infile),aps); if (bOrient) { atom_id *index; char *grpnames; /* Get a group for principal component analysis */ fprintf(stderr,"\nSelect group for the determining the orientation\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpnames); /* Orient the principal axes along the coordinate axes */ orient_princ(&atoms,isize,index,natom,x,bHaveV ? v : NULL, NULL); sfree(index); sfree(grpnames); } if ( bScale ) { /* scale coordinates and box */ if (bRho) { /* Compute scaling constant */ real vol,dens; vol = det(box); dens = (mass*AMU)/(vol*NANO*NANO*NANO); fprintf(stderr,"Volume of input %g (nm^3)\n",vol); fprintf(stderr,"Mass of input %g (a.m.u.)\n",mass); fprintf(stderr,"Density of input %g (g/l)\n",dens); if (vol==0 || mass==0) gmx_fatal(FARGS,"Cannot scale density with " "zero mass (%g) or volume (%g)\n",mass,vol); scale[XX] = scale[YY] = scale[ZZ] = pow(dens/rho,1.0/3.0); fprintf(stderr,"Scaling all box vectors by %g\n",scale[XX]); } scale_conf(atoms.nr,x,box,scale); } if (bAlign) { if (bIndex) { fprintf(stderr,"\nSelect a group that you want to align:\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm), 1,&asize,&aindex,&agrpname); } else { asize = atoms.nr; snew(aindex,asize); for (i=0;i<asize;i++) aindex[i]=i; } printf("Aligning %d atoms (out of %d) to %g %g %g, center of rotation %g %g %g\n",asize,natom, targetvec[XX],targetvec[YY],targetvec[ZZ], aligncenter[XX],aligncenter[YY],aligncenter[ZZ]); /*subtract out pivot point*/ for(i=0; i<asize; i++) rvec_dec(x[aindex[i]],aligncenter); /*now determine transform and rotate*/ /*will this work?*/ principal_comp(asize,aindex,atoms.atom,x, trans,princd); unitv(targetvec,targetvec); printf("Using %g %g %g as principal axis\n", trans[0][2],trans[1][2],trans[2][2]); tmpvec[XX]=trans[0][2]; tmpvec[YY]=trans[1][2]; tmpvec[ZZ]=trans[2][2]; calc_rotmatrix(tmpvec, targetvec, rotmatrix); /* rotmatrix finished */ for (i=0;i<asize;++i) { mvmul(rotmatrix,x[aindex[i]],tmpvec); copy_rvec(tmpvec,x[aindex[i]]); } /*add pivot point back*/ for(i=0; i<asize; i++) rvec_inc(x[aindex[i]],aligncenter); if (!bIndex) sfree(aindex); } if (bTranslate) { if (bIndex) { fprintf(stderr,"\nSelect a group that you want to translate:\n"); get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm), 1,&ssize,&sindex,&sgrpname); } else { ssize = atoms.nr; sindex = NULL; } printf("Translating %d atoms (out of %d) by %g %g %g nm\n",ssize,natom, translation[XX],translation[YY],translation[ZZ]); if (sindex) { for(i=0; i<ssize; i++) rvec_inc(x[sindex[i]],translation); } else { for(i=0; i<natom; i++) rvec_inc(x[i],translation); } } if (bRotate) { /* Rotate */ printf("Rotating %g, %g, %g degrees around the X, Y and Z axis respectively\n",rotangles[XX],rotangles[YY],rotangles[ZZ]); for(i=0; i<DIM; i++) rotangles[i] *= DEG2RAD; rotate_conf(natom,x,v,rotangles[XX],rotangles[YY],rotangles[ZZ]); } if (bCalcGeom) { /* recalc geometrical center and max and min coordinates and size */ calc_geom(ssize,sindex,x,gc,min,max,FALSE); rvec_sub(max, min, size); if (bScale || bOrient || bRotate) printf("new system size : %6.3f %6.3f %6.3f\n", size[XX],size[YY],size[ZZ]); } if (bSetSize || bDist || (btype[0][0]=='t' && bSetAng)) { ePBC = epbcXYZ; if (!(bSetSize || bDist)) for (i=0; i<DIM; i++) newbox[i] = norm(box[i]); clear_mat(box); /* calculate new boxsize */ switch(btype[0][0]){ case 't': if (bDist) for(i=0; i<DIM; i++) newbox[i] = size[i]+2*dist; if (!bSetAng) { box[XX][XX] = newbox[XX]; box[YY][YY] = newbox[YY]; box[ZZ][ZZ] = newbox[ZZ]; } else { matrix_convert(box,newbox,newang); } break; case 'c': case 'd': case 'o': if (bSetSize) d = newbox[0]; else d = diam+2*dist; if (btype[0][0] == 'c') for(i=0; i<DIM; i++) box[i][i] = d; else if (btype[0][0] == 'd') { box[XX][XX] = d; box[YY][YY] = d; box[ZZ][XX] = d/2; box[ZZ][YY] = d/2; box[ZZ][ZZ] = d*sqrt(2)/2; } else { box[XX][XX] = d; box[YY][XX] = d/3; box[YY][YY] = d*sqrt(2)*2/3; box[ZZ][XX] = -d/3; box[ZZ][YY] = d*sqrt(2)/3; box[ZZ][ZZ] = d*sqrt(6)/3; } break; } } /* calculate new coords for geometrical center */ if (!bSetCenter) calc_box_center(ecenterDEF,box,center); /* center molecule on 'center' */ if (bCenter) center_conf(natom,x,center,gc); /* print some */ if (bCalcGeom) { calc_geom(ssize,sindex,x, gc, min, max, FALSE); printf("new center :%7.3f%7.3f%7.3f (nm)\n",gc[XX],gc[YY],gc[ZZ]); } if (bOrient || bScale || bDist || bSetSize) { printf("new box vectors :%7.3f%7.3f%7.3f (nm)\n", norm(box[XX]), norm(box[YY]), norm(box[ZZ])); printf("new box angles :%7.2f%7.2f%7.2f (degrees)\n", norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[YY],box[ZZ])), norm2(box[ZZ])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[ZZ])), norm2(box[YY])==0 ? 0 : RAD2DEG*acos(cos_angle_no_table(box[XX],box[YY]))); printf("new box volume :%7.2f (nm^3)\n",det(box)); } if (check_box(epbcXYZ,box)) printf("\nWARNING: %s\n",check_box(epbcXYZ,box)); if (bDist && btype[0][0]=='t') { if(TRICLINIC(box)) { printf("\nWARNING: Your box is triclinic with non-orthogonal axes. In this case, the\n" "distance from the solute to a box surface along the corresponding normal\n" "vector might be somewhat smaller than your specified value %f.\n" "You can check the actual value with g_mindist -pi\n",dist); } else { printf("\nWARNING: No boxtype specified - distance condition applied in each dimension.\n" "If the molecule rotates the actual distance will be smaller. You might want\n" "to use a cubic box instead, or why not try a dodecahedron today?\n"); } } if (bCONECT && (outftp == efPDB) && (inftp == efTPR)) conect = gmx_conect_generate(top); else conect = NULL; if (bIndex) { fprintf(stderr,"\nSelect a group for output:\n"); get_index(&atoms,opt2fn_null("-n",NFILE,fnm), 1,&isize,&index,&grpname); if (opt2parg_bSet("-label",NPA,pa)) { for(i=0; (i<atoms.nr); i++) atoms.resinfo[atoms.atom[i].resind].chainid=label[0]; } if (opt2bSet("-bf",NFILE,fnm) || bLegend) { gmx_fatal(FARGS,"Sorry, cannot do bfactors with an index group."); } if (outftp == efPDB) { out=ffopen(outfile,"w"); write_pdbfile_indexed(out,title,&atoms,x,ePBC,box,' ',1,isize,index,conect,TRUE); ffclose(out); } else { write_sto_conf_indexed(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box,isize,index); } } else { if ((outftp == efPDB) || (outftp == efPQR)) { out=ffopen(outfile,"w"); if (bMead) { set_pdb_wide_format(TRUE); fprintf(out,"REMARK " "The B-factors in this file hold atomic radii\n"); fprintf(out,"REMARK " "The occupancy in this file hold atomic charges\n"); } else if (bGrasp) { fprintf(out,"GRASP PDB FILE\nFORMAT NUMBER=1\n"); fprintf(out,"REMARK " "The B-factors in this file hold atomic charges\n"); fprintf(out,"REMARK " "The occupancy in this file hold atomic radii\n"); } else if (opt2bSet("-bf",NFILE,fnm)) { read_bfac(opt2fn("-bf",NFILE,fnm),&n_bfac,&bfac,&bfac_nr); set_pdb_conf_bfac(atoms.nr,atoms.nres,&atoms, n_bfac,bfac,bfac_nr,peratom); } if (opt2parg_bSet("-label",NPA,pa)) { for(i=0; (i<atoms.nr); i++) atoms.resinfo[atoms.atom[i].resind].chainid=label[0]; } write_pdbfile(out,title,&atoms,x,ePBC,box,' ',-1,conect,TRUE); if (bLegend) pdb_legend(out,atoms.nr,atoms.nres,&atoms,x); if (visbox[0] > 0) visualize_box(out,bLegend ? atoms.nr+12 : atoms.nr, bLegend? atoms.nres=12 : atoms.nres,box,visbox); ffclose(out); } else write_sto_conf(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box); } gmx_atomprop_destroy(aps); do_view(oenv,outfile,NULL); thanx(stderr); return 0; }
int gmx_rotmat(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots the rotation matrix required for least squares fitting", "a conformation onto the reference conformation provided with", "[TT]-s[tt]. Translation is removed before fitting.", "The output are the three vectors that give the new directions", "of the x, y and z directions of the reference conformation,", "for example: (zx,zy,zz) is the orientation of the reference", "z-axis in the trajectory frame.", "[PAR]", "This tool is useful for, for instance,", "determining the orientation of a molecule", "at an interface, possibly on a trajectory produced with", "[TT]gmx trjconv -fit rotxy+transxy[tt] to remove the rotation", "in the [IT]x-y[it] plane.", "[PAR]", "Option [TT]-ref[tt] determines a reference structure for fitting,", "instead of using the structure from [TT]-s[tt]. The structure with", "the lowest sum of RMSD's to all other structures is used.", "Since the computational cost of this procedure grows with", "the square of the number of frames, the [TT]-skip[tt] option", "can be useful. A full fit or only a fit in the [IT]x-y[it] plane can", "be performed.", "[PAR]", "Option [TT]-fitxy[tt] fits in the [IT]x-y[it] plane before determining", "the rotation matrix." }; const char *reffit[] = { NULL, "none", "xyz", "xy", NULL }; static int skip = 1; static gmx_bool bFitXY = FALSE, bMW = TRUE; t_pargs pa[] = { { "-ref", FALSE, etENUM, {reffit}, "Determine the optimal reference structure" }, { "-skip", FALSE, etINT, {&skip}, "Use every nr-th frame for [TT]-ref[tt]" }, { "-fitxy", FALSE, etBOOL, {&bFitXY}, "Fit the x/y rotation before determining the rotation" }, { "-mw", FALSE, etBOOL, {&bMW}, "Use mass weighted fitting" } }; FILE *out; t_trxstatus *status; t_topology top; int ePBC; rvec *x_ref, *x; matrix box, R; real t; int natoms, i; char *grpname, title[256]; int gnx; gmx_rmpbc_t gpbc = NULL; atom_id *index; output_env_t oenv; real *w_rls; const char *leg[] = { "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz" }; #define NLEG asize(leg) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "rotmat", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &x_ref, NULL, box, bMW); gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr); gmx_rmpbc(gpbc, top.atoms.nr, box, x_ref); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname); if (reffit[0][0] != 'n') { get_refx(oenv, ftp2fn(efTRX, NFILE, fnm), reffit[0][2] == 'z' ? 3 : 2, skip, gnx, index, bMW, &top, ePBC, x_ref); } natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); snew(w_rls, natoms); for (i = 0; i < gnx; i++) { if (index[i] >= natoms) { gmx_fatal(FARGS, "Atom index (%d) is larger than the number of atoms in the trajecory (%d)", index[i]+1, natoms); } w_rls[index[i]] = (bMW ? top.atoms.atom[index[i]].m : 1.0); } if (reffit[0][0] == 'n') { reset_x(gnx, index, natoms, NULL, x_ref, w_rls); } out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Fit matrix", "Time (ps)", "", oenv); xvgr_legend(out, NLEG, leg, oenv); do { gmx_rmpbc(gpbc, natoms, box, x); reset_x(gnx, index, natoms, NULL, x, w_rls); if (bFitXY) { do_fit_ndim(2, natoms, w_rls, x_ref, x); } calc_fit_R(DIM, natoms, w_rls, x_ref, x, R); fprintf(out, "%7g %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f\n", t, R[XX][XX], R[XX][YY], R[XX][ZZ], R[YY][XX], R[YY][YY], R[YY][ZZ], R[ZZ][XX], R[ZZ][YY], R[ZZ][ZZ]); } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); close_trj(status); gmx_ffclose(out); do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy"); return 0; }
int gmx_potential(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the electrostatical potential across the box. The potential is", "calculated by first summing the charges per slice and then integrating", "twice of this charge distribution. Periodic boundaries are not taken", "into account. Reference of potential is taken to be the left side of", "the box. It is also possible to calculate the potential in spherical", "coordinates as function of r by calculating a charge distribution in", "spherical slices and twice integrating them. epsilon_r is taken as 1,", "but 2 is more appropriate in many cases." }; gmx_output_env_t *oenv; static int axis = 2; /* normal to memb. default z */ static const char *axtitle = "Z"; static int nslices = 10; /* nr of slices defined */ static int ngrps = 1; static gmx_bool bSpherical = FALSE; /* default is bilayer types */ static real fudge_z = 0; /* translate coordinates */ static gmx_bool bCorrect = 0; t_pargs pa [] = { { "-d", FALSE, etSTR, {&axtitle}, "Take the normal on the membrane in direction X, Y or Z." }, { "-sl", FALSE, etINT, {&nslices}, "Calculate potential as function of boxlength, dividing the box" " in this number of slices." }, { "-cb", FALSE, etINT, {&cb}, "Discard this number of first slices of box for integration" }, { "-ce", FALSE, etINT, {&ce}, "Discard this number of last slices of box for integration" }, { "-tz", FALSE, etREAL, {&fudge_z}, "Translate all coordinates by this distance in the direction of the box" }, { "-spherical", FALSE, etBOOL, {&bSpherical}, "Calculate spherical thingie" }, { "-ng", FALSE, etINT, {&ngrps}, "Number of groups to consider" }, { "-correct", FALSE, etBOOL, {&bCorrect}, "Assume net zero charge of groups to improve accuracy" } }; const char *bugs[] = { "Discarding slices for integration should not be necessary." }; double **potential, /* potential per slice */ **charge, /* total charge per slice */ **field, /* field per slice */ slWidth; /* width of one slice */ char **grpname; /* groupnames */ int *ngx; /* sizes of groups */ t_topology *top; /* topology */ int ePBC; int **index; /* indices for all groups */ t_filenm fnm[] = { /* files for g_order */ { efTRX, "-f", NULL, ffREAD }, /* trajectory file */ { efNDX, NULL, NULL, ffREAD }, /* index file */ { efTPR, NULL, NULL, ffREAD }, /* topology file */ { efXVG, "-o", "potential", ffWRITE }, /* xvgr output file */ { efXVG, "-oc", "charge", ffWRITE }, /* xvgr output file */ { efXVG, "-of", "field", ffWRITE }, /* xvgr output file */ }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, asize(bugs), bugs, &oenv)) { return 0; } /* Calculate axis */ axis = toupper(axtitle[0]) - 'X'; top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */ snew(grpname, ngrps); snew(index, ngrps); snew(ngx, ngrps); rd_index(ftp2fn(efNDX, NFILE, fnm), ngrps, ngx, index, grpname); calc_potential(ftp2fn(efTRX, NFILE, fnm), index, ngx, &potential, &charge, &field, &nslices, top, ePBC, axis, ngrps, &slWidth, fudge_z, bSpherical, bCorrect, oenv); plot_potential(potential, charge, field, opt2fn("-o", NFILE, fnm), opt2fn("-oc", NFILE, fnm), opt2fn("-of", NFILE, fnm), nslices, ngrps, (const char**)grpname, slWidth, oenv); do_view(oenv, opt2fn("-o", NFILE, fnm), NULL); /* view xvgr file */ do_view(oenv, opt2fn("-oc", NFILE, fnm), NULL); /* view xvgr file */ do_view(oenv, opt2fn("-of", NFILE, fnm), NULL); /* view xvgr file */ return 0; }
int gmx_h2order(int argc,char *argv[]) { const char *desc[] = { "Compute the orientation of water molecules with respect to the normal", "of the box. The program determines the average cosine of the angle", "between de dipole moment of water and an axis of the box. The box is", "divided in slices and the average orientation per slice is printed.", "Each water molecule is assigned to a slice, per time frame, based on the", "position of the oxygen. When -nm is used the angle between the water", "dipole and the axis from the center of mass to the oxygen is calculated", "instead of the angle between the dipole and a box axis." }; static int axis = 2; /* normal to memb. default z */ static const char *axtitle="Z"; static int nslices = 0; /* nr of slices defined */ t_pargs pa[] = { { "-d", FALSE, etSTR, {&axtitle}, "Take the normal on the membrane in direction X, Y or Z." }, { "-sl", FALSE, etINT, {&nslices}, "Calculate order parameter as function of boxlength, dividing the box" " in #nr slices."} }; const char *bugs[] = { "The program assigns whole water molecules to a slice, based on the first" "atom of three in the index file group. It assumes an order O,H,H." "Name is not important, but the order is. If this demand is not met," "assigning molecules to slices is different." }; output_env_t oenv; real *slOrder, /* av. cosine, per slice */ slWidth = 0.0; /* width of a slice */ rvec *slDipole; char *grpname, /* groupnames */ *micname; int ngx, /* nr. of atomsin sol group */ nmic; /* nr. of atoms in micelle */ t_topology *top; /* topology */ int ePBC; atom_id *index, /* indices for solvent group */ *micelle; gmx_bool bMicel = FALSE; /* think we're a micel */ t_filenm fnm[] = { /* files for g_order */ { efTRX, "-f", NULL, ffREAD }, /* trajectory file */ { efNDX, NULL, NULL, ffREAD }, /* index file */ { efNDX, "-nm", NULL, ffOPTRD }, /* index with micelle atoms */ { efTPX, NULL, NULL, ffREAD }, /* topology file */ { efXVG,"-o", "order", ffWRITE }, /* xvgr output file */ }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE, fnm, asize(pa),pa,asize(desc),desc,asize(bugs),bugs,&oenv); bMicel = opt2bSet("-nm",NFILE,fnm); top = read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC); /* read topology file */ rd_index(ftp2fn(efNDX,NFILE,fnm),1,&ngx,&index,&grpname); if (bMicel) rd_index(opt2fn("-nm",NFILE,fnm), 1, &nmic, &micelle, &micname); calc_h2order(ftp2fn(efTRX,NFILE,fnm), index, ngx, &slDipole, &slOrder, &slWidth, &nslices, top, ePBC, axis, bMicel, micelle, nmic, oenv); h2order_plot(slDipole, slOrder, opt2fn("-o",NFILE,fnm), nslices, slWidth, oenv); do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy"); /* view xvgr file */ thanx(stderr); return 0; }
int gmx_sas(int argc,char *argv[]) { const char *desc[] = { "[TT]g_sas[tt] computes hydrophobic, hydrophilic and total solvent", "accessible surface area. See Eisenhaber F, Lijnzaad P, Argos P,", "Sander C, & Scharf M (1995) J. Comput. Chem. 16, 273-284.", "As a side effect, the Connolly surface can be generated as well in", "a [TT].pdb[tt] file where the nodes are represented as atoms and the", "vertice connecting the nearest nodes as CONECT records.", "The program will ask for a group for the surface calculation", "and a group for the output. The calculation group should always", "consists of all the non-solvent atoms in the system.", "The output group can be the whole or part of the calculation group.", "The average and standard deviation of the area over the trajectory can be plotted", "per residue and atom as well (options [TT]-or[tt] and [TT]-oa[tt]).", "In combination with the latter option an [TT].itp[tt] file can be", "generated (option [TT]-i[tt])", "which can be used to restrain surface atoms.[PAR]", "By default, periodic boundary conditions are taken into account,", "this can be turned off using the [TT]-nopbc[tt] option.[PAR]", "With the [TT]-tv[tt] option the total volume and density of the", "molecule can be computed.", "Please consider whether the normal probe radius is appropriate", "in this case or whether you would rather use e.g. 0. It is good", "to keep in mind that the results for volume and density are very", "approximate. For example, in ice Ih, one can easily fit water molecules in the", "pores which would yield a volume that is too low, and surface area and density", "that are both too high." }; output_env_t oenv; static real solsize = 0.14; static int ndots = 24; static real qcut = 0.2; static real minarea = 0.5, dgs_default=0; static gmx_bool bSave = TRUE,bPBC=TRUE,bFindex=FALSE; t_pargs pa[] = { { "-probe", FALSE, etREAL, {&solsize}, "Radius of the solvent probe (nm)" }, { "-ndots", FALSE, etINT, {&ndots}, "Number of dots per sphere, more dots means more accuracy" }, { "-qmax", FALSE, etREAL, {&qcut}, "The maximum charge (e, absolute value) of a hydrophobic atom" }, { "-f_index", FALSE, etBOOL, {&bFindex}, "Determine from a group in the index file what are the hydrophobic atoms rather than from the charge" }, { "-minarea", FALSE, etREAL, {&minarea}, "The minimum area (nm^2) to count an atom as a surface atom when writing a position restraint file (see help)" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Take periodicity into account" }, { "-prot", FALSE, etBOOL, {&bSave}, "Output the protein to the Connelly [TT].pdb[tt] file too" }, { "-dgs", FALSE, etREAL, {&dgs_default}, "Default value for solvation free energy per area (kJ/mol/nm^2)" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, "-s", NULL, ffREAD }, { efXVG, "-o", "area", ffWRITE }, { efXVG, "-or", "resarea", ffOPTWR }, { efXVG, "-oa", "atomarea", ffOPTWR }, { efXVG, "-tv", "volume", ffOPTWR }, { efPDB, "-q", "connelly", ffOPTWR }, { efNDX, "-n", "index", ffOPTRD }, { efITP, "-i", "surfat", ffOPTWR } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); if (solsize < 0) { solsize=1e-3; fprintf(stderr,"Probe size too small, setting it to %g\n",solsize); } if (ndots < 20) { ndots = 20; fprintf(stderr,"Ndots too small, setting it to %d\n",ndots); } please_cite(stderr,"Eisenhaber95"); sas_plot(NFILE,fnm,solsize,ndots,qcut,bSave,minarea,bPBC,dgs_default,bFindex, oenv); do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn_null("-or",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn_null("-oa",NFILE,fnm),"-nxy"); thanx(stderr); return 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; }
int gmx_vanhove(int argc,char *argv[]) { const char *desc[] = { "g_vanhove computes the Van Hove correlation function.", "The Van Hove G(r,t) is the probability that a particle that is at r0", "at time zero can be found at position r0+r at time t.", "g_vanhove determines G not for a vector r, but for the length of r.", "Thus it gives the probability that a particle moves a distance of r", "in time t.", "Jumps across the periodic boundaries are removed.", "Corrections are made for scaling due to isotropic", "or anisotropic pressure coupling.", "[PAR]", "With option [TT]-om[tt] the whole matrix can be written as a function", "of t and r or as a function of sqrt(t) and r (option [TT]-sqrt[tt]).", "[PAR]", "With option [TT]-or[tt] the Van Hove function is plotted for one", "or more values of t. Option [TT]-nr[tt] sets the number of times,", "option [TT]-fr[tt] the number spacing between the times.", "The binwidth is set with option [TT]-rbin[tt]. The number of bins", "is determined automatically.", "[PAR]", "With option [TT]-ot[tt] the integral up to a certain distance", "(option [TT]-rt[tt]) is plotted as a function of time.", "[PAR]", "For all frames that are read the coordinates of the selected particles", "are stored in memory. Therefore the program may use a lot of memory.", "For options [TT]-om[tt] and [TT]-ot[tt] the program may be slow.", "This is because the calculation scales as the number of frames times", "[TT]-fm[tt] or [TT]-ft[tt].", "Note that with the [TT]-dt[tt] option the memory usage and calculation", "time can be reduced." }; static int fmmax=0,ftmax=0,nlev=81,nr=1,fshift=0; static real sbin=0,rmax=2,rbin=0.01,mmax=0,rint=0; t_pargs pa[] = { { "-sqrt", FALSE, etREAL,{&sbin}, "Use sqrt(t) on the matrix axis which binspacing # in sqrt(ps)" }, { "-fm", FALSE, etINT, {&fmmax}, "Number of frames in the matrix, 0 is plot all" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum r in the matrix (nm)" }, { "-rbin", FALSE, etREAL, {&rbin}, "Binwidth in the matrix and for -or (nm)" }, { "-mmax", FALSE, etREAL, {&mmax}, "Maximum density in the matrix, 0 is calculate (1/nm)" }, { "-nlevels" ,FALSE, etINT, {&nlev}, "Number of levels in the matrix" }, { "-nr", FALSE, etINT, {&nr}, "Number of curves for the -or output" }, { "-fr", FALSE, etINT, {&fshift}, "Frame spacing for the -or output" }, { "-rt", FALSE, etREAL, {&rint}, "Integration limit for the -ot output (nm)" }, { "-ft", FALSE, etINT, {&ftmax}, "Number of frames in the -ot output, 0 is plot all" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXPM, "-om", "vanhove", ffOPTWR }, { efXVG, "-or", "vanhove_r", ffOPTWR }, { efXVG, "-ot", "vanhove_t", ffOPTWR } }; #define NFILE asize(fnm) output_env_t oenv; const char *matfile,*otfile,*orfile; char title[256]; t_topology top; int ePBC; matrix boxtop,box,*sbox,avbox,corr; rvec *xtop,*x,**sx; int isize,nalloc,nallocn,natom; t_trxstatus *status; atom_id *index; char *grpname; int nfr,f,ff,i,m,mat_nx=0,nbin=0,bin,mbin,fbin; real *time,t,invbin=0,rmax2=0,rint2=0,d2; real invsbin=0,matmax,normfac,dt,*tickx,*ticky; char buf[STRLEN],**legend; real **mat=NULL; int *pt=NULL,**pr=NULL,*mcount=NULL,*tcount=NULL,*rcount=NULL; FILE *fp; t_rgb rlo={1,1,1}, rhi={0,0,0}; CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); matfile = opt2fn_null("-om",NFILE,fnm); if (opt2parg_bSet("-fr",NPA,pa)) orfile = opt2fn("-or",NFILE,fnm); else orfile = opt2fn_null("-or",NFILE,fnm); if (opt2parg_bSet("-rt",NPA,pa)) otfile = opt2fn("-ot",NFILE,fnm); else otfile = opt2fn_null("-ot",NFILE,fnm); if (!matfile && !otfile && !orfile) { fprintf(stderr, "For output set one (or more) of the output file options\n"); exit(0); } read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,boxtop, FALSE); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname); nalloc = 0; time = NULL; sbox = NULL; sx = NULL; clear_mat(avbox); natom=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); nfr = 0; do { if (nfr >= nalloc) { nalloc += 100; srenew(time,nalloc); srenew(sbox,nalloc); srenew(sx,nalloc); } time[nfr] = t; copy_mat(box,sbox[nfr]); /* This assumes that the off-diagonal box elements * are not affected by jumps across the periodic boundaries. */ m_add(avbox,box,avbox); snew(sx[nfr],isize); for(i=0; i<isize; i++) copy_rvec(x[index[i]],sx[nfr][i]); nfr++; } while (read_next_x(oenv,status,&t,natom,x,box)); /* clean up */ sfree(x); close_trj(status); fprintf(stderr,"Read %d frames\n",nfr); dt = (time[nfr-1] - time[0])/(nfr - 1); /* Some ugly rounding to get nice nice times in the output */ dt = (int)(10000.0*dt + 0.5)/10000.0; invbin = 1.0/rbin; if (matfile) { if (fmmax <= 0 || fmmax >= nfr) fmmax = nfr - 1; snew(mcount,fmmax); nbin = (int)(rmax*invbin + 0.5); if (sbin == 0) { mat_nx = fmmax + 1; } else { invsbin = 1.0/sbin; mat_nx = sqrt(fmmax*dt)*invsbin + 1; } snew(mat,mat_nx); for(f=0; f<mat_nx; f++) snew(mat[f],nbin); rmax2 = sqr(nbin*rbin); /* Initialize time zero */ mat[0][0] = nfr*isize; mcount[0] += nfr; } else { fmmax = 0; } if (orfile) { snew(pr,nr); nalloc = 0; snew(rcount,nr); } if (otfile) { if (ftmax <= 0) ftmax = nfr - 1; snew(tcount,ftmax); snew(pt,nfr); rint2 = rint*rint; /* Initialize time zero */ pt[0] = nfr*isize; tcount[0] += nfr; } else { ftmax = 0; } msmul(avbox,1.0/nfr,avbox); for(f=0; f<nfr; f++) { if (f % 100 == 0) fprintf(stderr,"\rProcessing frame %d",f); /* Scale all the configuration to the average box */ m_inv_ur0(sbox[f],corr); mmul_ur0(avbox,corr,corr); for(i=0; i<isize; i++) { mvmul_ur0(corr,sx[f][i],sx[f][i]); if (f > 0) { /* Correct for periodic jumps */ for(m=DIM-1; m>=0; m--) { while(sx[f][i][m] - sx[f-1][i][m] > 0.5*avbox[m][m]) rvec_dec(sx[f][i],avbox[m]); while(sx[f][i][m] - sx[f-1][i][m] <= -0.5*avbox[m][m]) rvec_inc(sx[f][i],avbox[m]); } } } for(ff=0; ff<f; ff++) { fbin = f - ff; if (fbin <= fmmax || fbin <= ftmax) { if (sbin == 0) mbin = fbin; else mbin = (int)(sqrt(fbin*dt)*invsbin + 0.5); for(i=0; i<isize; i++) { d2 = distance2(sx[f][i],sx[ff][i]); if (mbin < mat_nx && d2 < rmax2) { bin = (int)(sqrt(d2)*invbin + 0.5); if (bin < nbin) { mat[mbin][bin] += 1; } } if (fbin <= ftmax && d2 <= rint2) pt[fbin]++; } if (matfile) mcount[mbin]++; if (otfile) tcount[fbin]++; } } if (orfile) { for(fbin=0; fbin<nr; fbin++) { ff = f - (fbin + 1)*fshift; if (ff >= 0) { for(i=0; i<isize; i++) { d2 = distance2(sx[f][i],sx[ff][i]); bin = (int)(sqrt(d2)*invbin); if (bin >= nalloc) { nallocn = 10*(bin/10) + 11; for(m=0; m<nr; m++) { srenew(pr[m],nallocn); for(i=nalloc; i<nallocn; i++) pr[m][i] = 0; } nalloc = nallocn; } pr[fbin][bin]++; } rcount[fbin]++; } } } } fprintf(stderr,"\n"); if (matfile) { matmax = 0; for(f=0; f<mat_nx; f++) { normfac = 1.0/(mcount[f]*isize*rbin); for(i=0; i<nbin; i++) { mat[f][i] *= normfac; if (mat[f][i] > matmax && (f!=0 || i!=0)) matmax = mat[f][i]; } } fprintf(stdout,"Value at (0,0): %.3f, maximum of the rest %.3f\n", mat[0][0],matmax); if (mmax > 0) matmax = mmax; snew(tickx,mat_nx); for(f=0; f<mat_nx; f++) { if (sbin == 0) tickx[f] = f*dt; else tickx[f] = f*sbin; } snew(ticky,nbin+1); for(i=0; i<=nbin; i++) ticky[i] = i*rbin; fp = ffopen(matfile,"w"); write_xpm(fp,MAT_SPATIAL_Y,"Van Hove function","G (1/nm)", sbin==0 ? "time (ps)" : "sqrt(time) (ps^1/2)","r (nm)", mat_nx,nbin,tickx,ticky,mat,0,matmax,rlo,rhi,&nlev); ffclose(fp); } if (orfile) { fp = xvgropen(orfile,"Van Hove function","r (nm)","G (nm\\S-1\\N)",oenv); fprintf(fp,"@ subtitle \"for particles in group %s\"\n",grpname); snew(legend,nr); for(fbin=0; fbin<nr; fbin++) { sprintf(buf,"%g ps",(fbin + 1)*fshift*dt); legend[fbin] = strdup(buf); } xvgr_legend(fp,nr,(const char**)legend,oenv); for(i=0; i<nalloc; i++) { fprintf(fp,"%g",i*rbin); for(fbin=0; fbin<nr; fbin++) fprintf(fp," %g", (real)pr[fbin][i]/(rcount[fbin]*isize*rbin*(i==0 ? 0.5 : 1))); fprintf(fp,"\n"); } ffclose(fp); } if (otfile) { sprintf(buf,"Probability of moving less than %g nm",rint); fp = xvgropen(otfile,buf,"t (ps)","",oenv); fprintf(fp,"@ subtitle \"for particles in group %s\"\n",grpname); for(f=0; f<=ftmax; f++) fprintf(fp,"%g %g\n",f*dt,(real)pt[f]/(tcount[f]*isize)); ffclose(fp); } do_view(oenv, matfile,NULL); do_view(oenv, orfile,NULL); do_view(oenv, otfile,NULL); thanx(stderr); return 0; }
int gmx_sigeps(int argc, char *argv[]) { const char *desc[] = { "[TT]g_sigeps[tt] is a simple utility that converts C6/C12 or C6/Cn combinations", "to [GRK]sigma[grk] and [GRK]epsilon[grk], or vice versa. It can also plot the potential", "in file. In addition, it makes an approximation of a Buckingham potential", "to a Lennard-Jones potential." }; static real c6 = 1.0e-3, cn = 1.0e-6, qi = 0, qj = 0, sig = 0.3, eps = 1, sigfac = 0.7; static real Abh = 1e5, Bbh = 32, Cbh = 1e-3; static int npow = 12; t_pargs pa[] = { { "-c6", FALSE, etREAL, {&c6}, "C6" }, { "-cn", FALSE, etREAL, {&cn}, "Constant for repulsion" }, { "-pow", FALSE, etINT, {&npow}, "Power of the repulsion term" }, { "-sig", FALSE, etREAL, {&sig}, "[GRK]sigma[grk]" }, { "-eps", FALSE, etREAL, {&eps}, "[GRK]epsilon[grk]" }, { "-A", FALSE, etREAL, {&Abh}, "Buckingham A" }, { "-B", FALSE, etREAL, {&Bbh}, "Buckingham B" }, { "-C", FALSE, etREAL, {&Cbh}, "Buckingham C" }, { "-qi", FALSE, etREAL, {&qi}, "qi" }, { "-qj", FALSE, etREAL, {&qj}, "qj" }, { "-sigfac", FALSE, etREAL, {&sigfac}, "Factor in front of [GRK]sigma[grk] for starting the plot" } }; t_filenm fnm[] = { { efXVG, "-o", "potje", ffWRITE } }; output_env_t oenv; #define NFILE asize(fnm) const char *legend[] = { "Lennard-Jones", "Buckingham" }; FILE *fp; int i; gmx_bool bBham; real qq, x, oldx, minimum, mval, dp[2], pp[2]; int cur = 0; #define next (1-cur) parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv); bBham = (opt2parg_bSet("-A", asize(pa), pa) || opt2parg_bSet("-B", asize(pa), pa) || opt2parg_bSet("-C", asize(pa), pa)); if (bBham) { c6 = Cbh; sig = pow((6.0/npow)*pow(npow/Bbh, npow-6.0), 1.0/(npow-6.0)); eps = c6/(4*pow(sig, 6.0)); cn = 4*eps*pow(sig, npow); } else { if (opt2parg_bSet("-sig", asize(pa), pa) || opt2parg_bSet("-eps", asize(pa), pa)) { c6 = 4*eps*pow(sig, 6); cn = 4*eps*pow(sig, npow); } else if (opt2parg_bSet("-c6", asize(pa), pa) || opt2parg_bSet("-cn", asize(pa), pa) || opt2parg_bSet("-pow", asize(pa), pa)) { sig = pow(cn/c6, 1.0/(npow-6.0)); eps = 0.25*c6*pow(sig, -6.0); } else { sig = eps = 0; } printf("c6 = %12.5e, c%d = %12.5e\n", c6, npow, cn); printf("sigma = %12.5f, epsilon = %12.5f\n", sig, eps); minimum = pow(npow/6.0*pow(sig, npow-6.0), 1.0/(npow-6)); printf("Van der Waals minimum at %g, V = %g\n\n", minimum, pot(minimum, 0, c6, cn, npow)); printf("Fit of Lennard Jones (%d-6) to Buckingham:\n", npow); Bbh = npow/minimum; Cbh = c6; Abh = 4*eps*pow(sig/minimum, npow)*exp(npow); printf("A = %g, B = %g, C = %g\n", Abh, Bbh, Cbh); } qq = qi*qj; fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Potential", "r (nm)", "E (kJ/mol)", oenv); xvgr_legend(fp, asize(legend), legend, oenv); if (sig == 0) { sig = 0.25; } minimum = -1; mval = 0; oldx = 0; for (i = 0; (i < 100); i++) { x = sigfac*sig+sig*i*0.02; dp[next] = dpot(x, qq, c6, cn, npow); fprintf(fp, "%10g %10g %10g\n", x, pot(x, qq, c6, cn, npow), bhpot(x, Abh, Bbh, Cbh)); if (qq != 0) { if ((i > 0) && (dp[cur]*dp[next] < 0)) { minimum = oldx + dp[cur]*(x-oldx)/(dp[cur]-dp[next]); mval = pot(minimum, qq, c6, cn, npow); printf("Van der Waals + Coulomb minimum at r = %g (nm). Value = %g (kJ/mol)\n", minimum, mval); } } cur = next; oldx = x; } ffclose(fp); do_view(oenv, ftp2fn(efXVG, NFILE, fnm), NULL); return 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; }
static void process_tcaf(int nframes, real dt, int nkc, real **tc, rvec *kfac, real rho, real wt, const char *fn_trans, const char *fn_tca, const char *fn_tc, const char *fn_tcf, const char *fn_cub, const char *fn_vk, const gmx_output_env_t *oenv) { FILE *fp, *fp_vk, *fp_cub = NULL; int nk, ntc; real **tcaf, **tcafc = NULL, eta, *sig; int i, j, k, kc; int ncorr; double fitparms[3]; nk = kset_c[nkc]; ntc = nk*NPK; if (fn_trans) { fp = xvgropen(fn_trans, "Transverse Current", "Time (ps)", "TC (nm/ps)", oenv); for (i = 0; i < nframes; i++) { fprintf(fp, "%g", i*dt); for (j = 0; j < ntc; j++) { fprintf(fp, " %g", tc[j][i]); } fprintf(fp, "\n"); } xvgrclose(fp); do_view(oenv, fn_trans, "-nxy"); } ncorr = (nframes+1)/2; if (ncorr > static_cast<int>(5*wt/dt+0.5)) { ncorr = static_cast<int>(5*wt/dt+0.5)+1; } snew(tcaf, nk); for (k = 0; k < nk; k++) { snew(tcaf[k], ncorr); } if (fn_cub) { snew(tcafc, nkc); for (k = 0; k < nkc; k++) { snew(tcafc[k], ncorr); } } snew(sig, ncorr); for (i = 0; i < ncorr; i++) { sig[i] = std::exp(0.5*i*dt/wt); } low_do_autocorr(fn_tca, oenv, "Transverse Current Autocorrelation Functions", nframes, ntc, ncorr, tc, dt, eacNormal, 1, FALSE, FALSE, FALSE, 0, 0, 0); do_view(oenv, fn_tca, "-nxy"); fp = xvgropen(fn_tc, "Transverse Current Autocorrelation Functions", "Time (ps)", "TCAF", oenv); for (i = 0; i < ncorr; i++) { kc = 0; fprintf(fp, "%g", i*dt); for (k = 0; k < nk; k++) { for (j = 0; j < NPK; j++) { tcaf[k][i] += tc[NPK*k+j][i]; } if (fn_cub) { for (j = 0; j < NPK; j++) { tcafc[kc][i] += tc[NPK*k+j][i]; } } if (i == 0) { fprintf(fp, " %g", 1.0); } else { tcaf[k][i] /= tcaf[k][0]; fprintf(fp, " %g", tcaf[k][i]); } if (k+1 == kset_c[kc+1]) { kc++; } } fprintf(fp, "\n"); } xvgrclose(fp); do_view(oenv, fn_tc, "-nxy"); if (fn_cub) { fp_cub = xvgropen(fn_cub, "TCAFs and fits", "Time (ps)", "TCAF", oenv); for (kc = 0; kc < nkc; kc++) { fprintf(fp_cub, "%g %g\n", 0.0, 1.0); for (i = 1; i < ncorr; i++) { tcafc[kc][i] /= tcafc[kc][0]; fprintf(fp_cub, "%g %g\n", i*dt, tcafc[kc][i]); } fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); tcafc[kc][0] = 1.0; } } fp_vk = xvgropen(fn_vk, "Fits", "k (nm\\S-1\\N)", "\\8h\\4 (10\\S-3\\N kg m\\S-1\\N s\\S-1\\N)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp_vk, "@ s0 symbol 2\n"); fprintf(fp_vk, "@ s0 symbol color 1\n"); fprintf(fp_vk, "@ s0 linestyle 0\n"); if (fn_cub) { fprintf(fp_vk, "@ s1 symbol 3\n"); fprintf(fp_vk, "@ s1 symbol color 2\n"); } } fp = xvgropen(fn_tcf, "TCAF Fits", "Time (ps)", "", oenv); for (k = 0; k < nk; k++) { tcaf[k][0] = 1.0; fitparms[0] = 1; fitparms[1] = 1; do_lmfit(ncorr, tcaf[k], sig, dt, 0, 0, ncorr*dt, oenv, bDebugMode(), effnVAC, fitparms, 0, NULL); eta = 1000*fitparms[1]*rho/ (4*fitparms[0]*PICO*norm2(kfac[k])/(NANO*NANO)); fprintf(stdout, "k %6.3f tau %6.3f eta %8.5f 10^-3 kg/(m s)\n", norm(kfac[k]), fitparms[0], eta); fprintf(fp_vk, "%6.3f %g\n", norm(kfac[k]), eta); for (i = 0; i < ncorr; i++) { fprintf(fp, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt)); } fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } xvgrclose(fp); do_view(oenv, fn_tcf, "-nxy"); if (fn_cub) { fprintf(stdout, "Averaged over k-vectors:\n"); fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); for (k = 0; k < nkc; k++) { tcafc[k][0] = 1.0; fitparms[0] = 1; fitparms[1] = 1; do_lmfit(ncorr, tcafc[k], sig, dt, 0, 0, ncorr*dt, oenv, bDebugMode(), effnVAC, fitparms, 0, NULL); eta = 1000*fitparms[1]*rho/ (4*fitparms[0]*PICO*norm2(kfac[kset_c[k]])/(NANO*NANO)); fprintf(stdout, "k %6.3f tau %6.3f Omega %6.3f eta %8.5f 10^-3 kg/(m s)\n", norm(kfac[kset_c[k]]), fitparms[0], fitparms[1], eta); fprintf(fp_vk, "%6.3f %g\n", norm(kfac[kset_c[k]]), eta); for (i = 0; i < ncorr; i++) { fprintf(fp_cub, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt)); } fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); xvgrclose(fp_cub); do_view(oenv, fn_cub, "-nxy"); } xvgrclose(fp_vk); do_view(oenv, fn_vk, "-nxy"); }
int gmx_order(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the order parameter per atom for carbon tails. For atom i the", "vector i-1, i+1 is used together with an axis. ", "The index file should contain only the groups to be used for calculations,", "with each group of equivalent carbons along the relevant acyl chain in its own", "group. There should not be any generic groups (like System, Protein) in the index", "file to avoid confusing the program (this is not relevant to tetrahedral order", "parameters however, which only work for water anyway).[PAR]", "[THISMODULE] can also give all", "diagonal elements of the order tensor and even calculate the deuterium", "order parameter Scd (default). If the option [TT]-szonly[tt] is given, only one", "order tensor component (specified by the [TT]-d[tt] option) is given and the", "order parameter per slice is calculated as well. If [TT]-szonly[tt] is not", "selected, all diagonal elements and the deuterium order parameter is", "given.[PAR]" "The tetrahedrality order parameters can be determined", "around an atom. Both angle an distance order parameters are calculated. See", "P.-L. Chau and A.J. Hardwick, Mol. Phys., 93, (1998), 511-518.", "for more details." }; static int nslices = 1; /* nr of slices defined */ static gmx_bool bSzonly = FALSE; /* True if only Sz is wanted */ static gmx_bool bUnsat = FALSE; /* True if carbons are unsat. */ static const char *normal_axis[] = { NULL, "z", "x", "y", NULL }; static gmx_bool permolecule = FALSE; /*compute on a per-molecule basis */ static gmx_bool radial = FALSE; /*compute a radial membrane normal */ static gmx_bool distcalc = FALSE; /*calculate distance from a reference group */ t_pargs pa[] = { { "-d", FALSE, etENUM, {normal_axis}, "Direction of the normal on the membrane" }, { "-sl", FALSE, etINT, {&nslices}, "Calculate order parameter as function of box length, dividing the box" " into this number of slices." }, { "-szonly", FALSE, etBOOL, {&bSzonly}, "Only give Sz element of order tensor. (axis can be specified with [TT]-d[tt])" }, { "-unsat", FALSE, etBOOL, {&bUnsat}, "Calculate order parameters for unsaturated carbons. Note that this can" "not be mixed with normal order parameters." }, { "-permolecule", FALSE, etBOOL, {&permolecule}, "Compute per-molecule Scd order parameters" }, { "-radial", FALSE, etBOOL, {&radial}, "Compute a radial membrane normal" }, { "-calcdist", FALSE, etBOOL, {&distcalc}, "Compute distance from a reference" }, }; rvec *order; /* order par. for each atom */ real **slOrder; /* same, per slice */ real slWidth = 0.0; /* width of a slice */ char **grpname; /* groupnames */ int ngrps, /* nr. of groups */ i, axis = 0; /* normal axis */ t_topology *top; /* topology */ int ePBC; atom_id *index, /* indices for a */ *a; /* atom numbers in each group */ t_blocka *block; /* data from index file */ t_filenm fnm[] = { /* files for g_order */ { efTRX, "-f", NULL, ffREAD }, /* trajectory file */ { efNDX, "-n", NULL, ffREAD }, /* index file */ { efNDX, "-nr", NULL, ffREAD }, /* index for radial axis calculation */ { efTPR, NULL, NULL, ffREAD }, /* topology file */ { efXVG, "-o", "order", ffWRITE }, /* xvgr output file */ { efXVG, "-od", "deuter", ffWRITE }, /* xvgr output file */ { efPDB, "-ob", NULL, ffWRITE }, /* write Scd as B factors to PDB if permolecule */ { efXVG, "-os", "sliced", ffWRITE }, /* xvgr output file */ { efXVG, "-Sg", "sg-ang", ffOPTWR }, /* xvgr output file */ { efXVG, "-Sk", "sk-dist", ffOPTWR }, /* xvgr output file */ { efXVG, "-Sgsl", "sg-ang-slice", ffOPTWR }, /* xvgr output file */ { efXVG, "-Sksl", "sk-dist-slice", ffOPTWR }, /* xvgr output file */ }; gmx_bool bSliced = FALSE; /* True if box is sliced */ #define NFILE asize(fnm) real **distvals = NULL; const char *sgfnm, *skfnm, *ndxfnm, *tpsfnm, *trxfnm; gmx_output_env_t *oenv; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } if (nslices < 1) { gmx_fatal(FARGS, "Can not have nslices < 1"); } sgfnm = opt2fn_null("-Sg", NFILE, fnm); skfnm = opt2fn_null("-Sk", NFILE, fnm); ndxfnm = opt2fn_null("-n", NFILE, fnm); tpsfnm = ftp2fn(efTPR, NFILE, fnm); trxfnm = ftp2fn(efTRX, NFILE, fnm); /* Calculate axis */ GMX_RELEASE_ASSERT(normal_axis[0] != NULL, "Options inconsistency; normal_axis[0] is NULL"); if (std::strcmp(normal_axis[0], "x") == 0) { axis = XX; } else if (std::strcmp(normal_axis[0], "y") == 0) { axis = YY; } else if (std::strcmp(normal_axis[0], "z") == 0) { axis = ZZ; } else { gmx_fatal(FARGS, "Invalid axis, use x, y or z"); } switch (axis) { case 0: fprintf(stderr, "Taking x axis as normal to the membrane\n"); break; case 1: fprintf(stderr, "Taking y axis as normal to the membrane\n"); break; case 2: fprintf(stderr, "Taking z axis as normal to the membrane\n"); break; } /* tetraheder order parameter */ if (skfnm || sgfnm) { /* If either of theoptions is set we compute both */ sgfnm = opt2fn("-Sg", NFILE, fnm); skfnm = opt2fn("-Sk", NFILE, fnm); calc_tetra_order_parm(ndxfnm, tpsfnm, trxfnm, sgfnm, skfnm, nslices, axis, opt2fn("-Sgsl", NFILE, fnm), opt2fn("-Sksl", NFILE, fnm), oenv); /* view xvgr files */ do_view(oenv, opt2fn("-Sg", NFILE, fnm), NULL); do_view(oenv, opt2fn("-Sk", NFILE, fnm), NULL); if (nslices > 1) { do_view(oenv, opt2fn("-Sgsl", NFILE, fnm), NULL); do_view(oenv, opt2fn("-Sksl", NFILE, fnm), NULL); } } else { /* tail order parameter */ if (nslices > 1) { bSliced = TRUE; fprintf(stderr, "Dividing box in %d slices.\n\n", nslices); } if (bSzonly) { fprintf(stderr, "Only calculating Sz\n"); } if (bUnsat) { fprintf(stderr, "Taking carbons as unsaturated!\n"); } top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */ block = init_index(ftp2fn(efNDX, NFILE, fnm), &grpname); index = block->index; /* get indices from t_block block */ a = block->a; /* see block.h */ ngrps = block->nr; if (permolecule) { nslices = index[1] - index[0]; /*I think this assumes contiguous lipids in topology*/ fprintf(stderr, "Calculating Scd order parameters for each of %d molecules\n", nslices); } if (radial) { fprintf(stderr, "Calculating radial distances\n"); if (!permolecule) { gmx_fatal(FARGS, "Cannot yet output radial distances without permolecule\n"); } } /* show atomtypes, to check if index file is correct */ print_types(index, a, ngrps, grpname, top); calc_order(ftp2fn(efTRX, NFILE, fnm), index, a, &order, &slOrder, &slWidth, nslices, bSliced, bUnsat, top, ePBC, ngrps, axis, permolecule, radial, distcalc, opt2fn_null("-nr", NFILE, fnm), &distvals, oenv); if (radial) { ngrps--; /*don't print the last group--was used for center-of-mass determination*/ } order_plot(order, slOrder, opt2fn("-o", NFILE, fnm), opt2fn("-os", NFILE, fnm), opt2fn("-od", NFILE, fnm), ngrps, nslices, slWidth, bSzonly, permolecule, distvals, oenv); if (opt2bSet("-ob", NFILE, fnm)) { if (!permolecule) { fprintf(stderr, "Won't write B-factors with averaged order parameters; use -permolecule\n"); } else { write_bfactors(fnm, NFILE, index, a, nslices, ngrps, slOrder, top, distvals, oenv); } } do_view(oenv, opt2fn("-o", NFILE, fnm), NULL); /* view xvgr file */ do_view(oenv, opt2fn("-os", NFILE, fnm), NULL); /* view xvgr file */ do_view(oenv, opt2fn("-od", NFILE, fnm), NULL); /* view xvgr file */ } if (distvals != NULL) { for (i = 0; i < nslices; ++i) { sfree(distvals[i]); } sfree(distvals); } return 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_disre(int argc,char *argv[]) { const char *desc[] = { "g_disre computes violations of distance restraints.", "If necessary all protons can be added to a protein molecule ", "using the protonate program.[PAR]", "The program always", "computes the instantaneous violations rather than time-averaged,", "because this analysis is done from a trajectory file afterwards", "it does not make sense to use time averaging. However,", "the time averaged values per restraint are given in the log file.[PAR]", "An index file may be used to select specific restraints for", "printing.[PAR]", "When the optional[TT]-q[tt] flag is given a pdb file coloured by the", "amount of average violations.[PAR]", "When the [TT]-c[tt] option is given, an index file will be read", "containing the frames in your trajectory corresponding to the clusters", "(defined in another manner) that you want to analyze. For these clusters", "the program will compute average violations using the third power", "averaging algorithm and print them in the log file." }; static int ntop = 0; static int nlevels = 20; static real max_dr = 0; static gmx_bool bThird = TRUE; t_pargs pa[] = { { "-ntop", FALSE, etINT, {&ntop}, "Number of large violations that are stored in the log file every step" }, { "-maxdr", FALSE, etREAL, {&max_dr}, "Maximum distance violation in matrix output. If less than or equal to 0 the maximum will be determined by the data." }, { "-nlevels", FALSE, etINT, {&nlevels}, "Number of levels in the matrix output" }, { "-third", FALSE, etBOOL, {&bThird}, "Use inverse third power averaging or linear for matrix output" } }; FILE *out=NULL,*aver=NULL,*numv=NULL,*maxxv=NULL,*xvg=NULL; t_tpxheader header; t_inputrec ir; gmx_mtop_t mtop; rvec *xtop; gmx_localtop_t *top; t_atoms *atoms=NULL; t_forcerec *fr; t_fcdata fcd; t_nrnb nrnb; t_commrec *cr; t_graph *g; int ntopatoms,natoms,i,j,kkk; t_trxstatus *status; real t; rvec *x,*f,*xav=NULL; matrix box; gmx_bool bPDB; int isize; atom_id *index=NULL,*ind_fit=NULL; char *grpname; t_cluster_ndx *clust=NULL; t_dr_result dr,*dr_clust=NULL; char **leg; real *vvindex=NULL,*w_rls=NULL; t_mdatoms *mdatoms; t_pbc pbc,*pbc_null; int my_clust; FILE *fplog; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; t_filenm fnm[] = { { efTPX, NULL, NULL, ffREAD }, { efTRX, "-f", NULL, ffREAD }, { efXVG, "-ds", "drsum", ffWRITE }, { efXVG, "-da", "draver", ffWRITE }, { efXVG, "-dn", "drnum", ffWRITE }, { efXVG, "-dm", "drmax", ffWRITE }, { efXVG, "-dr", "restr", ffWRITE }, { efLOG, "-l", "disres", ffWRITE }, { efNDX, NULL, "viol", ffOPTRD }, { efPDB, "-q", "viol", ffOPTWR }, { efNDX, "-c", "clust", ffOPTRD }, { efXPM, "-x", "matrix", ffOPTWR } }; #define NFILE asize(fnm) cr = init_par(&argc,&argv); CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,FALSE,0,&fplog); if (ntop) init5(ntop); read_tpxheader(ftp2fn(efTPX,NFILE,fnm),&header,FALSE,NULL,NULL); snew(xtop,header.natoms); read_tpx(ftp2fn(efTPX,NFILE,fnm),&ir,box,&ntopatoms,xtop,NULL,NULL,&mtop); bPDB = opt2bSet("-q",NFILE,fnm); if (bPDB) { snew(xav,ntopatoms); snew(ind_fit,ntopatoms); snew(w_rls,ntopatoms); for(kkk=0; (kkk<ntopatoms); kkk++) { w_rls[kkk] = 1; ind_fit[kkk] = kkk; } snew(atoms,1); *atoms = gmx_mtop_global_atoms(&mtop); if (atoms->pdbinfo == NULL) { snew(atoms->pdbinfo,atoms->nr); } } top = gmx_mtop_generate_local_top(&mtop,&ir); g = NULL; pbc_null = NULL; if (ir.ePBC != epbcNONE) { if (ir.bPeriodicMols) pbc_null = &pbc; else g = mk_graph(fplog,&top->idef,0,mtop.natoms,FALSE,FALSE); } if (ftp2bSet(efNDX,NFILE,fnm)) { rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname); xvg=xvgropen(opt2fn("-dr",NFILE,fnm),"Inidividual Restraints","Time (ps)", "nm",oenv); snew(vvindex,isize); snew(leg,isize); for(i=0; (i<isize); i++) { index[i]++; snew(leg[i],12); sprintf(leg[i],"index %d",index[i]); } xvgr_legend(xvg,isize,(const char**)leg,oenv); } else isize=0; ir.dr_tau=0.0; init_disres(fplog,&mtop,&ir,NULL,FALSE,&fcd,NULL); natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); snew(f,5*natoms); init_dr_res(&dr,fcd.disres.nres); if (opt2bSet("-c",NFILE,fnm)) { clust = cluster_index(fplog,opt2fn("-c",NFILE,fnm)); snew(dr_clust,clust->clust->nr+1); for(i=0; (i<=clust->clust->nr); i++) init_dr_res(&dr_clust[i],fcd.disres.nres); } else { out =xvgropen(opt2fn("-ds",NFILE,fnm), "Sum of Violations","Time (ps)","nm",oenv); aver=xvgropen(opt2fn("-da",NFILE,fnm), "Average Violation","Time (ps)","nm",oenv); numv=xvgropen(opt2fn("-dn",NFILE,fnm), "# Violations","Time (ps)","#",oenv); maxxv=xvgropen(opt2fn("-dm",NFILE,fnm), "Largest Violation","Time (ps)","nm",oenv); } mdatoms = init_mdatoms(fplog,&mtop,ir.efep!=efepNO); atoms2md(&mtop,&ir,0,NULL,0,mtop.natoms,mdatoms); update_mdatoms(mdatoms,ir.init_lambda); fr = mk_forcerec(); fprintf(fplog,"Made forcerec\n"); init_forcerec(fplog,oenv,fr,NULL,&ir,&mtop,cr,box,FALSE,NULL,NULL,NULL, FALSE,-1); init_nrnb(&nrnb); if (ir.ePBC != epbcNONE) gpbc = gmx_rmpbc_init(&top->idef,ir.ePBC,natoms,box); j=0; do { if (ir.ePBC != epbcNONE) { if (ir.bPeriodicMols) set_pbc(&pbc,ir.ePBC,box); else gmx_rmpbc(gpbc,natoms,box,x); } if (clust) { if (j > clust->maxframe) gmx_fatal(FARGS,"There are more frames in the trajectory than in the cluster index file. t = %8f\n",t); my_clust = clust->inv_clust[j]; range_check(my_clust,0,clust->clust->nr); check_viol(fplog,cr,&(top->idef.il[F_DISRES]), top->idef.iparams,top->idef.functype, x,f,fr,pbc_null,g,dr_clust,my_clust,isize,index,vvindex,&fcd); } else check_viol(fplog,cr,&(top->idef.il[F_DISRES]), top->idef.iparams,top->idef.functype, x,f,fr,pbc_null,g,&dr,0,isize,index,vvindex,&fcd); if (bPDB) { reset_x(atoms->nr,ind_fit,atoms->nr,NULL,x,w_rls); do_fit(atoms->nr,w_rls,x,x); if (j == 0) { /* Store the first frame of the trajectory as 'characteristic' * for colouring with violations. */ for(kkk=0; (kkk<atoms->nr); kkk++) copy_rvec(x[kkk],xav[kkk]); } } if (!clust) { if (isize > 0) { fprintf(xvg,"%10g",t); for(i=0; (i<isize); i++) fprintf(xvg," %10g",vvindex[i]); fprintf(xvg,"\n"); } fprintf(out, "%10g %10g\n",t,dr.sumv); fprintf(aver, "%10g %10g\n",t,dr.averv); fprintf(maxxv,"%10g %10g\n",t,dr.maxv); fprintf(numv, "%10g %10d\n",t,dr.nv); } j++; } while (read_next_x(oenv,status,&t,natoms,x,box)); close_trj(status); if (ir.ePBC != epbcNONE) gmx_rmpbc_done(gpbc); if (clust) { dump_clust_stats(fplog,fcd.disres.nres,&(top->idef.il[F_DISRES]), top->idef.iparams,clust->clust,dr_clust, clust->grpname,isize,index); } else { dump_stats(fplog,j,fcd.disres.nres,&(top->idef.il[F_DISRES]), top->idef.iparams,&dr,isize,index, bPDB ? atoms : NULL); if (bPDB) { write_sto_conf(opt2fn("-q",NFILE,fnm), "Coloured by average violation in Angstrom", atoms,xav,NULL,ir.ePBC,box); } dump_disre_matrix(opt2fn_null("-x",NFILE,fnm),&dr,fcd.disres.nres, j,&top->idef,&mtop,max_dr,nlevels,bThird); ffclose(out); ffclose(aver); ffclose(numv); ffclose(maxxv); if (isize > 0) { ffclose(xvg); do_view(oenv,opt2fn("-dr",NFILE,fnm),"-nxy"); } do_view(oenv,opt2fn("-dn",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-da",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-ds",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-dm",NFILE,fnm),"-nxy"); } thanx(stderr); if (gmx_parallel_env_initialized()) gmx_finalize(); gmx_log_close(fplog); return 0; }
int gmx_dielectric(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] calculates frequency dependent dielectric constants", "from the autocorrelation function of the total dipole moment in", "your simulation. This ACF can be generated by [gmx-dipoles].", "The functional forms of the available functions are:[PAR]", "One parameter: y = [EXP]-a[SUB]1[sub] x[exp],[BR]", "Two parameters: y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp],[BR]", "Three parameters: y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp] + (1 - a[SUB]2[sub]) [EXP]-a[SUB]3[sub] x[exp].[BR]", "Start values for the fit procedure can be given on the command line.", "It is also possible to fix parameters at their start value, use [TT]-fix[tt]", "with the number of the parameter you want to fix.", "[PAR]", "Three output files are generated, the first contains the ACF,", "an exponential fit to it with 1, 2 or 3 parameters, and the", "numerical derivative of the combination data/fit.", "The second file contains the real and imaginary parts of the", "frequency-dependent dielectric constant, the last gives a plot", "known as the Cole-Cole plot, in which the imaginary", "component is plotted as a function of the real component.", "For a pure exponential relaxation (Debye relaxation) the latter", "plot should be one half of a circle." }; t_filenm fnm[] = { { efXVG, "-f", "dipcorr", ffREAD }, { efXVG, "-d", "deriv", ffWRITE }, { efXVG, "-o", "epsw", ffWRITE }, { efXVG, "-c", "cole", ffWRITE } }; #define NFILE asize(fnm) output_env_t oenv; int i, j, nx, ny, nxtail, eFitFn, nfitparm; real dt, integral, fitintegral, *fitparms, fac, rffac; double **yd; real **y; const char *legend[] = { "Correlation", "Std. Dev.", "Fit", "Combined", "Derivative" }; static int fix = 0, bFour = 0, bX = 1, nsmooth = 3; static real tendInt = 5.0, tbegin = 5.0, tend = 500.0; static real A = 0.5, tau1 = 10.0, tau2 = 1.0, eps0 = 80, epsRF = 78.5, tail = 500.0; real lambda; t_pargs pa[] = { { "-fft", FALSE, etBOOL, {&bFour}, "use fast fourier transform for correlation function" }, { "-x1", FALSE, etBOOL, {&bX}, "use first column as [IT]x[it]-axis rather than first data set" }, { "-eint", FALSE, etREAL, {&tendInt}, "Time to end the integration of the data and start to use the fit"}, { "-bfit", FALSE, etREAL, {&tbegin}, "Begin time of fit" }, { "-efit", FALSE, etREAL, {&tend}, "End time of fit" }, { "-tail", FALSE, etREAL, {&tail}, "Length of function including data and tail from fit" }, { "-A", FALSE, etREAL, {&A}, "Start value for fit parameter A" }, { "-tau1", FALSE, etREAL, {&tau1}, "Start value for fit parameter [GRK]tau[grk]1" }, { "-tau2", FALSE, etREAL, {&tau2}, "Start value for fit parameter [GRK]tau[grk]2" }, { "-eps0", FALSE, etREAL, {&eps0}, "[GRK]epsilon[grk]0 of your liquid" }, { "-epsRF", FALSE, etREAL, {&epsRF}, "[GRK]epsilon[grk] of the reaction field used in your simulation. A value of 0 means infinity." }, { "-fix", FALSE, etINT, {&fix}, "Fix parameters at their start values, A (2), tau1 (1), or tau2 (4)" }, { "-ffn", FALSE, etENUM, {s_ffn}, "Fit function" }, { "-nsmooth", FALSE, etINT, {&nsmooth}, "Number of points for smoothing" } }; if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } please_cite(stdout, "Spoel98a"); printf("WARNING: non-polarizable models can never yield an infinite\n" "dielectric constant that is different from 1. This is incorrect\n" "in the reference given above (Spoel98a).\n\n"); nx = read_xvg(opt2fn("-f", NFILE, fnm), &yd, &ny); dt = yd[0][1] - yd[0][0]; nxtail = min(tail/dt, nx); printf("Read data set containing %d colums and %d rows\n", ny, nx); printf("Assuming (from data) that timestep is %g, nxtail = %d\n", dt, nxtail); snew(y, 6); for (i = 0; (i < ny); i++) { snew(y[i], max(nx, nxtail)); } for (i = 0; (i < nx); i++) { y[0][i] = yd[0][i]; for (j = 1; (j < ny); j++) { y[j][i] = yd[j][i]; } } if (nxtail > nx) { for (i = nx; (i < nxtail); i++) { y[0][i] = dt*i+y[0][0]; for (j = 1; (j < ny); j++) { y[j][i] = 0.0; } } nx = nxtail; } /* We have read a file WITHOUT standard deviations, so we make our own... */ if (ny == 2) { printf("Creating standard deviation numbers ...\n"); srenew(y, 3); snew(y[2], nx); fac = 1.0/((real)nx); for (i = 0; (i < nx); i++) { y[2][i] = fac; } } eFitFn = sffn2effn(s_ffn); nfitparm = nfp_ffn[eFitFn]; snew(fitparms, 4); fitparms[0] = tau1; if (nfitparm > 1) { fitparms[1] = A; } if (nfitparm > 2) { fitparms[2] = tau2; } snew(y[3], nx); snew(y[4], nx); snew(y[5], nx); integral = print_and_integrate(NULL, calc_nbegin(nx, y[0], tbegin), dt, y[1], NULL, 1); integral += do_lmfit(nx, y[1], y[2], dt, y[0], tbegin, tend, oenv, TRUE, eFitFn, fitparms, fix); for (i = 0; i < nx; i++) { y[3][i] = fit_function(eFitFn, fitparms, y[0][i]); } if (epsRF == 0) { /* This means infinity! */ lambda = 0; rffac = 1; } else { lambda = (eps0 - 1.0)/(2*epsRF - 1.0); rffac = (2*epsRF+eps0)/(2*epsRF+1); } printf("DATA INTEGRAL: %5.1f, tauD(old) = %5.1f ps, " "tau_slope = %5.1f, tau_slope,D = %5.1f ps\n", integral, integral*rffac, fitparms[0], fitparms[0]*rffac); printf("tau_D from tau1 = %8.3g , eps(Infty) = %8.3f\n", fitparms[0]*(1 + fitparms[1]*lambda), 1 + ((1 - fitparms[1])*(eps0 - 1))/(1 + fitparms[1]*lambda)); fitintegral = numerical_deriv(nx, y[0], y[1], y[3], y[4], y[5], tendInt, nsmooth); printf("FIT INTEGRAL (tau_M): %5.1f, tau_D = %5.1f\n", fitintegral, fitintegral*rffac); /* Now we have the negative gradient of <Phi(0) Phi(t)> */ write_xvg(opt2fn("-d", NFILE, fnm), "Data", nx-1, 6, y, legend, oenv); /* Do FFT and analysis */ do_four(opt2fn("-o", NFILE, fnm), opt2fn("-c", NFILE, fnm), nx-1, y[0], y[5], eps0, epsRF, oenv); do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); do_view(oenv, opt2fn("-c", NFILE, fnm), NULL); do_view(oenv, opt2fn("-d", NFILE, fnm), "-nxy"); return 0; }
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; }
int gmx_lie(int argc,char *argv[]) { const char *desc[] = { "g_lie computes a free energy estimate based on an energy analysis", "from. One needs an energy file with the following components:", "Coul (A-B) LJ-SR (A-B) etc." }; static real lie_lj=0,lie_qq=0,fac_lj=0.181,fac_qq=0.5; static const char *ligand="none"; t_pargs pa[] = { { "-Elj", FALSE, etREAL, {&lie_lj}, "Lennard-Jones interaction between ligand and solvent" }, { "-Eqq", FALSE, etREAL, {&lie_qq}, "Coulomb interaction between ligand and solvent" }, { "-Clj", FALSE, etREAL, {&fac_lj}, "Factor in the LIE equation for Lennard-Jones component of energy" }, { "-Cqq", FALSE, etREAL, {&fac_qq}, "Factor in the LIE equation for Coulomb component of energy" }, { "-ligand", FALSE, etSTR, {&ligand}, "Name of the ligand in the energy file" } }; #define NPA asize(pa) FILE *out; int nre,nframes=0,ct=0; ener_file_t fp; gmx_bool bCont; t_liedata *ld; gmx_enxnm_t *enm=NULL; t_enxframe *fr; real lie; double lieaver=0,lieav2=0; output_env_t oenv; t_filenm fnm[] = { { efEDR, "-f", "ener", ffREAD }, { efXVG, "-o", "lie", ffWRITE } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv); fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r"); do_enxnms(fp,&nre,&enm); ld = analyze_names(nre,enm,ligand); snew(fr,1); out = xvgropen(ftp2fn(efXVG,NFILE,fnm),"LIE free energy estimate", "Time (ps)","DGbind (kJ/mol)",oenv); do { bCont = do_enx(fp,fr); ct = check_times(fr->t); if (ct == 0) { lie = calc_lie(ld,fr->ener,lie_lj,lie_qq,fac_lj,fac_qq); lieaver += lie; lieav2 += lie*lie; nframes ++; fprintf(out,"%10g %10g\n",fr->t,lie); } } while (bCont); close_enx(fp); ffclose(out); fprintf(stderr,"\n"); if (nframes > 0) printf("DGbind = %.3f (%.3f)\n",lieaver/nframes, sqrt(lieav2/nframes-sqr(lieaver/nframes))); do_view(oenv,ftp2fn(efXVG,NFILE,fnm),"-nxy"); thanx(stderr); return 0; }
int gmx_sgangle(int argc,char *argv[]) { static char *desc[] = { "Compute the angle and distance between two groups. ", "The groups are defined by a number of atoms given in an index file and", "may be two or three atoms in size.", "If -one is set, only one group should be specified in the index", "file and the angle between this group at time 0 and t will be computed.", "The angles calculated depend on the order in which the atoms are ", "given. Giving for instance 5 6 will rotate the vector 5-6 with ", "180 degrees compared to giving 6 5. [PAR]If three atoms are given, ", "the normal on the plane spanned by those three atoms will be", "calculated, using the formula P1P2 x P1P3.", "The cos of the angle is calculated, using the inproduct of the two", "normalized vectors.[PAR]", "Here is what some of the file options do:[BR]", "-oa: Angle between the two groups specified in the index file. If a group contains three atoms the normal to the plane defined by those three atoms will be used. If a group contains two atoms, the vector defined by those two atoms will be used.[BR]", "-od: Distance between two groups. Distance is taken from the center of one group to the center of the other group.[BR]", "-od1: If one plane and one vector is given, the distances for each of the atoms from the center of the plane is given seperately.[BR]", "-od2: For two planes this option has no meaning." }; char *fna, *fnd, *fnd1, *fnd2; char *grpname[2]; /* name of the two groups */ int gnx[2]; /* size of the two groups */ t_topology *top; /* topology */ int ePBC; atom_id *index[2]; static bool bOne = FALSE, bZ=FALSE; t_pargs pa[] = { { "-one", FALSE, etBOOL, {&bOne}, "Only one group compute angle between vector at time zero and time t"}, { "-z", FALSE, etBOOL, {&bZ}, "Use the Z-axis as reference" } }; #define NPA asize(pa) t_filenm fnm[] = { /* files for g_sgangle */ { efTRX, "-f", NULL, ffREAD }, /* trajectory file */ { efNDX, NULL, NULL, ffREAD }, /* index file */ { efTPX, NULL, NULL, ffREAD }, /* topology file */ { efXVG,"-oa","sg_angle",ffWRITE }, /* xvgr output file */ { efXVG, "-od","sg_dist",ffOPTWR }, /* xvgr output file */ { efXVG, "-od1", "sg_dist1",ffOPTWR }, /* xvgr output file */ { efXVG, "-od2", "sg_dist2",ffOPTWR } /* xvgr output file */ }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL); top = read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC); /* read topology file */ fna = opt2fn("-oa",NFILE,fnm); fnd = opt2fn_null("-od",NFILE,fnm); fnd1 = opt2fn_null("-od1",NFILE,fnm); fnd2 = opt2fn_null("-od2",NFILE,fnm); /* read index file. */ if(bOne) { rd_index(ftp2fn(efNDX,NFILE,fnm),1,gnx,index,grpname); print_types(index[0],gnx[0],grpname[0], index[0],gnx[0],grpname[0],top); sgangle_plot_single(ftp2fn(efTRX,NFILE,fnm), fna, fnd, fnd1, fnd2, index[0],gnx[0],grpname[0], index[0],gnx[0],grpname[0], top,ePBC); } else { rd_index(ftp2fn(efNDX,NFILE,fnm),bZ ? 1 : 2,gnx,index,grpname); if (!bZ) print_types(index[0],gnx[0],grpname[0], index[1],gnx[1],grpname[1],top); else { gnx[1] = 0; grpname[1] = "Z-axis"; } sgangle_plot(ftp2fn(efTRX,NFILE,fnm), fna, fnd, fnd1, fnd2, index[0],gnx[0],grpname[0], index[1],gnx[1],grpname[1], top,ePBC); } do_view(fna,"-nxy"); /* view xvgr file */ do_view(fnd,"-nxy"); /* view xvgr file */ do_view(fnd1,"-nxy"); /* view xvgr file */ do_view(fnd2,"-nxy"); /* view xvgr file */ thanx(stderr); return 0; }