int gmx_sorient(int argc,char *argv[]) { t_topology top; int ePBC; char title[STRLEN]; int status; int natoms; real t; rvec *xtop,*x; matrix box; FILE *fp; int i,j,p,sa0,sa1,sa2,n,ntot,nf,m,*hist1,*hist2,*histn,nbin1,nbin2,nrbin; real *histi1,*histi2,invbw,invrbw; double sum1,sum2; int *isize,nrefgrp,nrefat; atom_id **index; char **grpname; real inp,outp,two_pi,nav,normfac,rmin2,rmax2,rcut,rcut2,r2,r,mass,mtot; real c1,c2; char str[STRLEN]; bool bTPS; rvec xref,dx,dxh1,dxh2,outer; t_pbc pbc; char *legr[] = { "<cos(\\8q\\4\\s1\\N)>", "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" }; char *legc[] = { "cos(\\8q\\4\\s1\\N)", "3cos\\S2\\N(\\8q\\4\\s2\\N)-1" }; static char *desc[] = { "g_sorient analyzes solvent orientation around solutes.", "It calculates two angles between the vector from one or more", "reference positions to the first atom of each solvent molecule:[BR]" "theta1: the angle with the vector from the first atom of the solvent", "molecule to the midpoint between atoms 2 and 3.[BR]", "theta2: the angle with the normal of the solvent plane, defined by the", "same three atoms, or when the option [TT]-v23[tt] is set", "the angle with the vector between atoms 2 and 3.[BR]", "The reference can be a set of atoms or", "the center of mass of a set of atoms. The group of solvent atoms should", "consist of 3 atoms per solvent molecule.", "Only solvent molecules between [TT]-rmin[tt] and [TT]-rmax[tt] are", "considered for [TT]-o[tt] and [TT]-no[tt] each frame.[PAR]", "[TT]-o[tt]: distribtion of cos(theta1) for rmin<=r<=rmax.[PAR]", "[TT]-no[tt]: distribution of cos(theta2) for rmin<=r<=rmax.[PAR]", "[TT]-ro[tt]: <cos(theta1)> and <3cos^2(theta2)-1> as a function of the", "distance.[PAR]", "[TT]-co[tt]: the sum over all solvent molecules within distance r", "of cos(theta1) and 3cos^2(theta2)-1 as a function of r.[PAR]", "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r" }; static bool bCom = FALSE,bVec23=FALSE,bPBC = FALSE; static real rmin=0.0,rmax=0.5,binwidth=0.02,rbinw=0.02; t_pargs pa[] = { { "-com", FALSE, etBOOL, {&bCom}, "Use the center of mass as the reference postion" }, { "-v23", FALSE, etBOOL, {&bVec23}, "Use the vector between atoms 2 and 3" }, { "-rmin", FALSE, etREAL, {&rmin}, "Minimum distance (nm)" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum distance (nm)" }, { "-cbin", FALSE, etREAL, {&binwidth}, "Binwidth for the cosine" }, { "-rbin", FALSE, etREAL, {&rbinw}, "Binwidth for r (nm)" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Check PBC for the center of mass calculation. Only necessary when your reference group consists of several molecules." } }; t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "sori.xvg", ffWRITE }, { efXVG, "-no", "snor.xvg", ffWRITE }, { efXVG, "-ro", "sord.xvg", ffWRITE }, { efXVG, "-co", "scum.xvg", ffWRITE }, { efXVG, "-rc", "scount.xvg", ffWRITE } }; #define NFILE asize(fnm) 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); two_pi = 2/M_PI; bTPS = (opt2bSet("-s",NFILE,fnm) || !opt2bSet("-n",NFILE,fnm) || bCom); if (bTPS) { read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box, bCom); } /* get index groups */ printf("Select a group of reference particles and a solvent group:\n"); snew(grpname,2); snew(index,2); snew(isize,2); if (bTPS) { get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),2,isize,index,grpname); } else { get_index(NULL,ftp2fn(efNDX,NFILE,fnm),2,isize,index,grpname); } if (bCom) { nrefgrp = 1; nrefat = isize[0]; } else { nrefgrp = isize[0]; nrefat = 1; } if (isize[1] % 3) gmx_fatal(FARGS,"The number of solvent atoms (%d) is not a multiple of 3", isize[1]); /* initialize reading trajectory: */ natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); rmin2 = sqr(rmin); rmax2 = sqr(rmax); rcut = 0.99*sqrt(max_cutoff2(guess_ePBC(box),box)); if (rcut == 0) rcut = 10*rmax; rcut2 = sqr(rcut); invbw = 1/binwidth; nbin1 = (int)(2*invbw + 0.5); nbin2 = (int)(invbw + 0.5); invrbw = 1/rbinw; snew(hist1,nbin1+1); snew(hist2,nbin2+1); nrbin = rcut/rbinw; if (nrbin == 0) nrbin = 1; snew(histi1,nrbin); snew(histi2,nrbin); snew(histn,nrbin); ntot = 0; nf = 0; sum1 = 0; sum2 = 0; /* start analysis of trajectory */ do { if (bTPS) { /* make molecules whole again */ rm_pbc(&top.idef,ePBC,natoms,box,x,x); } set_pbc(&pbc,ePBC,box); n = 0; inp = 0; outp = 0; for(p=0; (p<nrefgrp); p++) { if (bCom) calc_com_pbc(nrefat,&top,x,&pbc,index[0],xref,bPBC,box); else copy_rvec(x[index[0][p]],xref); for(m=0; m<isize[1]; m+=3) { sa0 = index[1][m]; sa1 = index[1][m+1]; sa2 = index[1][m+2]; pbc_dx(&pbc,x[sa0],xref,dx); r2 = norm2(dx); if (r2 < rcut2) { r = sqrt(r2); if (!bVec23) { /* Determine the normal to the plain */ rvec_sub(x[sa1],x[sa0],dxh1); rvec_sub(x[sa2],x[sa0],dxh2); rvec_inc(dxh1,dxh2); svmul(1/r,dx,dx); unitv(dxh1,dxh1); inp = iprod(dx,dxh1); cprod(dxh1,dxh2,outer); unitv(outer,outer); outp = iprod(dx,outer); } else { /* Use the vector between the 2nd and 3rd atom */ rvec_sub(x[sa2],x[sa1],dxh2); unitv(dxh2,dxh2); outp = iprod(dx,dxh2)/r; } (histi1[(int)(invrbw*r)]) += inp; (histi2[(int)(invrbw*r)]) += 3*sqr(outp) - 1; (histn[(int)(invrbw*r)])++; if (r2>=rmin2 && r2<rmax2) { (hist1[(int)(invbw*(inp + 1))])++; (hist2[(int)(invbw*fabs(outp))])++; sum1 += inp; sum2 += outp; n++; } } } } ntot += n; nf++; } while (read_next_x(status,&t,natoms,x,box)); /* clean up */ sfree(x); close_trj(status); /* Add the bin for the exact maximum to the previous bin */ hist1[nbin1-1] += hist1[nbin1]; hist2[nbin2-1] += hist2[nbin2]; nav = (real)ntot/(nrefgrp*nf); normfac = invbw/ntot; fprintf(stderr, "Average nr of molecules between %g and %g nm: %.1f\n", rmin,rmax,nav); if (ntot > 0) { sum1 /= ntot; sum2 /= ntot; fprintf(stderr,"Average cos(theta1) between %g and %g nm: %6.3f\n", rmin,rmax,sum1); fprintf(stderr,"Average 3cos2(theta2)-1 between %g and %g nm: %6.3f\n", rmin,rmax,sum2); } sprintf(str,"Solvent orientation between %g and %g nm",rmin,rmax); fp=xvgropen(opt2fn("-o",NFILE,fnm), str,"cos(\\8q\\4\\s1\\N)",""); if (bPrintXvgrCodes()) fprintf(fp,"@ subtitle \"average shell size %.1f molecules\"\n",nav); for(i=0; i<nbin1; i++) { fprintf(fp,"%g %g\n",(i+0.5)*binwidth-1,2*normfac*hist1[i]); } fclose(fp); sprintf(str,"Solvent normal orientation between %g and %g nm",rmin,rmax); fp=xvgropen(opt2fn("-no",NFILE,fnm), str,"cos(\\8q\\4\\s2\\N)",""); if (bPrintXvgrCodes()) fprintf(fp,"@ subtitle \"average shell size %.1f molecules\"\n",nav); for(i=0; i<nbin2; i++) { fprintf(fp,"%g %g\n",(i+0.5)*binwidth,normfac*hist2[i]); } fclose(fp); sprintf(str,"Solvent orientation"); fp=xvgropen(opt2fn("-ro",NFILE,fnm),str,"r (nm)",""); if (bPrintXvgrCodes()) fprintf(fp,"@ subtitle \"as a function of distance\"\n"); xvgr_legend(fp,2,legr); for(i=0; i<nrbin; i++) fprintf(fp,"%g %g %g\n",(i+0.5)*rbinw, histn[i] ? histi1[i]/histn[i] : 0, histn[i] ? histi2[i]/histn[i] : 0); fclose(fp); sprintf(str,"Cumulative solvent orientation"); fp=xvgropen(opt2fn("-co",NFILE,fnm),str,"r (nm)",""); if (bPrintXvgrCodes()) fprintf(fp,"@ subtitle \"as a function of distance\"\n"); xvgr_legend(fp,2,legc); normfac = 1.0/(nrefgrp*nf); c1 = 0; c2 = 0; fprintf(fp,"%g %g %g\n",0.0,c1,c2); for(i=0; i<nrbin; i++) { c1 += histi1[i]*normfac; c2 += histi2[i]*normfac; fprintf(fp,"%g %g %g\n",(i+1)*rbinw,c1,c2); } fclose(fp); sprintf(str,"Solvent distribution"); fp=xvgropen(opt2fn("-rc",NFILE,fnm),str,"r (nm)","molecules/nm"); if (bPrintXvgrCodes()) fprintf(fp,"@ subtitle \"as a function of distance\"\n"); normfac = 1.0/(rbinw*nf); for(i=0; i<nrbin; i++) { fprintf(fp,"%g %g\n",(i+0.5)*rbinw,histn[i]*normfac); } fclose(fp); do_view(opt2fn("-o",NFILE,fnm),NULL); do_view(opt2fn("-no",NFILE,fnm),NULL); do_view(opt2fn("-ro",NFILE,fnm),"-nxy"); do_view(opt2fn("-co",NFILE,fnm),"-nxy"); thanx(stderr); return 0; }
int main(int argc,char *argv[]) { static char *desc[] = { "[TT]do_shift[tt] reads a trajectory file and computes the chemical", "shift for each time frame (or every [BB]dt[bb] ps) by", "calling the 'total' program. If you do not have the total program,", "get it. do_shift assumes that the total executable is in", "[TT]/home/mdgroup/total/total[tt]. If that is not the case, then you should", "set an environment variable [BB]GMX_TOTAL[bb] as in: [PAR]", "[TT]setenv GMX_TOTAL /usr/local/bin/total[tt][PAR]", "where the right hand side should point to the total executable.[PAR]", "Output is printed in files [TT]shift.out[tt] where t is the time of the frame.[PAR]", "The program also needs an input file called [BB]random.dat[bb] which", "contains the random coil chemical shifts of all protons." }; static real dt=0.0; t_pargs pa[] = { { "-dt", FALSE, etREAL, { &dt }, "Time interval between frames." } }; static char *bugs[] = { "The program is very slow" }; static char *OXYGEN="O"; FILE *out,*tot,*fp; t_topology *top; t_atoms *atoms; int status,nres; real t,nt; int i,natoms,nframe=0; matrix box; int gnx; char *grpnm,*randf; atom_id *index; rvec *x,*x_s; char pdbfile[32],tmpfile[32]; char total[256],*dptr; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPX, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffREAD }, { efOUT, "-o", "shift", ffWRITE }, { efDAT, "-d", "random", ffREAD } }; char *leg[] = { "shift","ring","anisCO","anisCN","sigmaE","sum" }; #define NFILE asize(fnm) CopyRight(stdout,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME,NFILE,fnm, asize(pa),pa,asize(desc),desc,asize(bugs),bugs); top=read_top(ftp2fn(efTPX,NFILE,fnm)); atoms=&(top->atoms); nres=atoms->nres; for(i=0; (i<atoms->nr); i++) if ((strcmp(*atoms->atomname[i],"O1") == 0) || (strcmp(*atoms->atomname[i],"O2") == 0) || (strcmp(*atoms->atomname[i],"OXT") == 0) || (strcmp(*atoms->atomname[i],"OT") == 0)) atoms->atomname[i]=&OXYGEN; rd_index(ftp2fn(efNDX,NFILE,fnm),1,&gnx,&index,&grpnm); snew(x_s,atoms->nr); strcpy(pdbfile,"dsXXXXXX"); gmx_tmpnam(pdbfile); strcpy(tmpfile,"dsXXXXXX"); gmx_tmpnam(tmpfile); fprintf(stderr,"pdbfile = %s\ntmpfile = %s\n",pdbfile,tmpfile); if ((dptr=getenv("GMX_TOTAL")) == NULL) dptr="/home/mdgroup/total/total"; sprintf(total,"%s > /dev/null",dptr); fprintf(stderr,"total cmd='%s'\n",total); randf=ftp2fn(efDAT,NFILE,fnm); natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (natoms != atoms->nr) gmx_fatal(FARGS,"Trajectory does not match topology!"); out=ftp2FILE(efOUT,NFILE,fnm,"w"); xvgr_legend(out,asize(leg),leg); nt=t; do { if (t >= nt) { rm_pbc(&(top->idef),top->atoms.nr,box,x,x_s); fp=gmx_ffopen(pdbfile,"w"); write_pdbfile_indexed(fp,"Generated by do_shift", atoms,x_s,box,0,-1,gnx,index); gmx_ffclose(fp); if ((tot=popen(total,"w")) == NULL) perror("opening pipe to total"); fprintf(tot,"%s\n",pdbfile); fprintf(tot,"%s\n",tmpfile); fprintf(tot,"3\n"); fprintf(tot,"N\n"); fprintf(tot,"%s\n",randf); fprintf(tot,"N\n"); fprintf(tot,"N\n"); if (pclose(tot) != 0) perror("closing pipe to total"); cat(out,tmpfile,t); remove(pdbfile); remove(tmpfile); nt+=dt; nframe++; } } while(read_next_x(status,&t,natoms,x,box)); close_trx(status); gmx_ffclose(out); gmx_thanx(stderr); return 0; }
int gmx_mdmat(int argc,char *argv[]) { const char *desc[] = { "g_mdmat makes distance matrices consisting of the smallest distance", "between residue pairs. With -frames these distance matrices can be", "stored as a function", "of time, to be able to see differences in tertiary structure as a", "funcion of time. If you choose your options unwise, this may generate", "a large output file. Default only an averaged matrix over the whole", "trajectory is output.", "Also a count of the number of different atomic contacts between", "residues over the whole trajectory can be made.", "The output can be processed with xpm2ps to make a PostScript (tm) plot." }; static real truncate=1.5; static gmx_bool bAtom=FALSE; static int nlevels=40; t_pargs pa[] = { { "-t", FALSE, etREAL, {&truncate}, "trunc distance" }, { "-nlevels", FALSE, etINT, {&nlevels}, "Discretize distance in # levels" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXPM, "-mean", "dm", ffWRITE }, { efXPM, "-frames", "dmf", ffOPTWR }, { efXVG, "-no", "num",ffOPTWR }, }; #define NFILE asize(fnm) FILE *out=NULL,*fp; t_topology top; int ePBC; t_atoms useatoms; int isize; atom_id *index; char *grpname; int *rndx,*natm,prevres,newres; int i,j,nres,natoms,nframes,it,trxnat; t_trxstatus *status; int nr0; gmx_bool bCalcN,bFrames; real t,ratio; char title[256],label[234]; t_rgb rlo,rhi; rvec *x; real **mdmat,*resnr,**totmdmat; int **nmat,**totnmat; real *mean_n; int *tot_n; matrix box; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm, asize(pa),pa,asize(desc),desc,0,NULL,&oenv); fprintf(stderr,"Will truncate at %f nm\n",truncate); bCalcN = opt2bSet("-no",NFILE,fnm); bFrames= opt2bSet("-frames",NFILE,fnm); if ( bCalcN ) fprintf(stderr,"Will calculate number of different contacts\n"); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,FALSE); fprintf(stderr,"Select group for analysis\n"); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname); natoms=isize; snew(useatoms.atom,natoms); snew(useatoms.atomname,natoms); useatoms.nres = 0; snew(useatoms.resinfo,natoms); prevres = top.atoms.atom[index[0]].resind; newres = 0; for(i=0;(i<isize);i++) { int ii = index[i]; useatoms.atomname[i]=top.atoms.atomname[ii]; if (top.atoms.atom[ii].resind != prevres) { prevres = top.atoms.atom[ii].resind; newres++; useatoms.resinfo[i] = top.atoms.resinfo[prevres]; if (debug) { fprintf(debug,"New residue: atom %5s %5s %6d, index entry %5d, newres %5d\n", *(top.atoms.resinfo[top.atoms.atom[ii].resind].name), *(top.atoms.atomname[ii]), ii,i,newres); } } useatoms.atom[i].resind = newres; } useatoms.nres = newres+1; useatoms.nr = isize; rndx=res_ndx(&(useatoms)); natm=res_natm(&(useatoms)); nres=useatoms.nres; fprintf(stderr,"There are %d residues with %d atoms\n",nres,natoms); snew(resnr,nres); snew(mdmat,nres); snew(nmat,nres); snew(totnmat,nres); snew(mean_n,nres); snew(tot_n,nres); for(i=0; (i<nres); i++) { snew(mdmat[i],nres); snew(nmat[i],natoms); snew(totnmat[i],natoms); resnr[i]=i+1; } snew(totmdmat,nres); for(i=0; (i<nres); i++) snew(totmdmat[i],nres); trxnat=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); nframes=0; rlo.r=1.0, rlo.g=1.0, rlo.b=1.0; rhi.r=0.0, rhi.g=0.0, rhi.b=0.0; gpbc = gmx_rmpbc_init(&top.idef,ePBC,trxnat,box); if (bFrames) out=opt2FILE("-frames",NFILE,fnm,"w"); do { gmx_rmpbc(gpbc,trxnat,box,x); nframes++; calc_mat(nres,natoms,rndx,x,index,truncate,mdmat,nmat,ePBC,box); for (i=0; (i<nres); i++) for (j=0; (j<natoms); j++) if (nmat[i][j]) totnmat[i][j]++; for (i=0; (i<nres); i++) for (j=0; (j<nres); j++) totmdmat[i][j] += mdmat[i][j]; if (bFrames) { sprintf(label,"t=%.0f ps",t); write_xpm(out,0,label,"Distance (nm)","Residue Index","Residue Index", nres,nres,resnr,resnr,mdmat,0,truncate,rlo,rhi,&nlevels); } } while (read_next_x(oenv,status,&t,trxnat,x,box)); fprintf(stderr,"\n"); close_trj(status); gmx_rmpbc_done(gpbc); if (bFrames) ffclose(out); fprintf(stderr,"Processed %d frames\n",nframes); for (i=0; (i<nres); i++) for (j=0; (j<nres); j++) totmdmat[i][j] /= nframes; write_xpm(opt2FILE("-mean",NFILE,fnm,"w"),0,"Mean smallest distance", "Distance (nm)","Residue Index","Residue Index", nres,nres,resnr,resnr,totmdmat,0,truncate,rlo,rhi,&nlevels); if ( bCalcN ) { tot_nmat(nres,natoms,nframes,totnmat,tot_n,mean_n); fp=xvgropen(ftp2fn(efXVG,NFILE,fnm), "Increase in number of contacts","Residue","Ratio",oenv); fprintf(fp,"@ legend on\n"); fprintf(fp,"@ legend box on\n"); fprintf(fp,"@ legend loctype view\n"); fprintf(fp,"@ legend 0.75, 0.8\n"); fprintf(fp,"@ legend string 0 \"Total/mean\"\n"); fprintf(fp,"@ legend string 1 \"Total\"\n"); fprintf(fp,"@ legend string 2 \"Mean\"\n"); fprintf(fp,"@ legend string 3 \"# atoms\"\n"); fprintf(fp,"@ legend string 4 \"Mean/# atoms\"\n"); fprintf(fp,"#%3s %8s %3s %8s %3s %8s\n", "res","ratio","tot","mean","natm","mean/atm"); for (i=0; (i<nres); i++) { if (mean_n[i]==0) ratio=1; else ratio=tot_n[i]/mean_n[i]; fprintf(fp,"%3d %8.3f %3d %8.3f %3d %8.3f\n", i+1,ratio,tot_n[i],mean_n[i],natm[i],mean_n[i]/natm[i]); } ffclose(fp); } thanx(stderr); return 0; }
int gmx_saltbr(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots the distance between all combination of charged groups", "as a function of time. The groups are combined in different ways.", "A minimum distance can be given (i.e. a cut-off), such that groups", "that are never closer than that distance will not be plotted.[PAR]", "Output will be in a number of fixed filenames, [TT]min-min.xvg[tt], [TT]plus-min.xvg[tt]", "and [TT]plus-plus.xvg[tt], or files for every individual ion pair if the [TT]-sep[tt]", "option is selected. In this case, files are named as [TT]sb-(Resname)(Resnr)-(Atomnr)[tt].", "There may be [BB]many[bb] such files." }; static gmx_bool bSep = FALSE; static real truncate = 1000.0; t_pargs pa[] = { { "-t", FALSE, etREAL, {&truncate}, "Groups that are never closer than this distance are not plotted" }, { "-sep", FALSE, etBOOL, {&bSep}, "Use separate files for each interaction (may be MANY)" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPR, NULL, NULL, ffREAD }, }; #define NFILE asize(fnm) FILE *out[3], *fp; static const char *title[3] = { "Distance between positively charged groups", "Distance between negatively charged groups", "Distance between oppositely charged groups" }; static const char *fn[3] = { "plus-plus.xvg", "min-min.xvg", "plus-min.xvg" }; int nset[3] = {0, 0, 0}; t_topology *top; int ePBC; char *buf; t_trxstatus *status; int i, j, k, m, nnn, teller, ncg; real t, *time, qi, qj; t_charge *cg; real ***cgdist; int **nWithin; t_pbc pbc; rvec *x; matrix box; gmx_output_env_t *oenv; if (!parse_common_args(&argc, argv, PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); cg = mk_charge(&top->atoms, &(top->cgs), &ncg); snew(cgdist, ncg); snew(nWithin, ncg); for (i = 0; (i < ncg); i++) { snew(cgdist[i], ncg); snew(nWithin[i], ncg); } read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); teller = 0; time = NULL; do { srenew(time, teller+1); time[teller] = t; set_pbc(&pbc, ePBC, box); for (i = 0; (i < ncg); i++) { for (j = i+1; (j < ncg); j++) { srenew(cgdist[i][j], teller+1); cgdist[i][j][teller] = calc_dist(&pbc, x, &(top->cgs), cg[i].cg, cg[j].cg); if (cgdist[i][j][teller] < truncate) { nWithin[i][j] = 1; } } } teller++; } while (read_next_x(oenv, status, &t, x, box)); fprintf(stderr, "\n"); close_trj(status); if (bSep) { snew(buf, 256); for (i = 0; (i < ncg); i++) { for (j = i+1; (j < ncg); j++) { if (nWithin[i][j]) { sprintf(buf, "sb-%s:%s.xvg", cg[i].label, cg[j].label); fp = xvgropen(buf, buf, "Time (ps)", "Distance (nm)", oenv); for (k = 0; (k < teller); k++) { fprintf(fp, "%10g %10g\n", time[k], cgdist[i][j][k]); } xvgrclose(fp); } } } sfree(buf); } else { for (m = 0; (m < 3); m++) { out[m] = xvgropen(fn[m], title[m], "Time (ps)", "Distance (nm)", oenv); } snew(buf, 256); for (i = 0; (i < ncg); i++) { qi = cg[i].q; for (j = i+1; (j < ncg); j++) { qj = cg[j].q; if (nWithin[i][j]) { sprintf(buf, "%s:%s", cg[i].label, cg[j].label); if (qi*qj < 0) { nnn = 2; } else if (qi+qj > 0) { nnn = 0; } else { nnn = 1; } if (nset[nnn] == 0) { xvgr_legend(out[nnn], 1, (const char**)&buf, oenv); } else { if (output_env_get_xvg_format(oenv) == exvgXMGR) { fprintf(out[nnn], "@ legend string %d \"%s\"\n", nset[nnn], buf); } else if (output_env_get_xvg_format(oenv) == exvgXMGRACE) { fprintf(out[nnn], "@ s%d legend \"%s\"\n", nset[nnn], buf); } } nset[nnn]++; nWithin[i][j] = nnn+1; } } } for (k = 0; (k < teller); k++) { for (m = 0; (m < 3); m++) { fprintf(out[m], "%10g", time[k]); } for (i = 0; (i < ncg); i++) { for (j = i+1; (j < ncg); j++) { nnn = nWithin[i][j]; if (nnn > 0) { fprintf(out[nnn-1], " %10g", cgdist[i][j][k]); } } } for (m = 0; (m < 3); m++) { fprintf(out[m], "\n"); } } for (m = 0; (m < 3); m++) { xvgrclose(out[m]); if (nset[m] == 0) { remove(fn[m]); } } } return 0; }
int gmx_rotmat(int argc, char *argv[]) { const char *desc[] = { "[TT]g_rotmat[tt] 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]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) 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); 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); ffclose(out); do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy"); return 0; }
/* this is the main loop for the correlation type functions * fx and nx are file pointers to things like read_first_x and * read_next_x */ int corr_loop(t_corr *curr, const char *fn, const t_topology *top, int ePBC, gmx_bool bMol, int gnx[], int *index[], t_calc_func *calc1, gmx_bool bTen, int *gnx_com, int *index_com[], real dt, real t_pdb, rvec **x_pdb, matrix box_pdb, const gmx_output_env_t *oenv) { rvec *x[2]; /* the coordinates to read */ rvec *xa[2]; /* the coordinates to calculate displacements for */ rvec com = {0}; real t, t_prev = 0; int natoms, i, j, cur = 0, maxframes = 0; t_trxstatus *status; #define prev (1-cur) matrix box; gmx_bool bFirst; gmx_rmpbc_t gpbc = NULL; natoms = read_first_x(oenv, &status, fn, &curr->t0, &(x[cur]), box); #ifdef DEBUG fprintf(stderr, "Read %d atoms for first frame\n", natoms); #endif if ((gnx_com != NULL) && natoms < top->atoms.nr) { fprintf(stderr, "WARNING: The trajectory only contains part of the system (%d of %d atoms) and therefore the COM motion of only this part of the system will be removed\n", natoms, top->atoms.nr); } snew(x[prev], natoms); if (bMol) { curr->ncoords = curr->nmol; snew(xa[0], curr->ncoords); snew(xa[1], curr->ncoords); } else { curr->ncoords = natoms; xa[0] = x[0]; xa[1] = x[1]; } bFirst = TRUE; t = curr->t0; if (x_pdb) { *x_pdb = NULL; } if (bMol) { gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); } /* the loop over all frames */ do { if (x_pdb && ((bFirst && t_pdb < t) || (!bFirst && t_pdb > t - 0.5*(t - t_prev) && t_pdb < t + 0.5*(t - t_prev)))) { if (*x_pdb == NULL) { snew(*x_pdb, natoms); } for (i = 0; i < natoms; i++) { copy_rvec(x[cur][i], (*x_pdb)[i]); } copy_mat(box, box_pdb); } /* check whether we've reached a restart point */ if (bRmod(t, curr->t0, dt)) { curr->nrestart++; srenew(curr->x0, curr->nrestart); snew(curr->x0[curr->nrestart-1], curr->ncoords); srenew(curr->com, curr->nrestart); srenew(curr->n_offs, curr->nrestart); srenew(curr->lsq, curr->nrestart); snew(curr->lsq[curr->nrestart-1], curr->nmol); for (i = 0; i < curr->nmol; i++) { curr->lsq[curr->nrestart-1][i] = gmx_stats_init(); } if (debug) { fprintf(debug, "Extended data structures because of new restart %d\n", curr->nrestart); } } /* create or extend the frame-based arrays */ if (curr->nframes >= maxframes-1) { if (maxframes == 0) { for (i = 0; (i < curr->ngrp); i++) { curr->ndata[i] = NULL; curr->data[i] = NULL; if (bTen) { curr->datam[i] = NULL; } } curr->time = NULL; } maxframes += 10; for (i = 0; (i < curr->ngrp); i++) { srenew(curr->ndata[i], maxframes); srenew(curr->data[i], maxframes); if (bTen) { srenew(curr->datam[i], maxframes); } for (j = maxframes-10; j < maxframes; j++) { curr->ndata[i][j] = 0; curr->data[i][j] = 0; if (bTen) { clear_mat(curr->datam[i][j]); } } } srenew(curr->time, maxframes); } /* set the time */ curr->time[curr->nframes] = t - curr->t0; /* for the first frame, the previous frame is a copy of the first frame */ if (bFirst) { std::memcpy(xa[prev], xa[cur], curr->ncoords*sizeof(xa[prev][0])); bFirst = FALSE; } /* make the molecules whole */ if (bMol) { gmx_rmpbc(gpbc, natoms, box, x[cur]); } /* calculate the molecules' centers of masses and put them into xa */ if (bMol) { calc_mol_com(gnx[0], index[0], &top->mols, &top->atoms, x[cur], xa[cur]); } /* first remove the periodic boundary condition crossings */ for (i = 0; i < curr->ngrp; i++) { prep_data(bMol, gnx[i], index[i], xa[cur], xa[prev], box); } /* calculate the center of mass */ if (gnx_com) { prep_data(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box); calc_com(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box, &top->atoms, com); } /* loop over all groups in index file */ for (i = 0; (i < curr->ngrp); i++) { /* calculate something useful, like mean square displacements */ calc_corr(curr, i, gnx[i], index[i], xa[cur], (gnx_com != NULL), com, calc1, bTen); } cur = prev; t_prev = t; curr->nframes++; } while (read_next_x(oenv, status, &t, x[cur], box)); fprintf(stderr, "\nUsed %d restart points spaced %g %s over %g %s\n\n", curr->nrestart, output_env_conv_time(oenv, dt), output_env_get_time_unit(oenv), output_env_conv_time(oenv, curr->time[curr->nframes-1]), output_env_get_time_unit(oenv) ); if (bMol) { gmx_rmpbc_done(gpbc); } close_trj(status); return natoms; }
int gmx_genconf(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] multiplies a given coordinate file by simply stacking them", "on top of each other, like a small child playing with wooden blocks.", "The program makes a grid of [IT]user-defined[it]", "proportions ([TT]-nbox[tt]), ", "and interspaces the grid point with an extra space [TT]-dist[tt].[PAR]", "When option [TT]-rot[tt] is used the program does not check for overlap", "between molecules on grid points. It is recommended to make the box in", "the input file at least as big as the coordinates + ", "van der Waals radius.[PAR]", "If the optional trajectory file is given, conformations are not", "generated, but read from this file and translated appropriately to", "build the grid." }; const char *bugs[] = { "The program should allow for random displacement of lattice points." }; int vol; t_atoms *atoms; /* list with all atoms */ rvec *x, *xx, *v; /* coordinates? */ real t; vec4 *xrot, *vrot; int ePBC; matrix box, boxx; /* box length matrix */ rvec shift; int natoms; /* number of atoms in one molecule */ int nres; /* number of molecules? */ int i, j, k, l, m, ndx, nrdx, nx, ny, nz; t_trxstatus *status; gmx_bool bTRX; gmx_output_env_t *oenv; gmx_rng_t rng; t_filenm fnm[] = { { efSTX, "-f", "conf", ffREAD }, { efSTO, "-o", "out", ffWRITE }, { efTRX, "-trj", NULL, ffOPTRD } }; #define NFILE asize(fnm) static rvec nrbox = {1, 1, 1}; static int seed = 0; /* seed for random number generator */ static gmx_bool bRandom = FALSE; /* False: no random rotations */ static gmx_bool bRenum = TRUE; /* renumber residues */ static rvec dist = {0, 0, 0}; /* space added between molecules ? */ static rvec max_rot = {180, 180, 180}; /* maximum rotation */ t_pargs pa[] = { { "-nbox", FALSE, etRVEC, {nrbox}, "Number of boxes" }, { "-dist", FALSE, etRVEC, {dist}, "Distance between boxes" }, { "-seed", FALSE, etINT, {&seed}, "Random generator seed, if 0 generated from the time" }, { "-rot", FALSE, etBOOL, {&bRandom}, "Randomly rotate conformations" }, { "-maxrot", FALSE, etRVEC, {max_rot}, "Maximum random rotation" }, { "-renumber", FALSE, etBOOL, {&bRenum}, "Renumber residues" } }; if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, asize(bugs), bugs, &oenv)) { return 0; } if (seed == 0) { rng = gmx_rng_init(gmx_rng_make_seed()); } else { rng = gmx_rng_init(seed); } bTRX = ftp2bSet(efTRX, NFILE, fnm); nx = (int)(nrbox[XX]+0.5); ny = (int)(nrbox[YY]+0.5); nz = (int)(nrbox[ZZ]+0.5); if ((nx <= 0) || (ny <= 0) || (nz <= 0)) { gmx_fatal(FARGS, "Number of boxes (-nbox) should be larger than zero"); } vol = nx*ny*nz; /* calculate volume in grid points (= nr. molecules) */ t_topology *top; snew(top, 1); atoms = &top->atoms; read_tps_conf(opt2fn("-f", NFILE, fnm), top, &ePBC, &x, &v, box, FALSE); natoms = atoms->nr; nres = atoms->nres; /* nr of residues in one element? */ /* make space for all the atoms */ add_t_atoms(atoms, natoms*(vol-1), nres*(vol-1)); srenew(x, natoms*vol); /* get space for coordinates of all atoms */ srenew(v, natoms*vol); /* velocities. not really needed? */ snew(xrot, natoms); /* get space for rotation matrix? */ snew(vrot, natoms); if (bTRX) { if (!read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &xx, boxx)) { gmx_fatal(FARGS, "No atoms in trajectory %s", ftp2fn(efTRX, NFILE, fnm)); } } else { snew(xx, natoms); for (i = 0; i < natoms; i++) { copy_rvec(x[i], xx[i]); } } for (k = 0; (k < nz); k++) /* loop over all gridpositions */ { shift[ZZ] = k*(dist[ZZ]+box[ZZ][ZZ]); for (j = 0; (j < ny); j++) { shift[YY] = j*(dist[YY]+box[YY][YY])+k*box[ZZ][YY]; for (i = 0; (i < nx); i++) { shift[XX] = i*(dist[XX]+box[XX][XX])+j*box[YY][XX]+k*box[ZZ][XX]; ndx = (i*ny*nz+j*nz+k)*natoms; nrdx = (i*ny*nz+j*nz+k)*nres; /* Random rotation on input coords */ if (bRandom) { rand_rot(natoms, xx, v, xrot, vrot, rng, max_rot); } for (l = 0; (l < natoms); l++) { for (m = 0; (m < DIM); m++) { if (bRandom) { x[ndx+l][m] = xrot[l][m]; v[ndx+l][m] = vrot[l][m]; } else { x[ndx+l][m] = xx[l][m]; v[ndx+l][m] = v[l][m]; } } if (ePBC == epbcSCREW && i % 2 == 1) { /* Rotate around x axis */ for (m = YY; m <= ZZ; m++) { x[ndx+l][m] = box[YY][m] + box[ZZ][m] - x[ndx+l][m]; v[ndx+l][m] = -v[ndx+l][m]; } } for (m = 0; (m < DIM); m++) { x[ndx+l][m] += shift[m]; } atoms->atom[ndx+l].resind = nrdx + atoms->atom[l].resind; atoms->atomname[ndx+l] = atoms->atomname[l]; } for (l = 0; (l < nres); l++) { atoms->resinfo[nrdx+l] = atoms->resinfo[l]; if (bRenum) { atoms->resinfo[nrdx+l].nr += nrdx; } } if (bTRX) { if (!read_next_x(oenv, status, &t, xx, boxx) && ((i+1)*(j+1)*(k+1) < vol)) { gmx_fatal(FARGS, "Not enough frames in trajectory"); } } } } } if (bTRX) { close_trj(status); } /* make box bigger */ for (m = 0; (m < DIM); m++) { box[m][m] += dist[m]; } svmul(nx, box[XX], box[XX]); svmul(ny, box[YY], box[YY]); svmul(nz, box[ZZ], box[ZZ]); if (ePBC == epbcSCREW && nx % 2 == 0) { /* With an even number of boxes in x we can forgot about the screw */ ePBC = epbcXYZ; } /*depending on how you look at it, this is either a nasty hack or the way it should work*/ if (bRenum) { for (i = 0; i < atoms->nres; i++) { atoms->resinfo[i].nr = i+1; } } gmx_rng_destroy(rng); write_sto_conf(opt2fn("-o", NFILE, fnm), *top->name, atoms, x, v, ePBC, box); return 0; }
static void periodic_mindist_plot(const char *trxfn, const char *outfn, t_topology *top, int ePBC, int n, atom_id index[], gmx_bool bSplit, const output_env_t oenv) { FILE *out; const char *leg[5] = { "min per.", "max int.", "box1", "box2", "box3" }; t_trxstatus *status; real t; rvec *x; matrix box; int natoms, ind_min[2] = {0, 0}, ind_mini = 0, ind_minj = 0; real r, rmin, rmax, rmint, tmint; gmx_bool bFirst; gmx_rmpbc_t gpbc = NULL; natoms = read_first_x(oenv, &status, trxfn, &t, &x, box); check_index(NULL, n, index, NULL, natoms); out = xvgropen(outfn, "Minimum distance to periodic image", output_env_get_time_label(oenv), "Distance (nm)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ subtitle \"and maximum internal distance\"\n"); } xvgr_legend(out, 5, leg, oenv); rmint = box[XX][XX]; tmint = 0; if (NULL != top) { gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); } bFirst = TRUE; do { if (NULL != top) { gmx_rmpbc(gpbc, natoms, box, x); } periodic_dist(ePBC, box, x, n, index, &rmin, &rmax, ind_min); if (rmin < rmint) { rmint = rmin; tmint = t; ind_mini = ind_min[0]; ind_minj = ind_min[1]; } if (bSplit && !bFirst && fabs(t/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(out, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } fprintf(out, "\t%g\t%6.3f %6.3f %6.3f %6.3f %6.3f\n", output_env_conv_time(oenv, t), rmin, rmax, norm(box[0]), norm(box[1]), norm(box[2])); bFirst = FALSE; } while (read_next_x(oenv, status, &t, x, box)); if (NULL != top) { gmx_rmpbc_done(gpbc); } gmx_ffclose(out); fprintf(stdout, "\nThe shortest periodic distance is %g (nm) at time %g (%s),\n" "between atoms %d and %d\n", rmint, output_env_conv_time(oenv, tmint), output_env_get_time_unit(oenv), index[ind_mini]+1, index[ind_minj]+1); }
void dist_plot(const char *fn, const char *afile, const char *dfile, const char *nfile, const char *rfile, const char *xfile, real rcut, gmx_bool bMat, t_atoms *atoms, int ng, atom_id *index[], int gnx[], char *grpn[], gmx_bool bSplit, gmx_bool bMin, int nres, atom_id *residue, gmx_bool bPBC, int ePBC, gmx_bool bGroup, gmx_bool bEachResEachTime, gmx_bool bPrintResName, const output_env_t oenv) { FILE *atm, *dist, *num; t_trxstatus *trxout; char buf[256]; char **leg; real t, dmin, dmax, **mindres = NULL, **maxdres = NULL; int nmin, nmax; t_trxstatus *status; int i = -1, j, k, natoms; int min1, min2, max1, max2, min1r, min2r, max1r, max2r; atom_id oindex[2]; rvec *x0; matrix box; t_trxframe frout; gmx_bool bFirst; FILE *respertime = NULL; if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); dist = xvgropen(dfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv); sprintf(buf, "Number of Contacts %s %g nm", bMin ? "<" : ">", rcut); num = nfile ? xvgropen(nfile, buf, output_env_get_time_label(oenv), "Number", oenv) : NULL; atm = afile ? gmx_ffopen(afile, "w") : NULL; trxout = xfile ? open_trx(xfile, "w") : NULL; if (bMat) { if (ng == 1) { snew(leg, 1); sprintf(buf, "Internal in %s", grpn[0]); leg[0] = gmx_strdup(buf); xvgr_legend(dist, 0, (const char**)leg, oenv); if (num) { xvgr_legend(num, 0, (const char**)leg, oenv); } } else { snew(leg, (ng*(ng-1))/2); for (i = j = 0; (i < ng-1); i++) { for (k = i+1; (k < ng); k++, j++) { sprintf(buf, "%s-%s", grpn[i], grpn[k]); leg[j] = gmx_strdup(buf); } } xvgr_legend(dist, j, (const char**)leg, oenv); if (num) { xvgr_legend(num, j, (const char**)leg, oenv); } } } else { snew(leg, ng-1); for (i = 0; (i < ng-1); i++) { sprintf(buf, "%s-%s", grpn[0], grpn[i+1]); leg[i] = gmx_strdup(buf); } xvgr_legend(dist, ng-1, (const char**)leg, oenv); if (num) { xvgr_legend(num, ng-1, (const char**)leg, oenv); } } if (bEachResEachTime) { sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); respertime = xvgropen(rfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv); xvgr_legend(respertime, ng-1, (const char**)leg, oenv); if (bPrintResName) { fprintf(respertime, "# "); } for (j = 0; j < nres; j++) { fprintf(respertime, "%s%d ", *(atoms->resinfo[atoms->atom[index[0][residue[j]]].resind].name), atoms->atom[index[0][residue[j]]].resind); } fprintf(respertime, "\n"); } j = 0; if (nres) { snew(mindres, ng-1); snew(maxdres, ng-1); for (i = 1; i < ng; i++) { snew(mindres[i-1], nres); snew(maxdres[i-1], nres); for (j = 0; j < nres; j++) { mindres[i-1][j] = 1e6; } /* maxdres[*][*] is already 0 */ } } bFirst = TRUE; do { if (bSplit && !bFirst && fabs(t/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(dist, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); if (num) { fprintf(num, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } if (atm) { fprintf(atm, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } } fprintf(dist, "%12e", output_env_conv_time(oenv, t)); if (num) { fprintf(num, "%12e", output_env_conv_time(oenv, t)); } if (bMat) { if (ng == 1) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[0], index[0], index[0], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } } else { for (i = 0; (i < ng-1); i++) { for (k = i+1; (k < ng); k++) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[i], gnx[k], index[i], index[k], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } } } } } else { for (i = 1; (i < ng); i++) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[i], index[0], index[i], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } if (nres) { for (j = 0; j < nres; j++) { calc_dist(rcut, bPBC, ePBC, box, x0, residue[j+1]-residue[j], gnx[i], &(index[0][residue[j]]), index[i], bGroup, &dmin, &dmax, &nmin, &nmax, &min1r, &min2r, &max1r, &max2r); mindres[i-1][j] = min(mindres[i-1][j], dmin); maxdres[i-1][j] = max(maxdres[i-1][j], dmax); } } } } fprintf(dist, "\n"); if (num) { fprintf(num, "\n"); } if ( (bMin ? min1 : max1) != -1) { if (atm) { fprintf(atm, "%12e %12d %12d\n", output_env_conv_time(oenv, t), 1+(bMin ? min1 : max1), 1+(bMin ? min2 : max2)); } } if (trxout) { oindex[0] = bMin ? min1 : max1; oindex[1] = bMin ? min2 : max2; write_trx(trxout, 2, oindex, atoms, i, t, box, x0, NULL, NULL); } bFirst = FALSE; /*dmin should be minimum distance for residue and group*/ if (bEachResEachTime) { fprintf(respertime, "%12e", t); for (i = 1; i < ng; i++) { for (j = 0; j < nres; j++) { fprintf(respertime, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]); /*reset distances for next time point*/ mindres[i-1][j] = 1e6; maxdres[i-1][j] = 0; } } fprintf(respertime, "\n"); } } while (read_next_x(oenv, status, &t, x0, box)); close_trj(status); gmx_ffclose(dist); if (num) { gmx_ffclose(num); } if (atm) { gmx_ffclose(atm); } if (trxout) { close_trx(trxout); } if (nres && !bEachResEachTime) { FILE *res; sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); res = xvgropen(rfile, buf, "Residue (#)", "Distance (nm)", oenv); xvgr_legend(res, ng-1, (const char**)leg, oenv); for (j = 0; j < nres; j++) { fprintf(res, "%4d", j+1); for (i = 1; i < ng; i++) { fprintf(res, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]); } fprintf(res, "\n"); } } sfree(x0); }
int gmx_trjorder(int argc,char *argv[]) { const char *desc[] = { "[TT]trjorder[tt] orders molecules according to the smallest distance", "to atoms in a reference group", "or on z-coordinate (with option [TT]-z[tt]).", "With distance ordering, it will ask for a group of reference", "atoms and a group of molecules. For each frame of the trajectory", "the selected molecules will be reordered according to the shortest", "distance between atom number [TT]-da[tt] in the molecule and all the", "atoms in the reference group. The center of mass of the molecules can", "be used instead of a reference atom by setting [TT]-da[tt] to 0.", "All atoms in the trajectory are written", "to the output trajectory.[PAR]", "[TT]trjorder[tt] can be useful for e.g. analyzing the n waters closest to a", "protein.", "In that case the reference group would be the protein and the group", "of molecules would consist of all the water atoms. When an index group", "of the first n waters is made, the ordered trajectory can be used", "with any Gromacs program to analyze the n closest waters.", "[PAR]", "If the output file is a [TT].pdb[tt] file, the distance to the reference target", "will be stored in the B-factor field in order to color with e.g. Rasmol.", "[PAR]", "With option [TT]-nshell[tt] the number of molecules within a shell", "of radius [TT]-r[tt] around the reference group are printed." }; static int na=3,ref_a=1; static real rcut=0; static gmx_bool bCOM=FALSE,bZ=FALSE; t_pargs pa[] = { { "-na", FALSE, etINT, {&na}, "Number of atoms in a molecule" }, { "-da", FALSE, etINT, {&ref_a}, "Atom used for the distance calculation, 0 is COM" }, { "-com", FALSE, etBOOL, {&bCOM}, "Use the distance to the center of mass of the reference group" }, { "-r", FALSE, etREAL, {&rcut}, "Cutoff used for the distance calculation when computing the number of molecules in a shell around e.g. a protein" }, { "-z", FALSE, etBOOL, {&bZ}, "Order molecules on z-coordinate" } }; FILE *fp; t_trxstatus *out; t_trxstatus *status; gmx_bool bNShell,bPDBout; t_topology top; int ePBC; rvec *x,*xsol,xcom,dx; matrix box; t_pbc pbc; gmx_rmpbc_t gpbc; real t,totmass,mass,rcut2=0,n2; int natoms,nwat,ncut; char **grpname,title[256]; int i,j,d,*isize,isize_ref=0,isize_sol; atom_id sa,sr,*swi,**index,*ind_ref=NULL,*ind_sol; output_env_t oenv; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efTRO, "-o", "ordered", ffOPTWR }, { efXVG, "-nshell", "nshell", ffOPTWR } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,TRUE); sfree(x); /* get index groups */ printf("Select %sa group of molecules to be ordered:\n", bZ ? "" : "a group of reference atoms and "); snew(grpname,2); snew(index,2); snew(isize,2); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),bZ ? 1 : 2, isize,index,grpname); if (!bZ) { isize_ref = isize[0]; isize_sol = isize[1]; ind_ref = index[0]; ind_sol = index[1]; } else { isize_sol = isize[0]; ind_sol = index[0]; } natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (natoms > top.atoms.nr) gmx_fatal(FARGS,"Number of atoms in the run input file is larger than in the trjactory"); for(i=0; (i<2); i++) for(j=0; (j<isize[i]); j++) if (index[i][j] > natoms) gmx_fatal(FARGS,"An atom number in group %s is larger than the number of atoms in the trajectory"); if ((isize_sol % na) != 0) gmx_fatal(FARGS,"Number of atoms in the molecule group (%d) is not a multiple of na (%d)", isize[1],na); nwat = isize_sol/na; if (ref_a > na) gmx_fatal(FARGS,"The reference atom can not be larger than the number of atoms in a molecule"); ref_a--; snew(xsol,nwat); snew(order,nwat); snew(swi,natoms); for(i=0; (i<natoms); i++) swi[i] = i; out = NULL; fp = NULL; bNShell = ((opt2bSet("-nshell",NFILE,fnm)) || (opt2parg_bSet("-r",asize(pa),pa))); bPDBout = FALSE; if (bNShell) { rcut2 = rcut*rcut; fp = xvgropen(opt2fn("-nshell",NFILE,fnm),"Number of molecules", "Time (ps)","N",oenv); printf("Will compute the number of molecules within a radius of %g\n", rcut); } if (!bNShell || opt2bSet("-o",NFILE,fnm)) { bPDBout = (fn2ftp(opt2fn("-o",NFILE,fnm)) == efPDB); if (bPDBout && !top.atoms.pdbinfo) { fprintf(stderr,"Creating pdbfino records\n"); snew(top.atoms.pdbinfo,top.atoms.nr); } out = open_trx(opt2fn("-o",NFILE,fnm),"w"); } gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box); do { gmx_rmpbc(gpbc,natoms,box,x); set_pbc(&pbc,ePBC,box); if (ref_a == -1) { /* Calculate the COM of all solvent molecules */ for(i=0; i<nwat; i++) { totmass = 0; clear_rvec(xsol[i]); for(j=0; j<na; j++) { sa = ind_sol[i*na+j]; mass = top.atoms.atom[sa].m; totmass += mass; for(d=0; d<DIM; d++) { xsol[i][d] += mass*x[sa][d]; } } svmul(1/totmass,xsol[i],xsol[i]); } } else { /* Copy the reference atom of all solvent molecules */ for(i=0; i<nwat; i++) { copy_rvec(x[ind_sol[i*na+ref_a]],xsol[i]); } } if (bZ) { for(i=0; (i<nwat); i++) { sa = ind_sol[na*i]; order[i].i = sa; order[i].d2 = xsol[i][ZZ]; } } else if (bCOM) { totmass = 0; clear_rvec(xcom); for(i=0; i<isize_ref; i++) { mass = top.atoms.atom[ind_ref[i]].m; totmass += mass; for(j=0; j<DIM; j++) xcom[j] += mass*x[ind_ref[i]][j]; } svmul(1/totmass,xcom,xcom); for(i=0; (i<nwat); i++) { sa = ind_sol[na*i]; pbc_dx(&pbc,xcom,xsol[i],dx); order[i].i = sa; order[i].d2 = norm2(dx); } } else { /* Set distance to first atom */ for(i=0; (i<nwat); i++) { sa = ind_sol[na*i]; pbc_dx(&pbc,x[ind_ref[0]],xsol[i],dx); order[i].i = sa; order[i].d2 = norm2(dx); } for(j=1; (j<isize_ref); j++) { sr = ind_ref[j]; for(i=0; (i<nwat); i++) { sa = ind_sol[na*i]; pbc_dx(&pbc,x[sr],xsol[i],dx); n2 = norm2(dx); if (n2 < order[i].d2) order[i].d2 = n2; } } } if (bNShell) { ncut = 0; for(i=0; (i<nwat); i++) if (order[i].d2 <= rcut2) ncut++; fprintf(fp,"%10.3f %8d\n",t,ncut); } if (out) { qsort(order,nwat,sizeof(*order),ocomp); for(i=0; (i<nwat); i++) for(j=0; (j<na); j++) swi[ind_sol[na*i]+j] = order[i].i+j; /* Store the distance as the B-factor */ if (bPDBout) { for(i=0; (i<nwat); i++) { for(j=0; (j<na); j++) { top.atoms.pdbinfo[order[i].i+j].bfac = sqrt(order[i].d2); } } } write_trx(out,natoms,swi,&top.atoms,0,t,box,x,NULL,NULL); } } while(read_next_x(oenv,status,&t,natoms,x,box)); close_trj(status); if (out) close_trx(out); if (fp) ffclose(fp); gmx_rmpbc_done(gpbc); thanx(stderr); return 0; }
int gmx_principal(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] calculates the three principal axes of inertia for a group", "of atoms.", }; static gmx_bool foo = FALSE; t_pargs pa[] = { { "-foo", FALSE, etBOOL, {&foo}, "Dummy option to avoid empty array" } }; t_trxstatus *status; t_topology top; int ePBC; real t; rvec * x; int natoms; char *grpname, title[256]; int i, j, m, gnx, nam, mol; atom_id *index; rvec a1, a2, a3, moi; FILE * axis1; FILE * axis2; FILE * axis3; FILE * fmoi; matrix axes, box; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-a1", "axis1", ffWRITE }, { efDAT, "-a2", "axis2", ffWRITE }, { efDAT, "-a3", "axis3", ffWRITE }, { efDAT, "-om", "moi", ffWRITE } }; #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; } axis1 = ffopen(opt2fn("-a1", NFILE, fnm), "w"); axis2 = ffopen(opt2fn("-a2", NFILE, fnm), "w"); axis3 = ffopen(opt2fn("-a3", NFILE, fnm), "w"); fmoi = ffopen(opt2fn("-om", NFILE, fnm), "w"); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, NULL, NULL, box, TRUE); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname); natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); do { gmx_rmpbc(gpbc, natoms, box, x); calc_principal_axes(&top, x, index, gnx, axes, moi); fprintf(axis1, "%15.10f %15.10f %15.10f %15.10f\n", t, axes[XX][XX], axes[YY][XX], axes[ZZ][XX]); fprintf(axis2, "%15.10f %15.10f %15.10f %15.10f\n", t, axes[XX][YY], axes[YY][YY], axes[ZZ][YY]); fprintf(axis3, "%15.10f %15.10f %15.10f %15.10f\n", t, axes[XX][ZZ], axes[YY][ZZ], axes[ZZ][ZZ]); fprintf(fmoi, "%15.10f %15.10f %15.10f %15.10f\n", t, moi[XX], moi[YY], moi[ZZ]); } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); close_trj(status); ffclose(axis1); ffclose(axis2); ffclose(axis3); ffclose(fmoi); return 0; }
int gmx_rmsf(int argc,char *argv[]) { static char *desc[] = { "g_rmsf computes the root mean square fluctuation (RMSF, i.e. standard ", "deviation) of atomic positions ", "after (optionally) fitting to a reference frame.[PAR]", "With option [TT]-oq[tt] the RMSF values are converted to B-factor", "values, which are written to a pdb file with the coordinates, of the", "structure file, or of a pdb 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] g_rmsf will compute anisotropic", "temperature factors and then it will also output average coordinates", "and a pdb 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 pdb 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 pdb 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 bool bRes=FALSE,bAniso=FALSE,bdevX=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 step,nre,natom,natoms,i,g,m,teller=0; real t,lambda,*w_rls,*w_rms; t_tpxheader header; t_inputrec ir; t_topology top; int ePBC; t_atoms *pdbatoms,*refatoms; bool bCont; matrix box,pdbbox; rvec *x,*pdbx,*xref; int status,npdbatoms,res0; char buf[256],*label; char title[STRLEN]; FILE *fp; /* the graphics file */ char *devfn,*dirfn; int resnr; bool bReadPDB; atom_id *index; int isize; char *grpnames; real bfac,pdb_bfac,*Uaver; double **U,*xav; atom_id aid; rvec *rmsd_x=NULL; real *rmsf,invcount,totmass; int d; real count=0; rvec xcm; char *leg[2] = { "MD", "X-Ray" }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efPDB, "-q", NULL, 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) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE , NFILE,fnm,asize(pargs),pargs,asize(desc),desc,0,NULL); bReadPDB = ftp2bSet(efPDB,NFILE,fnm); devfn = opt2fn_null("-od",NFILE,fnm); dirfn = opt2fn_null("-dir",NFILE,fnm); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xref,NULL,box,TRUE); 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) { get_stx_coordnum(opt2fn("-q",NFILE,fnm),&npdbatoms); snew(pdbatoms,1); snew(refatoms,1); init_t_atoms(pdbatoms,npdbatoms,TRUE); init_t_atoms(refatoms,npdbatoms,TRUE); snew(pdbx,npdbatoms); /* Read coordinates twice */ read_stx_conf(opt2fn("-q",NFILE,fnm),title,pdbatoms,pdbx,NULL,NULL,pdbbox); read_stx_conf(opt2fn("-q",NFILE,fnm),title,refatoms,pdbx,NULL,NULL,pdbbox); } else { pdbatoms = &top.atoms; refatoms = &top.atoms; pdbx = xref; npdbatoms = pdbatoms->nr; snew(pdbatoms->pdbinfo,npdbatoms); copy_mat(box,pdbbox); } if (bFit) sub_xcm(xref,isize,index,top.atoms.atom,xcm,FALSE); natom = read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); /* Now read the trj again to compute fluctuations */ teller = 0; do { if (bFit) { /* Remove periodic boundary */ rm_pbc(&(top.idef),ePBC,natom,box,x,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] += sqr(x[aid][d]-xref[aid][d]); } } } count += 1.0; teller++; } while(read_next_x(status,&t,natom,x,box)); close_trj(status); 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 (bAniso) { for(i=0; i<isize; i++) { aid = index[i]; pdbatoms->pdbinfo[aid].bAnisotropic = TRUE; pdbatoms->pdbinfo[aid].uij[U11] = 1e6*U[i][XX*DIM + XX]; pdbatoms->pdbinfo[aid].uij[U22] = 1e6*U[i][YY*DIM + YY]; pdbatoms->pdbinfo[aid].uij[U33] = 1e6*U[i][ZZ*DIM + ZZ]; pdbatoms->pdbinfo[aid].uij[U12] = 1e6*U[i][XX*DIM + YY]; pdbatoms->pdbinfo[aid].uij[U13] = 1e6*U[i][XX*DIM + ZZ]; pdbatoms->pdbinfo[aid].uij[U23] = 1e6*U[i][YY*DIM + ZZ]; } } if (bRes) { average_residues(rmsf,isize,index,w_rls,&top.atoms); 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 = ffopen(dirfn,"w"); print_dir(fp,Uaver); fclose(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)"); xvgr_legend(fp,2,leg); for(i=0;(i<isize);i++) { if (!bRes || i+1==isize || top.atoms.atom[index[i]].resnr!=top.atoms.atom[index[i+1]].resnr) { resnr = top.atoms.atom[index[i]].resnr; pdb_bfac = find_pdb_bfac(pdbatoms,*(top.atoms.resname[resnr]),resnr, *(top.atoms.atomname[index[i]])); fprintf(fp,"%5d %10.5f %10.5f\n", bRes ? top.atoms.atom[index[i]].resnr+1 : i+1,rmsf[i]*bfac, pdb_bfac); } } fclose(fp); } else { fp = xvgropen(ftp2fn(efXVG,NFILE,fnm),"RMS fluctuation",label,"(nm)"); for(i=0; i<isize; i++) if (!bRes || i+1==isize || top.atoms.atom[index[i]].resnr!=top.atoms.atom[index[i+1]].resnr) fprintf(fp,"%5d %8.4f\n", bRes ? top.atoms.atom[index[i]].resnr+1 : i+1,sqrt(rmsf[i])); fclose(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,isize,index,w_rls,&top.atoms); /* Write RMSD output */ fp = xvgropen(devfn,"RMS Deviation",label,"(nm)"); for(i=0; i<isize; i++) if (!bRes || i+1==isize || top.atoms.atom[index[i]].resnr!=top.atoms.atom[index[i+1]].resnr) fprintf(fp,"%5d %8.4f\n", bRes ? top.atoms.atom[index[i]].resnr+1 : i+1,sqrt(rmsf[i])); fclose(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(xref[index[i]],xcm); write_sto_conf_indexed(opt2fn("-oq",NFILE,fnm),title,pdbatoms,pdbx, NULL,ePBC,pdbbox,isize,index); } if (opt2bSet("-ox",NFILE,fnm)) { /* Misuse xref as a temporary array */ for(i=0; i<isize; i++) for(d=0; d<DIM; d++) xref[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,xref,NULL, ePBC,pdbbox,isize,index); } if (bAniso) { correlate_aniso(opt2fn("-oc",NFILE,fnm),refatoms,pdbatoms); do_view(opt2fn("-oc",NFILE,fnm),"-nxy"); } do_view(opt2fn("-o",NFILE,fnm),"-nxy"); if (devfn) do_view(opt2fn("-od",NFILE,fnm),"-nxy"); thanx(stderr); return 0; }
void calc_density(const char *fn, atom_id **index, int gnx[], double ***slDensity, int *nslices, t_topology *top, int ePBC, int axis, int nr_grps, real *slWidth, gmx_bool bCenter, atom_id *index_center, int ncenter, gmx_bool bRelative, const output_env_t oenv) { rvec *x0; /* coordinates without pbc */ matrix box; /* box (3x3) */ double invvol; int natoms; /* nr. atoms in trj */ t_trxstatus *status; int **slCount, /* nr. of atoms in one slice for a group */ i, j, n, /* loop indices */ ax1 = 0, ax2 = 0, nr_frames = 0, /* number of frames */ slice; /* current slice */ real t, z; real boxSz, aveBox; char *buf; /* for tmp. keeping atomname */ gmx_rmpbc_t gpbc = NULL; if (axis < 0 || axis >= DIM) { gmx_fatal(FARGS, "Invalid axes. Terminating\n"); } if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } aveBox = 0; if (!*nslices) { *nslices = (int)(box[axis][axis] * 10); /* default value */ fprintf(stderr, "\nDividing the box in %d slices\n", *nslices); } snew(*slDensity, nr_grps); for (i = 0; i < nr_grps; i++) { snew((*slDensity)[i], *nslices); } gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr); /*********** Start processing trajectory ***********/ do { gmx_rmpbc(gpbc, natoms, box, x0); /* Translate atoms so the com of the center-group is in the * box geometrical center. */ if (bCenter) { center_coords(&top->atoms, index_center, ncenter, box, x0); } invvol = *nslices/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]); if (bRelative) { *slWidth = 1.0/(*nslices); boxSz = 1.0; } else { *slWidth = box[axis][axis]/(*nslices); boxSz = box[axis][axis]; } aveBox += box[axis][axis]; for (n = 0; n < nr_grps; n++) { for (i = 0; i < gnx[n]; i++) /* loop over all atoms in index file */ { z = x0[index[n][i]][axis]; while (z < 0) { z += box[axis][axis]; } while (z > box[axis][axis]) { z -= box[axis][axis]; } if (bRelative) { z = z/box[axis][axis]; } /* determine which slice atom is in */ if (bCenter) { slice = floor( (z-(boxSz/2.0)) / (*slWidth) ) + *nslices/2; } else { slice = floor(z / (*slWidth)); } /* Slice should already be 0<=slice<nslices, but we just make * sure we are not hit by IEEE rounding errors since we do * math operations after applying PBC above. */ if (slice < 0) { slice += *nslices; } else if (slice >= *nslices) { slice -= *nslices; } (*slDensity)[n][slice] += top->atoms.atom[index[n][i]].m*invvol; } } nr_frames++; } while (read_next_x(oenv, status, &t, x0, box)); gmx_rmpbc_done(gpbc); /*********** done with status file **********/ close_trj(status); /* slDensity now contains the total mass per slice, summed over all frames. Now divide by nr_frames and volume of slice */ fprintf(stderr, "\nRead %d frames from trajectory. Calculating density\n", nr_frames); if (bRelative) { aveBox /= nr_frames; *slWidth = aveBox/(*nslices); } for (n = 0; n < nr_grps; n++) { for (i = 0; i < *nslices; i++) { (*slDensity)[n][i] /= nr_frames; } } sfree(x0); /* free memory used by coordinate array */ }
void calc_electron_density(const char *fn, atom_id **index, int gnx[], double ***slDensity, int *nslices, t_topology *top, int ePBC, int axis, int nr_grps, real *slWidth, t_electron eltab[], int nr, gmx_bool bCenter, atom_id *index_center, int ncenter, gmx_bool bRelative, const output_env_t oenv) { rvec *x0; /* coordinates without pbc */ matrix box; /* box (3x3) */ double invvol; int natoms; /* nr. atoms in trj */ t_trxstatus *status; int i, n, /* loop indices */ nr_frames = 0, /* number of frames */ slice; /* current slice */ t_electron *found; /* found by bsearch */ t_electron sought; /* thingie thought by bsearch */ real boxSz, aveBox; gmx_rmpbc_t gpbc = NULL; real t, z; if (axis < 0 || axis >= DIM) { gmx_fatal(FARGS, "Invalid axes. Terminating\n"); } if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } aveBox = 0; if (!*nslices) { *nslices = (int)(box[axis][axis] * 10); /* default value */ fprintf(stderr, "\nDividing the box in %d slices\n", *nslices); } snew(*slDensity, nr_grps); for (i = 0; i < nr_grps; i++) { snew((*slDensity)[i], *nslices); } gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr); /*********** Start processing trajectory ***********/ do { gmx_rmpbc(gpbc, natoms, box, x0); /* Translate atoms so the com of the center-group is in the * box geometrical center. */ if (bCenter) { center_coords(&top->atoms, index_center, ncenter, box, x0); } invvol = *nslices/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]); if (bRelative) { *slWidth = 1.0/(*nslices); boxSz = 1.0; } else { *slWidth = box[axis][axis]/(*nslices); boxSz = box[axis][axis]; } aveBox += box[axis][axis]; for (n = 0; n < nr_grps; n++) { for (i = 0; i < gnx[n]; i++) /* loop over all atoms in index file */ { z = x0[index[n][i]][axis]; while (z < 0) { z += box[axis][axis]; } while (z > box[axis][axis]) { z -= box[axis][axis]; } if (bRelative) { z = z/box[axis][axis]; } /* determine which slice atom is in */ if (bCenter) { slice = floor( (z-(boxSz/2.0)) / (*slWidth) ) + *nslices/2; } else { slice = (z / (*slWidth)); } sought.nr_el = 0; sought.atomname = gmx_strdup(*(top->atoms.atomname[index[n][i]])); /* now find the number of electrons. This is not efficient. */ found = (t_electron *) bsearch((const void *)&sought, (const void *)eltab, nr, sizeof(t_electron), (int(*)(const void*, const void*))compare); if (found == NULL) { fprintf(stderr, "Couldn't find %s. Add it to the .dat file\n", *(top->atoms.atomname[index[n][i]])); } else { (*slDensity)[n][slice] += (found->nr_el - top->atoms.atom[index[n][i]].q)*invvol; } free(sought.atomname); } } nr_frames++; } while (read_next_x(oenv, status, &t, x0, box)); gmx_rmpbc_done(gpbc); /*********** done with status file **********/ close_trj(status); /* slDensity now contains the total number of electrons per slice, summed over all frames. Now divide by nr_frames and volume of slice */ fprintf(stderr, "\nRead %d frames from trajectory. Counting electrons\n", nr_frames); if (bRelative) { aveBox /= nr_frames; *slWidth = aveBox/(*nslices); } for (n = 0; n < nr_grps; n++) { for (i = 0; i < *nslices; i++) { (*slDensity)[n][i] /= nr_frames; } } sfree(x0); /* free memory used by coordinate array */ }
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; 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_vanhove(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the Van Hove correlation function.", "The Van Hove G(r,t) is the probability that a particle that is at r[SUB]0[sub]", "at time zero can be found at position r[SUB]0[sub]+r at time t.", "[THISMODULE] 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[sqrt] 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[sqrt] on the matrix axis which binspacing # in [SQRT]ps[sqrt]" }, { "-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 [TT]-or[tt] (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 [TT]-or[tt] output" }, { "-fr", FALSE, etINT, {&fshift}, "Frame spacing for the [TT]-or[tt] output" }, { "-rt", FALSE, etREAL, {&rint}, "Integration limit for the [TT]-ot[tt] output (nm)" }, { "-ft", FALSE, etINT, {&ftmax}, "Number of frames in the [TT]-ot[tt] 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) gmx_output_env_t *oenv; const char *matfile, *otfile, *orfile; t_topology top; int ePBC; matrix boxtop, box, *sbox, avbox, corr; rvec *xtop, *x, **sx; int isize, nalloc, nallocn; t_trxstatus *status; int *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}; 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; } 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), &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); 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); } GMX_RELEASE_ASSERT(time != NULL, "Memory allocation failure; time array is NULL"); GMX_RELEASE_ASSERT(sbox != NULL, "Memory allocation failure; sbox array is NULL"); 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, 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 = std::round(10000.0*dt)/10000.0; invbin = 1.0/rbin; if (matfile) { if (fmmax <= 0 || fmmax >= nfr) { fmmax = nfr - 1; } snew(mcount, fmmax); nbin = static_cast<int>(rmax*invbin + 0.5); if (sbin == 0) { mat_nx = fmmax + 1; } else { invsbin = 1.0/sbin; mat_nx = static_cast<int>(std::sqrt(fmmax*dt)*invsbin + 1); } snew(mat, mat_nx); for (f = 0; f < mat_nx; f++) { snew(mat[f], nbin); } rmax2 = gmx::square(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); fflush(stderr); } if (ePBC != epbcNONE) { /* Scale all the configuration to the average box */ gmx::invertBoxMatrix(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 = static_cast<int>(std::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 = static_cast<int>(std::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 = static_cast<int>(std::sqrt(d2)*invbin + 0.5); 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 = gmx_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); gmx_ffclose(fp); } if (orfile) { fp = xvgropen(orfile, "Van Hove function", "r (nm)", "G (nm\\S-1\\N)", oenv); if (output_env_get_print_xvgr_codes(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] = gmx_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", static_cast<real>(pr[fbin][i])/(rcount[fbin]*isize*rbin*(i == 0 ? 0.5 : 1.0))); } fprintf(fp, "\n"); } xvgrclose(fp); } if (otfile) { sprintf(buf, "Probability of moving less than %g nm", rint); fp = xvgropen(otfile, buf, "t (ps)", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname); } for (f = 0; f <= ftmax; f++) { fprintf(fp, "%g %g\n", f*dt, static_cast<real>(pt[f])/(tcount[f]*isize)); } xvgrclose(fp); } do_view(oenv, matfile, NULL); do_view(oenv, orfile, NULL); do_view(oenv, otfile, NULL); return 0; }
void calc_potential(const char *fn, atom_id **index, int gnx[], double ***slPotential, double ***slCharge, double ***slField, int *nslices, t_topology *top, int ePBC, int axis, int nr_grps, double *slWidth, double fudge_z, gmx_bool bSpherical, gmx_bool bCorrect, const output_env_t oenv) { rvec *x0; /* coordinates without pbc */ matrix box; /* box (3x3) */ int natoms; /* nr. atoms in trj */ t_trxstatus *status; int i, n, /* loop indices */ teller = 0, ax1 = 0, ax2 = 0, nr_frames = 0, /* number of frames */ slice; /* current slice */ double slVolume; /* volume of slice for spherical averaging */ double qsum, nn; real t; double z; rvec xcm; gmx_rmpbc_t gpbc = NULL; switch (axis) { case 0: ax1 = 1; ax2 = 2; break; case 1: ax1 = 0; ax2 = 2; break; case 2: ax1 = 0; ax2 = 1; break; default: gmx_fatal(FARGS, "Invalid axes. Terminating\n"); } if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } if (!*nslices) { *nslices = static_cast<int>(box[axis][axis] * 10.0); /* default value */ } fprintf(stderr, "\nDividing the box in %d slices\n", *nslices); snew(*slField, nr_grps); snew(*slCharge, nr_grps); snew(*slPotential, nr_grps); for (i = 0; i < nr_grps; i++) { snew((*slField)[i], *nslices); snew((*slCharge)[i], *nslices); snew((*slPotential)[i], *nslices); } gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); /*********** Start processing trajectory ***********/ do { *slWidth = box[axis][axis]/(*nslices); teller++; gmx_rmpbc(gpbc, natoms, box, x0); /* calculate position of center of mass based on group 1 */ calc_xcm(x0, gnx[0], index[0], top->atoms.atom, xcm, FALSE); svmul(-1, xcm, xcm); for (n = 0; n < nr_grps; n++) { /* Check whether we actually have all positions of the requested index * group in the trajectory file */ if (gnx[n] > natoms) { gmx_fatal(FARGS, "You selected a group with %d atoms, but only %d atoms\n" "were found in the trajectory.\n", gnx[n], natoms); } for (i = 0; i < gnx[n]; i++) /* loop over all atoms in index file */ { if (bSpherical) { rvec_add(x0[index[n][i]], xcm, x0[index[n][i]]); /* only distance from origin counts, not sign */ slice = static_cast<int>(norm(x0[index[n][i]])/(*slWidth)); /* this is a nice check for spherical groups but not for all water in a cubic box since a lot will fall outside the sphere if (slice > (*nslices)) { fprintf(stderr,"Warning: slice = %d\n",slice); } */ (*slCharge)[n][slice] += top->atoms.atom[index[n][i]].q; } else { z = x0[index[n][i]][axis]; z = z + fudge_z; if (z < 0) { z += box[axis][axis]; } if (z > box[axis][axis]) { z -= box[axis][axis]; } /* determine which slice atom is in */ slice = static_cast<int>((z / (*slWidth))); (*slCharge)[n][slice] += top->atoms.atom[index[n][i]].q; } } } nr_frames++; } while (read_next_x(oenv, status, &t, x0, box)); gmx_rmpbc_done(gpbc); /*********** done with status file **********/ close_trj(status); /* slCharge now contains the total charge per slice, summed over all frames. Now divide by nr_frames and integrate twice */ if (bSpherical) { fprintf(stderr, "\n\nRead %d frames from trajectory. Calculating potential" "in spherical coordinates\n", nr_frames); } else { fprintf(stderr, "\n\nRead %d frames from trajectory. Calculating potential\n", nr_frames); } for (n = 0; n < nr_grps; n++) { for (i = 0; i < *nslices; i++) { if (bSpherical) { /* charge per volume is now the summed charge, divided by the nr of frames and by the volume of the slice it's in, 4pi r^2 dr */ slVolume = 4*M_PI * sqr(i) * sqr(*slWidth) * *slWidth; if (slVolume == 0) { (*slCharge)[n][i] = 0; } else { (*slCharge)[n][i] = (*slCharge)[n][i] / (nr_frames * slVolume); } } else { /* get charge per volume */ (*slCharge)[n][i] = (*slCharge)[n][i] * (*nslices) / (nr_frames * box[axis][axis] * box[ax1][ax1] * box[ax2][ax2]); } } /* Now we have charge densities */ } if (bCorrect && !bSpherical) { for (n = 0; n < nr_grps; n++) { nn = 0; qsum = 0; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { nn++; qsum += (*slCharge)[n][i]; } } qsum /= nn; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { (*slCharge)[n][i] -= qsum; } } } } for (n = 0; n < nr_grps; n++) { /* integrate twice to get field and potential */ p_integrate((*slField)[n], (*slCharge)[n], *nslices, *slWidth); } if (bCorrect && !bSpherical) { for (n = 0; n < nr_grps; n++) { nn = 0; qsum = 0; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { nn++; qsum += (*slField)[n][i]; } } qsum /= nn; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { (*slField)[n][i] -= qsum; } } } } for (n = 0; n < nr_grps; n++) { p_integrate((*slPotential)[n], (*slField)[n], *nslices, *slWidth); } /* Now correct for eps0 and in spherical case for r*/ for (n = 0; n < nr_grps; n++) { for (i = 0; i < *nslices; i++) { if (bSpherical) { (*slPotential)[n][i] = ELC * (*slPotential)[n][i] * -1.0E9 / (EPS0 * i * (*slWidth)); (*slField)[n][i] = ELC * (*slField)[n][i] * 1E18 / (EPS0 * i * (*slWidth)); } else { (*slPotential)[n][i] = ELC * (*slPotential)[n][i] * -1.0E9 / EPS0; (*slField)[n][i] = ELC * (*slField)[n][i] * 1E18 / EPS0; } } } sfree(x0); /* free memory used by coordinate array */ }
int gmx_spol(int argc, char *argv[]) { t_topology *top; t_inputrec *ir; t_atom *atom; char title[STRLEN]; t_trxstatus *status; int nrefat, natoms, nf, ntot; real t; rvec *xtop, *x, xref, trial, dx = {0}, dip, dir; matrix box; FILE *fp; int *isize, nrefgrp; atom_id **index, *molindex; char **grpname; real rmin2, rmax2, rcut, rcut2, rdx2 = 0, rtry2, qav, q, dip2, invbw; int nbin, i, m, mol, a0, a1, a, d; double sdip, sdip2, sinp, sdinp, nmol; int *hist; t_pbc pbc; gmx_rmpbc_t gpbc = NULL; const char *desc[] = { "[THISMODULE] analyzes dipoles around a solute; it is especially useful", "for polarizable water. A group of reference atoms, or a center", "of mass reference (option [TT]-com[tt]) and a group of solvent", "atoms is required. The program splits the group of solvent atoms", "into molecules. For each solvent molecule the distance to the", "closest atom in reference group or to the COM is determined.", "A cumulative distribution of these distances is plotted.", "For each distance between [TT]-rmin[tt] and [TT]-rmax[tt]", "the inner product of the distance vector", "and the dipole of the solvent molecule is determined.", "For solvent molecules with net charge (ions), the net charge of the ion", "is subtracted evenly from all atoms in the selection of each ion.", "The average of these dipole components is printed.", "The same is done for the polarization, where the average dipole is", "subtracted from the instantaneous dipole. The magnitude of the average", "dipole is set with the option [TT]-dip[tt], the direction is defined", "by the vector from the first atom in the selected solvent group", "to the midpoint between the second and the third atom." }; output_env_t oenv; static gmx_bool bCom = FALSE, bPBC = FALSE; static int srefat = 1; static real rmin = 0.0, rmax = 0.32, refdip = 0, bw = 0.01; t_pargs pa[] = { { "-com", FALSE, etBOOL, {&bCom}, "Use the center of mass as the reference postion" }, { "-refat", FALSE, etINT, {&srefat}, "The reference atom of the solvent molecule" }, { "-rmin", FALSE, etREAL, {&rmin}, "Maximum distance (nm)" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum distance (nm)" }, { "-dip", FALSE, etREAL, {&refdip}, "The average dipole (D)" }, { "-bw", FALSE, etREAL, {&bw}, "The bin width" } }; t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPX, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "scdist.xvg", 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; } snew(top, 1); snew(ir, 1); read_tpx_top(ftp2fn(efTPX, NFILE, fnm), ir, box, &natoms, NULL, NULL, NULL, top); /* get index groups */ printf("Select a group of reference particles and a solvent group:\n"); snew(grpname, 2); snew(index, 2); snew(isize, 2); get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 2, isize, index, grpname); if (bCom) { nrefgrp = 1; nrefat = isize[0]; } else { nrefgrp = isize[0]; nrefat = 1; } spol_atom2molindex(&(isize[1]), index[1], &(top->mols)); srefat--; /* initialize reading trajectory: */ natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); rcut = 0.99*sqrt(max_cutoff2(ir->ePBC, box)); if (rcut == 0) { rcut = 10*rmax; } rcut2 = sqr(rcut); invbw = 1/bw; nbin = (int)(rcut*invbw)+2; snew(hist, nbin); rmin2 = sqr(rmin); rmax2 = sqr(rmax); nf = 0; ntot = 0; sdip = 0; sdip2 = 0; sinp = 0; sdinp = 0; molindex = top->mols.index; atom = top->atoms.atom; gpbc = gmx_rmpbc_init(&top->idef, ir->ePBC, natoms); /* start analysis of trajectory */ do { /* make molecules whole again */ gmx_rmpbc(gpbc, natoms, box, x); set_pbc(&pbc, ir->ePBC, box); if (bCom) { calc_com_pbc(nrefat, top, x, &pbc, index[0], xref, ir->ePBC); } for (m = 0; m < isize[1]; m++) { mol = index[1][m]; a0 = molindex[mol]; a1 = molindex[mol+1]; for (i = 0; i < nrefgrp; i++) { pbc_dx(&pbc, x[a0+srefat], bCom ? xref : x[index[0][i]], trial); rtry2 = norm2(trial); if (i == 0 || rtry2 < rdx2) { copy_rvec(trial, dx); rdx2 = rtry2; } } if (rdx2 < rcut2) { hist[(int)(sqrt(rdx2)*invbw)+1]++; } if (rdx2 >= rmin2 && rdx2 < rmax2) { unitv(dx, dx); clear_rvec(dip); qav = 0; for (a = a0; a < a1; a++) { qav += atom[a].q; } qav /= (a1 - a0); for (a = a0; a < a1; a++) { q = atom[a].q - qav; for (d = 0; d < DIM; d++) { dip[d] += q*x[a][d]; } } for (d = 0; d < DIM; d++) { dir[d] = -x[a0][d]; } for (a = a0+1; a < a0+3; a++) { for (d = 0; d < DIM; d++) { dir[d] += 0.5*x[a][d]; } } unitv(dir, dir); svmul(ENM2DEBYE, dip, dip); dip2 = norm2(dip); sdip += sqrt(dip2); sdip2 += dip2; for (d = 0; d < DIM; d++) { sinp += dx[d]*dip[d]; sdinp += dx[d]*(dip[d] - refdip*dir[d]); } ntot++; } } nf++; } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); /* clean up */ sfree(x); close_trj(status); fprintf(stderr, "Average number of molecules within %g nm is %.1f\n", rmax, (real)ntot/(real)nf); if (ntot > 0) { sdip /= ntot; sdip2 /= ntot; sinp /= ntot; sdinp /= ntot; fprintf(stderr, "Average dipole: %f (D), std.dev. %f\n", sdip, sqrt(sdip2-sqr(sdip))); fprintf(stderr, "Average radial component of the dipole: %f (D)\n", sinp); fprintf(stderr, "Average radial component of the polarization: %f (D)\n", sdinp); } fp = xvgropen(opt2fn("-o", NFILE, fnm), "Cumulative solvent distribution", "r (nm)", "molecules", oenv); nmol = 0; for (i = 0; i <= nbin; i++) { nmol += hist[i]; fprintf(fp, "%g %g\n", i*bw, nmol/nf); } ffclose(fp); do_view(oenv, opt2fn("-o", NFILE, fnm), NULL); return 0; }
int main(int argc, char *argv[]) { const char *desc[] = { "Do statistics on pair distance", "from an existing molecular dynamics trajectory." }; gmx_bool bGREC = FALSE; gmx_bool bTraj = FALSE; int i, j; rvec *x = NULL, *x_ref = NULL; matrix box; char buf[256]; t_topology top; output_env_t oenv; int ePBC; t_trxstatus *status; int natoms_trx; real t; t_filenm fnm[] = { { efTPS, NULL, NULL, ffREAD }, { efLOG, "-n", NULL, ffREAD }, { efTRX, "-f", NULL, ffOPTRD }, { efLOG, "-o", NULL, ffWRITE }, }; t_pargs pa[] = { { "-grec", FALSE, etBOOL, {&bGREC}, "Using GREC"} }; #define NFILE asize(fnm) #define NPA asize(pa) CopyRight(stderr, argv[0]); parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), buf, &top, &ePBC, &x_ref, NULL, box, TRUE); bTraj = opt2bSet("-f", NFILE, fnm); /* obtain GREC_FA */ int *GREC_ind; if (bGREC) { FILE *fgrec; fgrec = fopen("GREC", "r"); int grec_size; fscanf(fgrec, "%d", &grec_size); snew(GREC_ind, grec_size); for(i=0; i<grec_size; i++) fscanf(fgrec, "%d", GREC_ind + i); fclose(fgrec); } #define myIndex(i) (bGREC ? GREC_ind[i] : i) /* read index file */ FILE *findex; findex = fopen(opt2fn("-n", NFILE, fnm), "r"); int ind1, ind2; hashTable *h = Hash_init(113); while (fscanf(findex, "%d", &ind1) != EOF) { fscanf(findex, "%d", &ind2); Hash_insertKey(h, "dd", ind1, ind2); } fclose(findex); int size; void ***vectorKeyList; Hash_getSize(h, &size); snew(vectorKeyList, size); Hash_dump(h, NULL, NULL, NULL, NULL, vectorKeyList); printf("size=%d\n", size); /* set reference value from the topology file */ double diff; for(i=0; i< size; i++) { ind1 = *(int *)(vectorKeyList[i][0]); ind2 = *(int *)(vectorKeyList[i][1]); /* indicating coordinate data is missing in the topology file */ if(fabs(x_ref[myIndex(ind1)][0]) < 5e-6 && fabs(x_ref[myIndex(ind1)][1]) < 5e-6 && fabs(x_ref[myIndex(ind1)][2]) < 5e-6 ) continue; if(fabs(x_ref[myIndex(ind2)][0]) < 5e-6 && fabs(x_ref[myIndex(ind2)][1]) < 5e-6 && fabs(x_ref[myIndex(ind2)][2]) < 5e-6 ) continue; diff = 0; diff += (x_ref[myIndex(ind1)][0] - x_ref[myIndex(ind2)][0]) * (x_ref[myIndex(ind1)][0] - x_ref[myIndex(ind2)][0]); diff += (x_ref[myIndex(ind1)][1] - x_ref[myIndex(ind2)][1]) * (x_ref[myIndex(ind1)][1] - x_ref[myIndex(ind2)][1]); diff += (x_ref[myIndex(ind1)][2] - x_ref[myIndex(ind2)][2]) * (x_ref[myIndex(ind1)][2] - x_ref[myIndex(ind2)][2]); diff = sqrt(diff); Hash_setReferenceValue(h, diff, "dd", ind1, ind2); } if(bTraj) { /* 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); /* start looping over frames: */ do { for(i=0; i< size; i++) { ind1 = *(int *)(vectorKeyList[i][0]); ind2 = *(int *)(vectorKeyList[i][1]); diff = 0; diff += (x[myIndex(ind1)][0] - x[myIndex(ind2)][0]) * (x[myIndex(ind1)][0] - x[myIndex(ind2)][0]); diff += (x[myIndex(ind1)][1] - x[myIndex(ind2)][1]) * (x[myIndex(ind1)][1] - x[myIndex(ind2)][1]); diff += (x[myIndex(ind1)][2] - x[myIndex(ind2)][2]) * (x[myIndex(ind1)][2] - x[myIndex(ind2)][2]); diff = sqrt(diff); Hash_addData(h, diff, "dd", ind1, ind2); } } while (read_next_x(oenv, status, &t, natoms_trx, x, box)); close_trj(status); } /* output the statistics */ FILE *fopt; fopt = fopen(opt2fn("-o", NFILE, fnm), "w"); double **a; snew(a, size); for(i=0; i<size; i++) snew(a[i], 3); Hash_dump(h, a, NULL, NULL, NULL, NULL); for(i=0; i<size; i++) { ind1 = *(int *)(vectorKeyList[i][0]); ind2 = *(int *)(vectorKeyList[i][1]); /* using standard deviation */ fprintf(fopt, "%4d %4d %13.6f %13.6f %13.6f\n", ind1, ind2, a[i][0], sqrt(a[i][1]), a[i][2]); } fclose(fopt); Hash_del(h); sfree(x_ref); sfree(x); sfree(GREC_ind); sfree(vectorKeyList); for(i=0; i<size; i++) sfree(a[i]); sfree(a); }
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; 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_rmsdist(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the root mean square deviation of atom distances,", "which has the advantage that no fit is needed like in standard RMS", "deviation as computed by [gmx-rms].", "The reference structure is taken from the structure file.", "The RMSD at time t is calculated as the RMS", "of the differences in distance between atom-pairs in the reference", "structure and the structure at time t.[PAR]", "[THISMODULE] can also produce matrices of the rms distances, rms distances", "scaled with the mean distance and the mean distances and matrices with", "NMR averaged distances (1/r^3 and 1/r^6 averaging). Finally, lists", "of atom pairs with 1/r^3 and 1/r^6 averaged distance below the", "maximum distance ([TT]-max[tt], which will default to 0.6 in this case)", "can be generated, by default averaging over equivalent hydrogens", "(all triplets of hydrogens named \\*[123]). Additionally a list of", "equivalent atoms can be supplied ([TT]-equiv[tt]), each line containing", "a set of equivalent atoms specified as residue number and name and", "atom name; e.g.:[PAR]", "[TT]HB* 3 SER HB1 3 SER HB2[tt][PAR]", "Residue and atom names must exactly match those in the structure", "file, including case. Specifying non-sequential atoms is undefined." }; int natom, i, j, teller, gi, gj; real t; t_topology top; int ePBC; t_atoms *atoms; matrix box; rvec *x; FILE *fp; t_trxstatus *status; int isize, gnr = 0; atom_id *index, *noe_index; char *grpname; real **d_r, **d, **dtot, **dtot2, **mean, **rms, **rmsc, *resnr; real **dtot1_3 = NULL, **dtot1_6 = NULL; real rmsnow, meanmax, rmsmax, rmscmax; real max1_3, max1_6; t_noe_gr *noe_gr = NULL; t_noe **noe = NULL; t_rgb rlo, rhi; char buf[255]; gmx_bool bRMS, bScale, bMean, bNOE, bNMR3, bNMR6, bNMR; static int nlevels = 40; static real scalemax = -1.0; static gmx_bool bSumH = TRUE; static gmx_bool bPBC = TRUE; output_env_t oenv; t_pargs pa[] = { { "-nlevels", FALSE, etINT, {&nlevels}, "Discretize RMS in this number of levels" }, { "-max", FALSE, etREAL, {&scalemax}, "Maximum level in matrices" }, { "-sumh", FALSE, etBOOL, {&bSumH}, "Average distance over equivalent hydrogens" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Use periodic boundary conditions when computing distances" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-equiv", "equiv", ffOPTRD }, { efXVG, NULL, "distrmsd", ffWRITE }, { efXPM, "-rms", "rmsdist", ffOPTWR }, { efXPM, "-scl", "rmsscale", ffOPTWR }, { efXPM, "-mean", "rmsmean", ffOPTWR }, { efXPM, "-nmr3", "nmr3", ffOPTWR }, { efXPM, "-nmr6", "nmr6", ffOPTWR }, { efDAT, "-noe", "noe", ffOPTWR }, }; #define NFILE asize(fnm) 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; } bRMS = opt2bSet("-rms", NFILE, fnm); bScale = opt2bSet("-scl", NFILE, fnm); bMean = opt2bSet("-mean", NFILE, fnm); bNOE = opt2bSet("-noe", NFILE, fnm); bNMR3 = opt2bSet("-nmr3", NFILE, fnm); bNMR6 = opt2bSet("-nmr6", NFILE, fnm); bNMR = bNMR3 || bNMR6 || bNOE; max1_3 = 0; max1_6 = 0; /* check input */ if (bNOE && scalemax < 0) { scalemax = 0.6; fprintf(stderr, "WARNING: using -noe without -max " "makes no sense, setting -max to %g\n\n", scalemax); } /* get topology and index */ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), buf, &top, &ePBC, &x, NULL, box, FALSE); if (!bPBC) { ePBC = epbcNONE; } atoms = &(top.atoms); get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); /* initialize arrays */ snew(d, isize); snew(dtot, isize); snew(dtot2, isize); if (bNMR) { snew(dtot1_3, isize); snew(dtot1_6, isize); } snew(mean, isize); snew(rms, isize); snew(rmsc, isize); snew(d_r, isize); snew(resnr, isize); for (i = 0; (i < isize); i++) { snew(d[i], isize); snew(dtot[i], isize); snew(dtot2[i], isize); if (bNMR) { snew(dtot1_3[i], isize); snew(dtot1_6[i], isize); } snew(mean[i], isize); snew(rms[i], isize); snew(rmsc[i], isize); snew(d_r[i], isize); resnr[i] = i+1; } /*set box type*/ calc_dist(isize, index, x, ePBC, box, d_r); sfree(x); /*open output files*/ fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "RMS Deviation", "Time (ps)", "RMSD (nm)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"of distances between %s atoms\"\n", grpname); } /*do a first step*/ natom = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); teller = 0; do { calc_dist_tot(isize, index, x, ePBC, box, d, dtot, dtot2, bNMR, dtot1_3, dtot1_6); rmsnow = rms_diff(isize, d, d_r); fprintf(fp, "%g %g\n", t, rmsnow); teller++; } while (read_next_x(oenv, status, &t, x, box)); fprintf(stderr, "\n"); xvgrclose(fp); close_trj(status); calc_rms(isize, teller, dtot, dtot2, mean, &meanmax, rms, &rmsmax, rmsc, &rmscmax); fprintf(stderr, "rmsmax = %g, rmscmax = %g\n", rmsmax, rmscmax); if (bNMR) { calc_nmr(isize, teller, dtot1_3, dtot1_6, &max1_3, &max1_6); } if (scalemax > -1.0) { rmsmax = scalemax; rmscmax = scalemax; meanmax = scalemax; max1_3 = scalemax; max1_6 = scalemax; } if (bNOE) { /* make list of noe atom groups */ snew(noe_index, isize+1); snew(noe_gr, isize); gnr = analyze_noe_equivalent(opt2fn_null("-equiv", NFILE, fnm), atoms, isize, index, bSumH, noe_index, noe_gr); fprintf(stdout, "Found %d non-equivalent atom-groups in %d atoms\n", gnr, isize); /* make half matrix of of noe-group distances from atom distances */ snew(noe, gnr); for (i = 0; i < gnr; i++) { snew(noe[i], gnr); } calc_noe(isize, noe_index, dtot1_3, dtot1_6, gnr, noe); } rlo.r = 1.0, rlo.g = 1.0, rlo.b = 1.0; rhi.r = 0.0, rhi.g = 0.0, rhi.b = 0.0; if (bRMS) { write_xpm(opt2FILE("-rms", NFILE, fnm, "w"), 0, "RMS of distance", "RMS (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, rms, 0.0, rmsmax, rlo, rhi, &nlevels); } if (bScale) { write_xpm(opt2FILE("-scl", NFILE, fnm, "w"), 0, "Relative RMS", "RMS", "Atom Index", "Atom Index", isize, isize, resnr, resnr, rmsc, 0.0, rmscmax, rlo, rhi, &nlevels); } if (bMean) { write_xpm(opt2FILE("-mean", NFILE, fnm, "w"), 0, "Mean Distance", "Distance (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, mean, 0.0, meanmax, rlo, rhi, &nlevels); } if (bNMR3) { write_xpm(opt2FILE("-nmr3", NFILE, fnm, "w"), 0, "1/r^3 averaged distances", "Distance (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, dtot1_3, 0.0, max1_3, rlo, rhi, &nlevels); } if (bNMR6) { write_xpm(opt2FILE("-nmr6", NFILE, fnm, "w"), 0, "1/r^6 averaged distances", "Distance (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, dtot1_6, 0.0, max1_6, rlo, rhi, &nlevels); } if (bNOE) { write_noe(opt2FILE("-noe", NFILE, fnm, "w"), gnr, noe, noe_gr, scalemax); } do_view(oenv, ftp2fn(efXVG, NFILE, fnm), NULL); return 0; }
int gmx_disre(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes violations of distance restraints.", "If necessary, all protons can be added to a protein molecule ", "using the [gmx-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 [REF].pdb[ref] 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_fcdata fcd; t_nrnb nrnb; 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[] = { { efTPR, 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) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } fplog = ftp2FILE(efLOG, NFILE, fnm, "w"); if (ntop) { init5(ntop); } read_tpxheader(ftp2fn(efTPR, NFILE, fnm), &header, FALSE, NULL, NULL); snew(xtop, header.natoms); read_tpx(ftp2fn(efTPR, 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)) { /* TODO: Nothing is written to this file if -c is provided, but it is * still opened... */ rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); xvg = xvgropen(opt2fn("-dr", NFILE, fnm), "Individual 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, &fcd, NULL, FALSE); 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, mtop.natoms, mdatoms); update_mdatoms(mdatoms, ir.fepvals->init_lambda); init_nrnb(&nrnb); if (ir.ePBC != epbcNONE) { gpbc = gmx_rmpbc_init(&top->idef, ir.ePBC, natoms); } 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, &(top->idef.il[F_DISRES]), top->idef.iparams, x, f, pbc_null, g, dr_clust, my_clust, isize, index, vvindex, &fcd); } else { check_viol(fplog, &(top->idef.il[F_DISRES]), top->idef.iparams, x, f, 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, 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); xvgrclose(out); xvgrclose(aver); xvgrclose(numv); xvgrclose(maxxv); 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"); } if (isize > 0) { xvgrclose(xvg); if (!clust) { do_view(oenv, opt2fn("-dr", NFILE, fnm), "-nxy"); } } gmx_log_close(fplog); return 0; }
int main(int argc,char *argv[]) { const char *desc[] = { "do_dssp ", "reads a trajectory file and computes the secondary structure for", "each time frame ", "calling the dssp program. If you do not have the dssp program,", "get it. do_dssp assumes that the dssp executable is", "/usr/local/bin/dssp. If this is not the case, then you should", "set an environment variable [BB]DSSP[bb] pointing to the dssp", "executable, e.g.: [PAR]", "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]", "The structure assignment for each residue and time is written to an", "[TT].xpm[tt] matrix file. This file can be visualized with for instance", "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].", "Individual chains are separated by light grey lines in the xpm and", "postscript files.", "The number of residues with each secondary structure type and the", "total secondary structure ([TT]-sss[tt]) count as a function of", "time are also written to file ([TT]-sc[tt]).[PAR]", "Solvent accessible surface (SAS) per residue can be calculated, both in", "absolute values (A^2) and in fractions of the maximal accessible", "surface of a residue. The maximal accessible surface is defined as", "the accessible surface of a residue in a chain of glycines.", "[BB]Note[bb] that the program [TT]g_sas[tt] can also compute SAS", "and that is more efficient.[PAR]", "Finally, this program can dump the secondary structure in a special file", "[TT]ssdump.dat[tt] for usage in the program [TT]g_chi[tt]. Together", "these two programs can be used to analyze dihedral properties as a", "function of secondary structure type." }; static bool bVerbose; static const char *ss_string="HEBT"; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "HIDDENGenerate miles of useless information" }, { "-sss", FALSE, etSTR, {&ss_string}, "Secondary structures for structure count"} }; int status; FILE *tapein; FILE *ss,*acc,*fTArea,*tmpf; char *fnSCount,*fnArea,*fnTArea,*fnAArea; char *leg[] = { "Phobic", "Phylic" }; t_topology top; int ePBC; t_atoms *atoms; t_matrix mat; int nres,nr0,naccr,nres_plus_separators; bool *bPhbres,bDoAccSurf; real t; int i,natoms,nframe=0; matrix box; int gnx; char *grpnm,*ss_str; atom_id *index; rvec *xp,*x; int *average_area; real **accr,*accr_ptr=NULL,*av_area, *norm_av_area; char pdbfile[32],tmpfile[32],title[256]; char dssp[256]; const char *dptr; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-ssdump", "ssdump", ffOPTWR }, { efMAP, "-map", "ss", ffLIBRD }, { efXPM, "-o", "ss", ffWRITE }, { efXVG, "-sc", "scount", ffWRITE }, { efXPM, "-a", "area", ffOPTWR }, { efXVG, "-ta", "totarea", ffOPTWR }, { efXVG, "-aa", "averarea",ffOPTWR } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT | PCA_BE_NICE , NFILE,fnm, asize(pa),pa, asize(desc),desc,0,NULL); fnSCount= opt2fn("-sc",NFILE,fnm); fnArea = opt2fn_null("-a", NFILE,fnm); fnTArea = opt2fn_null("-ta",NFILE,fnm); fnAArea = opt2fn_null("-aa",NFILE,fnm); bDoAccSurf=(fnArea || fnTArea || fnAArea); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xp,NULL,box,FALSE); atoms=&(top.atoms); check_oo(atoms); bPhbres=bPhobics(atoms); get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpnm); nres=0; nr0=-1; for(i=0; (i<gnx); i++) { if (atoms->atom[index[i]].resind != nr0) { nr0=atoms->atom[index[i]].resind; nres++; } } fprintf(stderr,"There are %d residues in your selected group\n",nres); strcpy(pdbfile,"ddXXXXXX"); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile,"w")) == NULL) { sprintf(pdbfile,"%ctmp%cfilterXXXXXX",DIR_SEPARATOR,DIR_SEPARATOR); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile,"w")) == NULL) gmx_fatal(FARGS,"Can not open tmp file %s",pdbfile); } else fclose(tmpf); strcpy(tmpfile,"ddXXXXXX"); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile,"w")) == NULL) { sprintf(tmpfile,"%ctmp%cfilterXXXXXX",DIR_SEPARATOR,DIR_SEPARATOR); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile,"w")) == NULL) gmx_fatal(FARGS,"Can not open tmp file %s",tmpfile); } else fclose(tmpf); if ((dptr=getenv("DSSP")) == NULL) dptr="/usr/local/bin/dssp"; if (!gmx_fexist(dptr)) gmx_fatal(FARGS,"DSSP executable (%s) does not exist (use setenv DSSP)", dptr); sprintf(dssp,"%s %s %s %s > /dev/null %s", dptr,bDoAccSurf?"":"-na",pdbfile,tmpfile,bVerbose?"":"2> /dev/null"); if (bVerbose) fprintf(stderr,"dssp cmd='%s'\n",dssp); if (fnTArea) { fTArea=xvgropen(fnTArea,"Solvent Accessible Surface Area", xvgr_tlabel(),"Area (nm\\S2\\N)"); xvgr_legend(fTArea,2,leg); } else fTArea=NULL; mat.map=NULL; mat.nmap=getcmap(libopen(opt2fn("-map",NFILE,fnm)), opt2fn("-map",NFILE,fnm),&(mat.map)); natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (natoms > atoms->nr) gmx_fatal(FARGS,"\nTrajectory does not match topology!"); if (gnx > natoms) gmx_fatal(FARGS,"\nTrajectory does not match selected group!"); snew(average_area, atoms->nres); snew(av_area , atoms->nres); snew(norm_av_area, atoms->nres); accr=NULL; naccr=0; do { t = convert_time(t); if (bDoAccSurf && nframe>=naccr) { naccr+=10; srenew(accr,naccr); for(i=naccr-10; i<naccr; i++) snew(accr[i],2*atoms->nres-1); } rm_pbc(&(top.idef),ePBC,natoms,box,x,x); tapein=ffopen(pdbfile,"w"); write_pdbfile_indexed(tapein,NULL,atoms,x,ePBC,box,0,-1,gnx,index,NULL); fclose(tapein); #ifdef GMX_NO_SYSTEM printf("Warning-- No calls to system(3) supported on this platform."); printf("Warning-- Skipping execution of 'system(\"%s\")'.", dssp); exit(1); #else if(0 != system(dssp)) { gmx_fatal(FARGS,"Failed to execute command: %s",dssp); } #endif /* strip_dssp returns the number of lines found in the dssp file, i.e. * the number of residues plus the separator lines */ if (bDoAccSurf) accr_ptr = accr[nframe]; nres_plus_separators = strip_dssp(tmpfile,nres,bPhbres,t, accr_ptr,fTArea,&mat,average_area); remove(tmpfile); remove(pdbfile); nframe++; } while(read_next_x(status,&t,natoms,x,box)); fprintf(stderr,"\n"); close_trj(status); if (fTArea) ffclose(fTArea); prune_ss_legend(&mat); ss=opt2FILE("-o",NFILE,fnm,"w"); mat.flags = 0; write_xpm_m(ss,mat); ffclose(ss); if (opt2bSet("-ssdump",NFILE,fnm)) { snew(ss_str,nres+1); for(i=0; (i<nres); i++) ss_str[i] = mat.map[mat.matrix[0][i]].code.c1; ss_str[i] = '\0'; ss = opt2FILE("-ssdump",NFILE,fnm,"w"); fprintf(ss,"%d\n%s\n",nres,ss_str); fclose(ss); sfree(ss_str); } analyse_ss(fnSCount,&mat,ss_string); if (bDoAccSurf) { write_sas_mat(fnArea,accr,nframe,nres_plus_separators,&mat); for(i=0; i<atoms->nres; i++) av_area[i] = (average_area[i] / (real)nframe); norm_acc(atoms, nres, av_area, norm_av_area); if (fnAArea) { acc=xvgropen(fnAArea,"Average Accessible Area", "Residue","A\\S2"); for(i=0; (i<nres); i++) fprintf(acc,"%5d %10g %10g\n",i+1,av_area[i], norm_av_area[i]); ffclose(acc); } } view_all(NFILE, fnm); thanx(stderr); return 0; }
int gmx_do_dssp(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] ", "reads a trajectory file and computes the secondary structure for", "each time frame ", "calling the dssp program. If you do not have the dssp program,", "get it from http://swift.cmbi.ru.nl/gv/dssp. [THISMODULE] assumes ", "that the dssp executable is located in ", "[TT]/usr/local/bin/dssp[tt]. If this is not the case, then you should", "set an environment variable [TT]DSSP[tt] pointing to the dssp", "executable, e.g.: [PAR]", "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]", "Since version 2.0.0, dssp is invoked with a syntax that differs", "from earlier versions. If you have an older version of dssp,", "use the [TT]-ver[tt] option to direct do_dssp to use the older syntax.", "By default, do_dssp uses the syntax introduced with version 2.0.0.", "Even newer versions (which at the time of writing are not yet released)", "are assumed to have the same syntax as 2.0.0.[PAR]", "The structure assignment for each residue and time is written to an", "[TT].xpm[tt] matrix file. This file can be visualized with for instance", "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].", "Individual chains are separated by light grey lines in the [TT].xpm[tt] and", "postscript files.", "The number of residues with each secondary structure type and the", "total secondary structure ([TT]-sss[tt]) count as a function of", "time are also written to file ([TT]-sc[tt]).[PAR]", "Solvent accessible surface (SAS) per residue can be calculated, both in", "absolute values (A^2) and in fractions of the maximal accessible", "surface of a residue. The maximal accessible surface is defined as", "the accessible surface of a residue in a chain of glycines.", "[BB]Note[bb] that the program [gmx-sas] can also compute SAS", "and that is more efficient.[PAR]", "Finally, this program can dump the secondary structure in a special file", "[TT]ssdump.dat[tt] for usage in the program [gmx-chi]. Together", "these two programs can be used to analyze dihedral properties as a", "function of secondary structure type." }; static gmx_bool bVerbose; static const char *ss_string = "HEBT"; static int dsspVersion = 2; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "HIDDENGenerate miles of useless information" }, { "-sss", FALSE, etSTR, {&ss_string}, "Secondary structures for structure count"}, { "-ver", FALSE, etINT, {&dsspVersion}, "DSSP major version. Syntax changed with version 2"} }; t_trxstatus *status; FILE *tapein; FILE *ss, *acc, *fTArea, *tmpf; const char *fnSCount, *fnArea, *fnTArea, *fnAArea; const char *leg[] = { "Phobic", "Phylic" }; t_topology top; int ePBC; t_atoms *atoms; t_matrix mat; int nres, nr0, naccr, nres_plus_separators; gmx_bool *bPhbres, bDoAccSurf; real t; int i, j, natoms, nframe = 0; matrix box; int gnx; char *grpnm, *ss_str; atom_id *index; rvec *xp, *x; int *average_area; real **accr, *accr_ptr = NULL, *av_area, *norm_av_area; char pdbfile[32], tmpfile[32], title[256]; char dssp[256]; const char *dptr; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-ssdump", "ssdump", ffOPTWR }, { efMAP, "-map", "ss", ffLIBRD }, { efXPM, "-o", "ss", ffWRITE }, { efXVG, "-sc", "scount", ffWRITE }, { efXPM, "-a", "area", ffOPTWR }, { efXVG, "-ta", "totarea", ffOPTWR }, { efXVG, "-aa", "averarea", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } fnSCount = opt2fn("-sc", NFILE, fnm); fnArea = opt2fn_null("-a", NFILE, fnm); fnTArea = opt2fn_null("-ta", NFILE, fnm); fnAArea = opt2fn_null("-aa", NFILE, fnm); bDoAccSurf = (fnArea || fnTArea || fnAArea); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xp, NULL, box, FALSE); atoms = &(top.atoms); check_oo(atoms); bPhbres = bPhobics(atoms); get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpnm); nres = 0; nr0 = -1; for (i = 0; (i < gnx); i++) { if (atoms->atom[index[i]].resind != nr0) { nr0 = atoms->atom[index[i]].resind; nres++; } } fprintf(stderr, "There are %d residues in your selected group\n", nres); strcpy(pdbfile, "ddXXXXXX"); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile, "w")) == NULL) { sprintf(pdbfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile, "w")) == NULL) { gmx_fatal(FARGS, "Can not open tmp file %s", pdbfile); } } else { fclose(tmpf); } strcpy(tmpfile, "ddXXXXXX"); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile, "w")) == NULL) { sprintf(tmpfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile, "w")) == NULL) { gmx_fatal(FARGS, "Can not open tmp file %s", tmpfile); } } else { fclose(tmpf); } if ((dptr = getenv("DSSP")) == NULL) { dptr = "/usr/local/bin/dssp"; } if (!gmx_fexist(dptr)) { gmx_fatal(FARGS, "DSSP executable (%s) does not exist (use setenv DSSP)", dptr); } if (dsspVersion >= 2) { if (dsspVersion > 2) { printf("\nWARNING: You use DSSP version %d, which is not explicitly\nsupported by do_dssp. Assuming version 2 syntax.\n\n", dsspVersion); } sprintf(dssp, "%s -i %s -o %s > /dev/null %s", dptr, pdbfile, tmpfile, bVerbose ? "" : "2> /dev/null"); } else { sprintf(dssp, "%s %s %s %s > /dev/null %s", dptr, bDoAccSurf ? "" : "-na", pdbfile, tmpfile, bVerbose ? "" : "2> /dev/null"); } fprintf(stderr, "dssp cmd='%s'\n", dssp); if (fnTArea) { fTArea = xvgropen(fnTArea, "Solvent Accessible Surface Area", output_env_get_xvgr_tlabel(oenv), "Area (nm\\S2\\N)", oenv); xvgr_legend(fTArea, 2, leg, oenv); } else { fTArea = NULL; } mat.map = NULL; mat.nmap = getcmap(libopen(opt2fn("-map", NFILE, fnm)), opt2fn("-map", NFILE, fnm), &(mat.map)); natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); if (natoms > atoms->nr) { gmx_fatal(FARGS, "\nTrajectory does not match topology!"); } if (gnx > natoms) { gmx_fatal(FARGS, "\nTrajectory does not match selected group!"); } snew(average_area, atoms->nres); snew(av_area, atoms->nres); snew(norm_av_area, atoms->nres); accr = NULL; naccr = 0; gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); do { t = output_env_conv_time(oenv, t); if (bDoAccSurf && nframe >= naccr) { naccr += 10; srenew(accr, naccr); for (i = naccr-10; i < naccr; i++) { snew(accr[i], 2*atoms->nres-1); } } gmx_rmpbc(gpbc, natoms, box, x); tapein = gmx_ffopen(pdbfile, "w"); write_pdbfile_indexed(tapein, NULL, atoms, x, ePBC, box, ' ', -1, gnx, index, NULL, TRUE); gmx_ffclose(tapein); #ifdef GMX_NO_SYSTEM printf("Warning-- No calls to system(3) supported on this platform."); printf("Warning-- Skipping execution of 'system(\"%s\")'.", dssp); exit(1); #else if (0 != system(dssp)) { gmx_fatal(FARGS, "Failed to execute command: %s\n", "Try specifying your dssp version with the -ver option.", dssp); } #endif /* strip_dssp returns the number of lines found in the dssp file, i.e. * the number of residues plus the separator lines */ if (bDoAccSurf) { accr_ptr = accr[nframe]; } nres_plus_separators = strip_dssp(tmpfile, nres, bPhbres, t, accr_ptr, fTArea, &mat, average_area, oenv); remove(tmpfile); remove(pdbfile); nframe++; } while (read_next_x(oenv, status, &t, x, box)); fprintf(stderr, "\n"); close_trj(status); if (fTArea) { gmx_ffclose(fTArea); } gmx_rmpbc_done(gpbc); prune_ss_legend(&mat); ss = opt2FILE("-o", NFILE, fnm, "w"); mat.flags = 0; write_xpm_m(ss, mat); gmx_ffclose(ss); if (opt2bSet("-ssdump", NFILE, fnm)) { ss = opt2FILE("-ssdump", NFILE, fnm, "w"); snew(ss_str, nres+1); fprintf(ss, "%d\n", nres); for (j = 0; j < mat.nx; j++) { for (i = 0; (i < mat.ny); i++) { ss_str[i] = mat.map[mat.matrix[j][i]].code.c1; } ss_str[i] = '\0'; fprintf(ss, "%s\n", ss_str); } gmx_ffclose(ss); sfree(ss_str); } analyse_ss(fnSCount, &mat, ss_string, oenv); if (bDoAccSurf) { write_sas_mat(fnArea, accr, nframe, nres_plus_separators, &mat); for (i = 0; i < atoms->nres; i++) { av_area[i] = (average_area[i] / (real)nframe); } norm_acc(atoms, nres, av_area, norm_av_area); if (fnAArea) { acc = xvgropen(fnAArea, "Average Accessible Area", "Residue", "A\\S2", oenv); for (i = 0; (i < nres); i++) { fprintf(acc, "%5d %10g %10g\n", i+1, av_area[i], norm_av_area[i]); } gmx_ffclose(acc); } } view_all(oenv, NFILE, fnm); return 0; }
static void get_refx(output_env_t oenv, const char *trxfn, int nfitdim, int skip, int gnx, int *index, gmx_bool bMW, t_topology *top, int ePBC, rvec *x_ref) { int natoms, nfr_all, nfr, i, j, a, r, c, min_fr; t_trxstatus *status; real *ti, min_t; double tot_mass, msd, *srmsd, min_srmsd, srmsd_tot; rvec *x, **xi; real xf; matrix box, R; real *w_rls; gmx_rmpbc_t gpbc = NULL; nfr_all = 0; nfr = 0; snew(ti, 100); snew(xi, 100); natoms = read_first_x(oenv, &status, trxfn, &ti[nfr], &x, box); snew(w_rls, gnx); tot_mass = 0; for (a = 0; a < gnx; a++) { if (index[a] >= natoms) { gmx_fatal(FARGS, "Atom index (%d) is larger than the number of atoms in the trajecory (%d)", index[a]+1, natoms); } w_rls[a] = (bMW ? top->atoms.atom[index[a]].m : 1.0); tot_mass += w_rls[a]; } gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); do { if (nfr_all % skip == 0) { gmx_rmpbc(gpbc, natoms, box, x); snew(xi[nfr], gnx); for (i = 0; i < gnx; i++) { copy_rvec(x[index[i]], xi[nfr][i]); } reset_x(gnx, NULL, gnx, NULL, xi[nfr], w_rls); nfr++; if (nfr % 100 == 0) { srenew(ti, nfr+100); srenew(xi, nfr+100); } } nfr_all++; } while (read_next_x(oenv, status, &ti[nfr], x, box)); close_trj(status); sfree(x); gmx_rmpbc_done(gpbc); snew(srmsd, nfr); for (i = 0; i < nfr; i++) { printf("\rProcessing frame %d of %d", i, nfr); for (j = i+1; j < nfr; j++) { calc_fit_R(nfitdim, gnx, w_rls, xi[i], xi[j], R); msd = 0; for (a = 0; a < gnx; a++) { for (r = 0; r < DIM; r++) { xf = 0; for (c = 0; c < DIM; c++) { xf += R[r][c]*xi[j][a][c]; } msd += w_rls[a]*sqr(xi[i][a][r] - xf); } } msd /= tot_mass; srmsd[i] += sqrt(msd); srmsd[j] += sqrt(msd); } sfree(xi[i]); } printf("\n"); sfree(w_rls); min_srmsd = GMX_REAL_MAX; min_fr = -1; min_t = -1; srmsd_tot = 0; for (i = 0; i < nfr; i++) { srmsd[i] /= (nfr - 1); if (srmsd[i] < min_srmsd) { min_srmsd = srmsd[i]; min_fr = i; min_t = ti[i]; } srmsd_tot += srmsd[i]; } sfree(srmsd); printf("Average RMSD between all structures: %.3f\n", srmsd_tot/nfr); printf("Structure with lowest RMSD to all others: time %g, av. RMSD %.3f\n", min_t, min_srmsd); for (a = 0; a < gnx; a++) { copy_rvec(xi[min_fr][a], x_ref[index[a]]); } sfree(xi); }
void read_ang_dih(const char *trj_fn, gmx_bool bAngles, gmx_bool bSaveAll, gmx_bool bRb, gmx_bool bPBC, int maxangstat, int angstat[], int *nframes, real **time, int isize, atom_id index[], real **trans_frac, real **aver_angle, real *dih[], const output_env_t oenv) { t_pbc *pbc; t_trxstatus *status; int i, angind, natoms, total, teller; int nangles, n_alloc; real t, fraction, pifac, aa, angle; real *angles[2]; matrix box; rvec *x; int cur = 0; #define prev (1-cur) snew(pbc, 1); natoms = read_first_x(oenv, &status, trj_fn, &t, &x, box); if (bAngles) { nangles = isize/3; pifac = M_PI; } else { nangles = isize/4; pifac = 2.0*M_PI; } snew(angles[cur], nangles); snew(angles[prev], nangles); /* Start the loop over frames */ total = 0; teller = 0; n_alloc = 0; *time = NULL; *trans_frac = NULL; *aver_angle = NULL; do { if (teller >= n_alloc) { n_alloc += 100; if (bSaveAll) { for (i = 0; (i < nangles); i++) { srenew(dih[i], n_alloc); } } srenew(*time, n_alloc); srenew(*trans_frac, n_alloc); srenew(*aver_angle, n_alloc); } (*time)[teller] = t; if (pbc) { set_pbc(pbc, -1, box); } if (bAngles) { calc_angles(pbc, isize, index, angles[cur], x); } else { calc_dihs(pbc, isize, index, angles[cur], x); /* Trans fraction */ fraction = calc_fraction(angles[cur], nangles); (*trans_frac)[teller] = fraction; /* Change Ryckaert-Bellemans dihedrals to polymer convention * Modified 990913 by Erik: * We actually shouldn't change the convention, since it's * calculated from polymer above, but we change the intervall * from [-180,180] to [0,360]. */ if (bRb) { for (i = 0; (i < nangles); i++) { if (angles[cur][i] <= 0.0) { angles[cur][i] += 2*M_PI; } } } /* Periodicity in dihedral space... */ if (bPBC) { for (i = 0; (i < nangles); i++) { real dd = angles[cur][i]; angles[cur][i] = atan2(sin(dd), cos(dd)); } } else { if (teller > 1) { for (i = 0; (i < nangles); i++) { while (angles[cur][i] <= angles[prev][i] - M_PI) { angles[cur][i] += 2*M_PI; } while (angles[cur][i] > angles[prev][i] + M_PI) { angles[cur][i] -= 2*M_PI; } } } } } /* Average angles */ aa = 0; for (i = 0; (i < nangles); i++) { aa = aa+angles[cur][i]; /* angle in rad / 2Pi * max determines bin. bins go from 0 to maxangstat, even though scale goes from -pi to pi (dihedral) or -pi/2 to pi/2 (angle) Basically: translate the x-axis by Pi. Translate it back by -Pi when plotting. */ angle = angles[cur][i]; if (!bAngles) { while (angle < -M_PI) { angle += 2*M_PI; } while (angle >= M_PI) { angle -= 2*M_PI; } angle += M_PI; } /* Update the distribution histogram */ angind = (int) ((angle*maxangstat)/pifac + 0.5); if (angind == maxangstat) { angind = 0; } if ( (angind < 0) || (angind >= maxangstat) ) { /* this will never happen */ gmx_fatal(FARGS, "angle (%f) index out of range (0..%d) : %d\n", angle, maxangstat, angind); } angstat[angind]++; if (angind == maxangstat) { fprintf(stderr, "angle %d fr %d = %g\n", i, cur, angle); } total++; } /* average over all angles */ (*aver_angle)[teller] = (aa/nangles); /* this copies all current dih. angles to dih[i], teller is frame */ if (bSaveAll) { for (i = 0; i < nangles; i++) { dih[i][teller] = angles[cur][i]; } } /* Swap buffers */ cur = prev; /* Increment loop counter */ teller++; } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); sfree(x); sfree(angles[cur]); sfree(angles[prev]); *nframes = teller; }
static void density_in_time (const char *fn, int **index, int gnx[], real bw, real bwz, int nsttblock, real *****Densdevel, int *xslices, int *yslices, int *zslices, int *tblock, const t_topology *top, int ePBC, int axis, gmx_bool bCenter, gmx_bool bps1d, const gmx_output_env_t *oenv) { /* * *****Densdevel pointer to array of density values in slices and frame-blocks Densdevel[*nsttblock][*xslices][*yslices][*zslices] * Densslice[x][y][z] * nsttblock - nr of frames in each time-block * bw widths of normal slices * * axis - axis direction (normal to slices) * nndx - number ot atoms in **index * grpn - group number in index */ t_trxstatus *status; gmx_rmpbc_t gpbc = nullptr; matrix box; /* Box - 3x3 -each step*/ rvec *x0; /* List of Coord without PBC*/ int i, j, /* loop indices, checks etc*/ ax1 = 0, ax2 = 0, /* tangent directions */ framenr = 0, /* frame number in trajectory*/ slicex, slicey, slicez; /*slice # of x y z position */ real ***Densslice = nullptr; /* Density-slice in one frame*/ real dscale; /*physical scaling factor*/ real t, x, y, z; /* time and coordinates*/ rvec bbww; *tblock = 0; /* blocknr in block average - initialise to 0*/ /* Axis: X=0, Y=1,Z=2 */ switch (axis) { case 0: ax1 = YY; ax2 = ZZ; /*Surface: YZ*/ break; case 1: ax1 = ZZ; ax2 = XX; /* Surface : XZ*/ break; case 2: ax1 = XX; ax2 = YY; /* Surface XY*/ break; default: gmx_fatal(FARGS, "Invalid axes. Terminating\n"); } if (read_first_x(oenv, &status, fn, &t, &x0, box) == 0) { gmx_fatal(FARGS, "Could not read coordinates from file"); /* Open trajectory for read*/ } *zslices = 1+static_cast<int>(std::floor(box[axis][axis]/bwz)); *yslices = 1+static_cast<int>(std::floor(box[ax2][ax2]/bw)); *xslices = 1+static_cast<int>(std::floor(box[ax1][ax1]/bw)); if (bps1d) { if (*xslices < *yslices) { *xslices = 1; } else { *yslices = 1; } } fprintf(stderr, "\nDividing the box in %5d x %5d x %5d slices with binw %f along axis %d\n", *xslices, *yslices, *zslices, bw, axis ); /****Start trajectory processing***/ /*Initialize Densdevel and PBC-remove*/ gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr); *Densdevel = nullptr; do { bbww[XX] = box[ax1][ax1]/ *xslices; bbww[YY] = box[ax2][ax2]/ *yslices; bbww[ZZ] = box[axis][axis]/ *zslices; gmx_rmpbc(gpbc, top->atoms.nr, box, x0); /*Reset Densslice every nsttblock steps*/ /* The first conditional is for clang to understand that this branch is * always taken the first time. */ if (Densslice == nullptr || framenr % nsttblock == 0) { snew(Densslice, *xslices); for (i = 0; i < *xslices; i++) { snew(Densslice[i], *yslices); for (j = 0; j < *yslices; j++) { snew(Densslice[i][j], *zslices); } } /* Allocate Memory to extra frame in Densdevel - rather stupid approach: * A single frame each time, although only every nsttblock steps. */ srenew(*Densdevel, *tblock+1); (*Densdevel)[*tblock] = Densslice; } dscale = (*xslices)*(*yslices)*(*zslices)*AMU/ (box[ax1][ax1]*box[ax2][ax2]*box[axis][axis]*nsttblock*(NANO*NANO*NANO)); if (bCenter) { center_coords(&top->atoms, box, x0, axis); } for (j = 0; j < gnx[0]; j++) { /*Loop over all atoms in selected index*/ x = x0[index[0][j]][ax1]; y = x0[index[0][j]][ax2]; z = x0[index[0][j]][axis]; while (x < 0) { x += box[ax1][ax1]; } while (x > box[ax1][ax1]) { x -= box[ax1][ax1]; } while (y < 0) { y += box[ax2][ax2]; } while (y > box[ax2][ax2]) { y -= box[ax2][ax2]; } while (z < 0) { z += box[axis][axis]; } while (z > box[axis][axis]) { z -= box[axis][axis]; } slicex = static_cast<int>(x/bbww[XX]) % *xslices; slicey = static_cast<int>(y/bbww[YY]) % *yslices; slicez = static_cast<int>(z/bbww[ZZ]) % *zslices; Densslice[slicex][slicey][slicez] += (top->atoms.atom[index[0][j]].m*dscale); } framenr++; if (framenr % nsttblock == 0) { /*Implicit incrementation of Densdevel via renewal of Densslice*/ /*only every nsttblock steps*/ (*tblock)++; } } while (read_next_x(oenv, status, &t, x0, box)); /*Free memory we no longer need and exit.*/ gmx_rmpbc_done(gpbc); close_trx(status); if (0) { FILE *fp; fp = fopen("koko.xvg", "w"); for (j = 0; (j < *zslices); j++) { fprintf(fp, "%5d", j); for (i = 0; (i < *tblock); i++) { fprintf(fp, " %10g", (*Densdevel)[i][9][1][j]); } fprintf(fp, "\n"); } fclose(fp); } }
int gmx_genconf(int argc, char *argv[]) { static char *desc[] = { "genconf multiplies a given coordinate file by simply stacking them", "on top of each other, like a small child playing with wooden blocks.", "The program makes a grid of [IT]user defined[it]", "proportions ([TT]-nbox[tt]), ", "and interspaces the grid point with an extra space [TT]-dist[tt].[PAR]", "When option [TT]-rot[tt] is used the program does not check for overlap", "between molecules on grid points. It is recommended to make the box in", "the input file at least as big as the coordinates + ", "Van der Waals radius.[PAR]", "If the optional trajectory file is given, conformations are not", "generated, but read from this file and translated appropriately to", "build the grid." }; static char *bugs[] = { "The program should allow for random displacement off lattice points." }; int vol; t_atoms *atoms; /* list with all atoms */ char title[STRLEN]; rvec *x,*xx,*v; /* coordinates? */ real t; vec4 *xrot,*vrot; int ePBC; matrix box,boxx; /* box length matrix */ rvec shift; int natoms; /* number of atoms in one molecule */ int nres; /* number of molecules? */ int i,j,k,l,m,ndx,nrdx,nx,ny,nz,status=-1; bool bTRX; t_filenm fnm[] = { { efSTX, "-f", "conf", ffREAD }, { efSTO, "-o", "out", ffWRITE }, { efTRX, "-trj",NULL, ffOPTRD } }; #define NFILE asize(fnm) static rvec nrbox = {1,1,1}; static int seed = 0; /* seed for random number generator */ static int nmolat = 3; static int nblock = 1; static bool bShuffle = FALSE; static bool bSort = FALSE; static bool bRandom = FALSE; /* False: no random rotations */ static bool bRenum = TRUE; /* renumber residues */ static rvec dist = {0,0,0}; /* space added between molecules ? */ static rvec max_rot = {180,180,180}; /* maximum rotation */ t_pargs pa[] = { { "-nbox", FALSE, etRVEC, {nrbox}, "Number of boxes" }, { "-dist", FALSE, etRVEC, {dist}, "Distance between boxes" }, { "-seed", FALSE, etINT, {&seed}, "Random generator seed, if 0 generated from the time" }, { "-rot", FALSE, etBOOL, {&bRandom}, "Randomly rotate conformations" }, { "-shuffle",FALSE, etBOOL, {&bShuffle},"Random shuffling of molecules" }, { "-sort", FALSE, etBOOL, {&bSort}, "Sort molecules on X coord" }, { "-block", FALSE, etINT, {&nblock}, "Divide the box in blocks on this number of cpus" }, { "-nmolat", FALSE, etINT, {&nmolat}, "Number of atoms per molecule, assumed to start from 0. " "If you set this wrong, it will screw up your system!" }, { "-maxrot", FALSE, etRVEC, {max_rot}, "Maximum random rotation" }, { "-renumber",FALSE,etBOOL, {&bRenum}, "Renumber residues" } }; CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa, asize(desc),desc,asize(bugs),bugs); if (bRandom && (seed == 0)) seed = make_seed(); bTRX = ftp2bSet(efTRX,NFILE,fnm); nx = (int)(nrbox[XX]+0.5); ny = (int)(nrbox[YY]+0.5); nz = (int)(nrbox[ZZ]+0.5); if ((nx <= 0) || (ny <= 0) || (nz <= 0)) gmx_fatal(FARGS,"Number of boxes (-nbox) should be larger than zero"); if ((nmolat <= 0) && bShuffle) gmx_fatal(FARGS,"Can not shuffle if the molecules only have %d atoms", nmolat); vol=nx*ny*nz; /* calculate volume in grid points (= nr. molecules) */ get_stx_coordnum(opt2fn("-f",NFILE,fnm),&natoms); snew(atoms,1); /* make space for all the atoms */ init_t_atoms(atoms,natoms*vol,FALSE); snew(x,natoms*vol); /* get space for coordinates of all atoms */ snew(xrot,natoms); /* get space for rotation matrix? */ snew(v,natoms*vol); /* velocities. not really needed? */ snew(vrot,natoms); /* set atoms->nr to the number in one box * * to avoid complaints in read_stx_conf * */ atoms->nr = natoms; read_stx_conf(opt2fn("-f",NFILE,fnm),title,atoms,x,v,&ePBC,box); nres=atoms->nres; /* nr of residues in one element? */ if (bTRX) { if (!read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&xx,boxx)) gmx_fatal(FARGS,"No atoms in trajectory %s",ftp2fn(efTRX,NFILE,fnm)); } else { snew(xx,natoms); for(i=0; i<natoms; i++) { copy_rvec(x[i],xx[i]); } } for(k=0; (k<nz); k++) { /* loop over all gridpositions */ shift[ZZ]=k*(dist[ZZ]+box[ZZ][ZZ]); for(j=0; (j<ny); j++) { shift[YY]=j*(dist[YY]+box[YY][YY])+k*box[ZZ][YY]; for(i=0; (i<nx); i++) { shift[XX]=i*(dist[XX]+box[XX][XX])+j*box[YY][XX]+k*box[ZZ][XX]; ndx=(i*ny*nz+j*nz+k)*natoms; nrdx=(i*ny*nz+j*nz+k)*nres; /* Random rotation on input coords */ if (bRandom) rand_rot(natoms,xx,v,xrot,vrot,&seed,max_rot); for(l=0; (l<natoms); l++) { for(m=0; (m<DIM); m++) { if (bRandom) { x[ndx+l][m] = xrot[l][m]; v[ndx+l][m] = vrot[l][m]; } else { x[ndx+l][m] = xx[l][m]; v[ndx+l][m] = v[l][m]; } } if (ePBC == epbcSCREW && i % 2 == 1) { /* Rotate around x axis */ for(m=YY; m<=ZZ; m++) { x[ndx+l][m] = box[YY][m] + box[ZZ][m] - x[ndx+l][m]; v[ndx+l][m] = -v[ndx+l][m]; } } for(m=0; (m<DIM); m++) { x[ndx+l][m] += shift[m]; } atoms->atom[ndx+l].resnr=(bRenum ? nrdx:0) + atoms->atom[l].resnr; atoms->atomname[ndx+l]=atoms->atomname[l]; } for(l=0; (l<nres); l++) atoms->resname[nrdx+l]=atoms->resname[l]; if (bTRX) if (!read_next_x(status,&t,natoms,xx,boxx) && ((i+1)*(j+1)*(k+1) < vol)) gmx_fatal(FARGS,"Not enough frames in trajectory"); } } } if (bTRX) close_trj(status); /* make box bigger */ for(m=0; (m<DIM); m++) box[m][m] += dist[m]; svmul(nx,box[XX],box[XX]); svmul(ny,box[YY],box[YY]); svmul(nz,box[ZZ],box[ZZ]); if (ePBC == epbcSCREW && nx % 2 == 0) { /* With an even number of boxes in x we can forgot about the screw */ ePBC = epbcXYZ; } /* move_x(natoms*vol,x,box); */ /* put atoms in box? */ atoms->nr*=vol; atoms->nres*=vol; if (bShuffle) randwater(0,atoms->nr/nmolat,nmolat,x,v,&seed); else if (bSort) sortwater(0,atoms->nr/nmolat,nmolat,x,v); else if (opt2parg_bSet("-block",asize(pa),pa)) mkcompact(0,atoms->nr/nmolat,nmolat,x,v,nblock,box); write_sto_conf(opt2fn("-o",NFILE,fnm),title,atoms,x,v,ePBC,box); thanx(stderr); return 0; }
int gmx_covar(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] calculates and diagonalizes the (mass-weighted)", "covariance matrix.", "All structures are fitted to the structure in the structure file.", "When this is not a run input file periodicity will not be taken into", "account. When the fit and analysis groups are identical and the analysis", "is non mass-weighted, the fit will also be non mass-weighted.", "[PAR]", "The eigenvectors are written to a trajectory file ([TT]-v[tt]).", "When the same atoms are used for the fit and the covariance analysis,", "the reference structure for the fit is written first with t=-1.", "The average (or reference when [TT]-ref[tt] is used) structure is", "written with t=0, the eigenvectors", "are written as frames with the eigenvector number as timestamp.", "[PAR]", "The eigenvectors can be analyzed with [gmx-anaeig].", "[PAR]", "Option [TT]-ascii[tt] writes the whole covariance matrix to", "an ASCII file. The order of the elements is: x1x1, x1y1, x1z1, x1x2, ...", "[PAR]", "Option [TT]-xpm[tt] writes the whole covariance matrix to an [REF].xpm[ref] file.", "[PAR]", "Option [TT]-xpma[tt] writes the atomic covariance matrix to an [REF].xpm[ref] file,", "i.e. for each atom pair the sum of the xx, yy and zz covariances is", "written.", "[PAR]", "Note that the diagonalization of a matrix requires memory and time", "that will increase at least as fast as than the square of the number", "of atoms involved. It is easy to run out of memory, in which", "case this tool will probably exit with a 'Segmentation fault'. You", "should consider carefully whether a reduced set of atoms will meet", "your needs for lower costs." }; static gmx_bool bFit = TRUE, bRef = FALSE, bM = FALSE, bPBC = TRUE; static int end = -1; t_pargs pa[] = { { "-fit", FALSE, etBOOL, {&bFit}, "Fit to a reference structure"}, { "-ref", FALSE, etBOOL, {&bRef}, "Use the deviation from the conformation in the structure file instead of from the average" }, { "-mwa", FALSE, etBOOL, {&bM}, "Mass-weighted covariance analysis"}, { "-last", FALSE, etINT, {&end}, "Last eigenvector to write away (-1 is till the last)" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Apply corrections for periodic boundary conditions" } }; FILE *out = NULL; /* initialization makes all compilers happy */ t_trxstatus *status; t_topology top; int ePBC; t_atoms *atoms; rvec *x, *xread, *xref, *xav, *xproj; matrix box, zerobox; real *sqrtm, *mat, *eigenvalues, sum, trace, inv_nframes; real t, tstart, tend, **mat2; real xj, *w_rls = NULL; real min, max, *axis; int natoms, nat, nframes0, nframes, nlevels; gmx_int64_t ndim, i, j, k, l; int WriteXref; const char *fitfile, *trxfile, *ndxfile; const char *eigvalfile, *eigvecfile, *averfile, *logfile; const char *asciifile, *xpmfile, *xpmafile; char str[STRLEN], *fitname, *ananame; int d, dj, nfit; atom_id *index, *ifit; gmx_bool bDiffMass1, bDiffMass2; char timebuf[STRLEN]; t_rgb rlo, rmi, rhi; real *eigenvectors; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "eigenval", ffWRITE }, { efTRN, "-v", "eigenvec", ffWRITE }, { efSTO, "-av", "average.pdb", ffWRITE }, { efLOG, NULL, "covar", ffWRITE }, { efDAT, "-ascii", "covar", ffOPTWR }, { efXPM, "-xpm", "covar", ffOPTWR }, { efXPM, "-xpma", "covara", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } clear_mat(zerobox); fitfile = ftp2fn(efTPS, NFILE, fnm); trxfile = ftp2fn(efTRX, NFILE, fnm); ndxfile = ftp2fn_null(efNDX, NFILE, fnm); eigvalfile = ftp2fn(efXVG, NFILE, fnm); eigvecfile = ftp2fn(efTRN, NFILE, fnm); averfile = ftp2fn(efSTO, NFILE, fnm); logfile = ftp2fn(efLOG, NFILE, fnm); asciifile = opt2fn_null("-ascii", NFILE, fnm); xpmfile = opt2fn_null("-xpm", NFILE, fnm); xpmafile = opt2fn_null("-xpma", NFILE, fnm); read_tps_conf(fitfile, &top, &ePBC, &xref, NULL, box, TRUE); atoms = &top.atoms; if (bFit) { printf("\nChoose a group for the least squares fit\n"); get_index(atoms, ndxfile, 1, &nfit, &ifit, &fitname); if (nfit < 3) { gmx_fatal(FARGS, "Need >= 3 points to fit!\n"); } } else { nfit = 0; } printf("\nChoose a group for the covariance analysis\n"); get_index(atoms, ndxfile, 1, &natoms, &index, &ananame); bDiffMass1 = FALSE; if (bFit) { snew(w_rls, atoms->nr); for (i = 0; (i < nfit); i++) { w_rls[ifit[i]] = atoms->atom[ifit[i]].m; if (i) { bDiffMass1 = bDiffMass1 || (w_rls[ifit[i]] != w_rls[ifit[i-1]]); } } } bDiffMass2 = FALSE; snew(sqrtm, natoms); for (i = 0; (i < natoms); i++) { if (bM) { sqrtm[i] = std::sqrt(atoms->atom[index[i]].m); if (i) { bDiffMass2 = bDiffMass2 || (sqrtm[i] != sqrtm[i-1]); } } else { sqrtm[i] = 1.0; } } if (bFit && bDiffMass1 && !bDiffMass2) { bDiffMass1 = natoms != nfit; for (i = 0; (i < natoms) && !bDiffMass1; i++) { bDiffMass1 = index[i] != ifit[i]; } if (!bDiffMass1) { fprintf(stderr, "\n" "Note: the fit and analysis group are identical,\n" " while the fit is mass weighted and the analysis is not.\n" " Making the fit non mass weighted.\n\n"); for (i = 0; (i < nfit); i++) { w_rls[ifit[i]] = 1.0; } } } /* Prepare reference frame */ if (bPBC) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, atoms->nr); gmx_rmpbc(gpbc, atoms->nr, box, xref); } if (bFit) { reset_x(nfit, ifit, atoms->nr, NULL, xref, w_rls); } snew(x, natoms); snew(xav, natoms); ndim = natoms*DIM; if (std::sqrt(static_cast<real>(GMX_INT64_MAX)) < static_cast<real>(ndim)) { gmx_fatal(FARGS, "Number of degrees of freedoms to large for matrix.\n"); } snew(mat, ndim*ndim); fprintf(stderr, "Calculating the average structure ...\n"); nframes0 = 0; nat = read_first_x(oenv, &status, trxfile, &t, &xread, box); if (nat != atoms->nr) { fprintf(stderr, "\nWARNING: number of atoms in tpx (%d) and trajectory (%d) do not match\n", natoms, nat); } do { nframes0++; /* calculate x: a fitted struture of the selected atoms */ if (bPBC) { gmx_rmpbc(gpbc, nat, box, xread); } if (bFit) { reset_x(nfit, ifit, nat, NULL, xread, w_rls); do_fit(nat, w_rls, xref, xread); } for (i = 0; i < natoms; i++) { rvec_inc(xav[i], xread[index[i]]); } } while (read_next_x(oenv, status, &t, xread, box)); close_trj(status); inv_nframes = 1.0/nframes0; for (i = 0; i < natoms; i++) { for (d = 0; d < DIM; d++) { xav[i][d] *= inv_nframes; xread[index[i]][d] = xav[i][d]; } } write_sto_conf_indexed(opt2fn("-av", NFILE, fnm), "Average structure", atoms, xread, NULL, epbcNONE, zerobox, natoms, index); sfree(xread); fprintf(stderr, "Constructing covariance matrix (%dx%d) ...\n", static_cast<int>(ndim), static_cast<int>(ndim)); nframes = 0; nat = read_first_x(oenv, &status, trxfile, &t, &xread, box); tstart = t; do { nframes++; tend = t; /* calculate x: a (fitted) structure of the selected atoms */ if (bPBC) { gmx_rmpbc(gpbc, nat, box, xread); } if (bFit) { reset_x(nfit, ifit, nat, NULL, xread, w_rls); do_fit(nat, w_rls, xref, xread); } if (bRef) { for (i = 0; i < natoms; i++) { rvec_sub(xread[index[i]], xref[index[i]], x[i]); } } else { for (i = 0; i < natoms; i++) { rvec_sub(xread[index[i]], xav[i], x[i]); } } for (j = 0; j < natoms; j++) { for (dj = 0; dj < DIM; dj++) { k = ndim*(DIM*j+dj); xj = x[j][dj]; for (i = j; i < natoms; i++) { l = k+DIM*i; for (d = 0; d < DIM; d++) { mat[l+d] += x[i][d]*xj; } } } } } while (read_next_x(oenv, status, &t, xread, box) && (bRef || nframes < nframes0)); close_trj(status); gmx_rmpbc_done(gpbc); fprintf(stderr, "Read %d frames\n", nframes); if (bRef) { /* copy the reference structure to the ouput array x */ snew(xproj, natoms); for (i = 0; i < natoms; i++) { copy_rvec(xref[index[i]], xproj[i]); } } else { xproj = xav; } /* correct the covariance matrix for the mass */ inv_nframes = 1.0/nframes; for (j = 0; j < natoms; j++) { for (dj = 0; dj < DIM; dj++) { for (i = j; i < natoms; i++) { k = ndim*(DIM*j+dj)+DIM*i; for (d = 0; d < DIM; d++) { mat[k+d] = mat[k+d]*inv_nframes*sqrtm[i]*sqrtm[j]; } } } } /* symmetrize the matrix */ for (j = 0; j < ndim; j++) { for (i = j; i < ndim; i++) { mat[ndim*i+j] = mat[ndim*j+i]; } } trace = 0; for (i = 0; i < ndim; i++) { trace += mat[i*ndim+i]; } fprintf(stderr, "\nTrace of the covariance matrix: %g (%snm^2)\n", trace, bM ? "u " : ""); if (asciifile) { out = gmx_ffopen(asciifile, "w"); for (j = 0; j < ndim; j++) { for (i = 0; i < ndim; i += 3) { fprintf(out, "%g %g %g\n", mat[ndim*j+i], mat[ndim*j+i+1], mat[ndim*j+i+2]); } } gmx_ffclose(out); } if (xpmfile) { min = 0; max = 0; snew(mat2, ndim); for (j = 0; j < ndim; j++) { mat2[j] = &(mat[ndim*j]); for (i = 0; i <= j; i++) { if (mat2[j][i] < min) { min = mat2[j][i]; } if (mat2[j][j] > max) { max = mat2[j][i]; } } } snew(axis, ndim); for (i = 0; i < ndim; i++) { axis[i] = i+1; } rlo.r = 0; rlo.g = 0; rlo.b = 1; rmi.r = 1; rmi.g = 1; rmi.b = 1; rhi.r = 1; rhi.g = 0; rhi.b = 0; out = gmx_ffopen(xpmfile, "w"); nlevels = 80; write_xpm3(out, 0, "Covariance", bM ? "u nm^2" : "nm^2", "dim", "dim", ndim, ndim, axis, axis, mat2, min, 0.0, max, rlo, rmi, rhi, &nlevels); gmx_ffclose(out); sfree(axis); sfree(mat2); } if (xpmafile) { min = 0; max = 0; snew(mat2, ndim/DIM); for (i = 0; i < ndim/DIM; i++) { snew(mat2[i], ndim/DIM); } for (j = 0; j < ndim/DIM; j++) { for (i = 0; i <= j; i++) { mat2[j][i] = 0; for (d = 0; d < DIM; d++) { mat2[j][i] += mat[ndim*(DIM*j+d)+DIM*i+d]; } if (mat2[j][i] < min) { min = mat2[j][i]; } if (mat2[j][j] > max) { max = mat2[j][i]; } mat2[i][j] = mat2[j][i]; } } snew(axis, ndim/DIM); for (i = 0; i < ndim/DIM; i++) { axis[i] = i+1; } rlo.r = 0; rlo.g = 0; rlo.b = 1; rmi.r = 1; rmi.g = 1; rmi.b = 1; rhi.r = 1; rhi.g = 0; rhi.b = 0; out = gmx_ffopen(xpmafile, "w"); nlevels = 80; write_xpm3(out, 0, "Covariance", bM ? "u nm^2" : "nm^2", "atom", "atom", ndim/DIM, ndim/DIM, axis, axis, mat2, min, 0.0, max, rlo, rmi, rhi, &nlevels); gmx_ffclose(out); sfree(axis); for (i = 0; i < ndim/DIM; i++) { sfree(mat2[i]); } sfree(mat2); } /* call diagonalization routine */ snew(eigenvalues, ndim); snew(eigenvectors, ndim*ndim); std::memcpy(eigenvectors, mat, ndim*ndim*sizeof(real)); fprintf(stderr, "\nDiagonalizing ...\n"); fflush(stderr); eigensolver(eigenvectors, ndim, 0, ndim, eigenvalues, mat); sfree(eigenvectors); /* now write the output */ sum = 0; for (i = 0; i < ndim; i++) { sum += eigenvalues[i]; } fprintf(stderr, "\nSum of the eigenvalues: %g (%snm^2)\n", sum, bM ? "u " : ""); if (std::abs(trace-sum) > 0.01*trace) { fprintf(stderr, "\nWARNING: eigenvalue sum deviates from the trace of the covariance matrix\n"); } /* Set 'end', the maximum eigenvector and -value index used for output */ if (end == -1) { if (nframes-1 < ndim) { end = nframes-1; fprintf(stderr, "\nWARNING: there are fewer frames in your trajectory than there are\n"); fprintf(stderr, "degrees of freedom in your system. Only generating the first\n"); fprintf(stderr, "%d out of %d eigenvectors and eigenvalues.\n", end, static_cast<int>(ndim)); } else { end = ndim; } } fprintf(stderr, "\nWriting eigenvalues to %s\n", eigvalfile); sprintf(str, "(%snm\\S2\\N)", bM ? "u " : ""); out = xvgropen(eigvalfile, "Eigenvalues of the covariance matrix", "Eigenvector index", str, oenv); for (i = 0; (i < end); i++) { fprintf (out, "%10d %g\n", static_cast<int>(i+1), eigenvalues[ndim-1-i]); } xvgrclose(out); if (bFit) { /* misuse lambda: 0/1 mass weighted analysis no/yes */ if (nfit == natoms) { WriteXref = eWXR_YES; for (i = 0; i < nfit; i++) { copy_rvec(xref[ifit[i]], x[i]); } } else { WriteXref = eWXR_NO; } } else { /* misuse lambda: -1 for no fit */ WriteXref = eWXR_NOFIT; } write_eigenvectors(eigvecfile, natoms, mat, TRUE, 1, end, WriteXref, x, bDiffMass1, xproj, bM, eigenvalues); out = gmx_ffopen(logfile, "w"); gmx_format_current_time(timebuf, STRLEN); fprintf(out, "Covariance analysis log, written %s\n", timebuf); fprintf(out, "Program: %s\n", argv[0]); gmx_getcwd(str, STRLEN); fprintf(out, "Working directory: %s\n\n", str); fprintf(out, "Read %d frames from %s (time %g to %g %s)\n", nframes, trxfile, output_env_conv_time(oenv, tstart), output_env_conv_time(oenv, tend), output_env_get_time_unit(oenv)); if (bFit) { fprintf(out, "Read reference structure for fit from %s\n", fitfile); } if (ndxfile) { fprintf(out, "Read index groups from %s\n", ndxfile); } fprintf(out, "\n"); fprintf(out, "Analysis group is '%s' (%d atoms)\n", ananame, natoms); if (bFit) { fprintf(out, "Fit group is '%s' (%d atoms)\n", fitname, nfit); } else { fprintf(out, "No fit was used\n"); } fprintf(out, "Analysis is %smass weighted\n", bDiffMass2 ? "" : "non-"); if (bFit) { fprintf(out, "Fit is %smass weighted\n", bDiffMass1 ? "" : "non-"); } fprintf(out, "Diagonalized the %dx%d covariance matrix\n", static_cast<int>(ndim), static_cast<int>(ndim)); fprintf(out, "Trace of the covariance matrix before diagonalizing: %g\n", trace); fprintf(out, "Trace of the covariance matrix after diagonalizing: %g\n\n", sum); fprintf(out, "Wrote %d eigenvalues to %s\n", static_cast<int>(end), eigvalfile); if (WriteXref == eWXR_YES) { fprintf(out, "Wrote reference structure to %s\n", eigvecfile); } fprintf(out, "Wrote average structure to %s and %s\n", averfile, eigvecfile); fprintf(out, "Wrote eigenvectors %d to %d to %s\n", 1, end, eigvecfile); gmx_ffclose(out); fprintf(stderr, "Wrote the log to %s\n", logfile); return 0; }
int main(int argc,char *argv[]) { static char *desc[] = { "The [TT]pmetest[tt] program tests the scaling of the PME code. When only given", "a [TT].tpr[tt] file it will compute PME for one frame. When given a trajectory", "it will do so for all the frames in the trajectory. Before the PME", "routine is called the coordinates are sorted along the X-axis.[PAR]", "As an extra service to the public the program can also compute", "long-range Coulomb energies for components of the system. When the", "[TT]-groups[tt] flag is given to the program the energy groups", "from the [TT].tpr[tt] file will be read, and half an energy matrix computed." }; t_commrec *cr,*mcr; static t_filenm fnm[] = { { efTPX, NULL, NULL, ffREAD }, { efTRN, "-o", NULL, ffWRITE }, { efLOG, "-g", "pme", ffWRITE }, { efTRX, "-f", NULL, ffOPTRD }, { efXVG, "-x", "ener-pme", ffWRITE } }; #define NFILE asize(fnm) /* Command line options ! */ static gmx_bool bVerbose=FALSE; static gmx_bool bOptFFT=FALSE; static gmx_bool bSort=FALSE; static int ewald_geometry=eewg3D; static int nnodes=1; static int pme_order=0; static rvec grid = { -1, -1, -1 }; static real rc = 0.0; static real dtol = 0.0; static gmx_bool bGroups = FALSE; static t_pargs pa[] = { { "-np", FALSE, etINT, {&nnodes}, "Number of nodes, must be the same as used for [TT]grompp[tt]" }, { "-v", FALSE, etBOOL,{&bVerbose}, "Be loud and noisy" }, { "-sort", FALSE, etBOOL,{&bSort}, "Sort coordinates. Crucial for domain decomposition." }, { "-grid", FALSE, etRVEC,{&grid}, "Number of grid cells in X, Y, Z dimension (if -1 use from [TT].tpr[tt])" }, { "-order", FALSE, etINT, {&pme_order}, "Order of the PME spreading algorithm" }, { "-groups", FALSE, etBOOL, {&bGroups}, "Compute half an energy matrix based on the energy groups in your [TT].tpr[tt] file" }, { "-rc", FALSE, etREAL, {&rc}, "Rcoulomb for Ewald summation" }, { "-tol", FALSE, etREAL, {&dtol}, "Tolerance for Ewald summation" } }; FILE *fp; t_inputrec *ir; t_topology top; t_tpxheader tpx; t_nrnb nrnb; t_nsborder *nsb; t_forcerec *fr; t_mdatoms *mdatoms; char title[STRLEN]; int natoms,step,status,i,ncg,root; real t,lambda,ewaldcoeff,qtot; rvec *x,*f,*xbuf; int *index; gmx_bool bCont; real *charge,*qbuf,*qqbuf; matrix box; /* Start the actual parallel code if necessary */ cr = init_par(&argc,&argv); root = 0; if (MASTER(cr)) CopyRight(stderr,argv[0]); /* Parse command line on all processors, arguments are passed on in * init_par (see above) */ parse_common_args(&argc,argv, PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_BE_NICE | PCA_CAN_SET_DEFFNM | (MASTER(cr) ? 0 : PCA_QUIET), NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL); #ifndef GMX_MPI if (nnodes > 1) gmx_fatal(FARGS,"GROMACS compiled without MPI support - can't do parallel runs"); #endif /* Open log files on all processors */ open_log(ftp2fn(efLOG,NFILE,fnm),cr); snew(ir,1); if (MASTER(cr)) { /* Read tpr file etc. */ read_tpxheader(ftp2fn(efTPX,NFILE,fnm),&tpx,FALSE,NULL,NULL); snew(x,tpx.natoms); read_tpx(ftp2fn(efTPX,NFILE,fnm),&step,&t,&lambda,ir, box,&natoms,x,NULL,NULL,&top); /* Charges */ qtot = 0; snew(charge,natoms); for(i=0; (i<natoms); i++) { charge[i] = top.atoms.atom[i].q; qtot += charge[i]; } /* Grid stuff */ if (opt2parg_bSet("-grid",asize(pa),pa)) { ir->nkx = grid[XX]; ir->nky = grid[YY]; ir->nkz = grid[ZZ]; } /* Check command line parameters for consistency */ if ((ir->nkx <= 0) || (ir->nky <= 0) || (ir->nkz <= 0)) gmx_fatal(FARGS,"PME grid = %d %d %d",ir->nkx,ir->nky,ir->nkz); if (opt2parg_bSet("-rc",asize(pa),pa)) ir->rcoulomb = rc; if (ir->rcoulomb <= 0) gmx_fatal(FARGS,"rcoulomb should be > 0 (not %f)",ir->rcoulomb); if (opt2parg_bSet("-order",asize(pa),pa)) ir->pme_order = pme_order; if (ir->pme_order <= 0) gmx_fatal(FARGS,"pme_order should be > 0 (not %d)",ir->pme_order); if (opt2parg_bSet("-tol",asize(pa),pa)) ir->ewald_rtol = dtol; if (ir->ewald_rtol <= 0) gmx_fatal(FARGS,"ewald_tol should be > 0 (not %f)",ir->ewald_rtol); } else { init_top(&top); } /* Add parallellization code here */ snew(nsb,1); if (MASTER(cr)) { ncg = top.blocks[ebCGS].multinr[0]; for(i=0; (i<cr->nnodes-1); i++) top.blocks[ebCGS].multinr[i] = min(ncg,(ncg*(i+1))/cr->nnodes); for( ; (i<MAXNODES); i++) top.blocks[ebCGS].multinr[i] = ncg; } if (PAR(cr)) { /* Set some variables to zero to avoid core dumps */ ir->opts.ngtc = ir->opts.ngacc = ir->opts.ngfrz = ir->opts.ngener = 0; #ifdef GMX_MPI /* Distribute the data over processors */ MPI_Bcast(&natoms,1,MPI_INT,root,MPI_COMM_WORLD); MPI_Bcast(ir,sizeof(*ir),MPI_BYTE,root,MPI_COMM_WORLD); MPI_Bcast(&qtot,1,GMX_MPI_REAL,root,MPI_COMM_WORLD); #endif /* Call some dedicated communication routines, master sends n-1 times */ if (MASTER(cr)) { for(i=1; (i<cr->nnodes); i++) { mv_block(i,&(top.blocks[ebCGS])); mv_block(i,&(top.atoms.excl)); } } else { ld_block(root,&(top.blocks[ebCGS])); ld_block(root,&(top.atoms.excl)); } if (!MASTER(cr)) { snew(charge,natoms); snew(x,natoms); } #ifdef GMX_MPI MPI_Bcast(charge,natoms,GMX_MPI_REAL,root,MPI_COMM_WORLD); #endif } ewaldcoeff = calc_ewaldcoeff(ir->rcoulomb,ir->ewald_rtol); if (bVerbose) pr_inputrec(stdlog,0,"Inputrec",ir); /* Allocate memory for temp arrays etc. */ snew(xbuf,natoms); snew(f,natoms); snew(qbuf,natoms); snew(qqbuf,natoms); snew(index,natoms); /* Initialize the PME code */ init_pme(stdlog,cr,ir->nkx,ir->nky,ir->nkz,ir->pme_order, natoms,FALSE,bOptFFT,ewald_geometry); /* MFlops accounting */ init_nrnb(&nrnb); /* Initialize the work division */ calc_nsb(stdlog,&(top.blocks[ebCGS]),cr->nnodes,nsb,0); nsb->nodeid = cr->nodeid; print_nsb(stdlog,"pmetest",nsb); /* Initiate forcerec */ mdatoms = atoms2md(stdlog,&top.atoms,ir->opts.nFreeze,ir->eI, ir->delta_t,0,ir->opts.tau_t,FALSE,FALSE); snew(fr,1); init_forcerec(stdlog,fr,ir,&top,cr,mdatoms,nsb,box,FALSE,NULL,NULL,FALSE); /* First do PME based on coordinates in tpr file, send them to * other processors if needed. */ if (MASTER(cr)) fprintf(stdlog,"-----\n" "Results based on tpr file %s\n",ftp2fn(efTPX,NFILE,fnm)); #ifdef GMX_MPI if (PAR(cr)) { MPI_Bcast(x[0],natoms*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD); MPI_Bcast(box[0],DIM*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD); MPI_Bcast(&t,1,GMX_MPI_REAL,root,MPI_COMM_WORLD); } #endif do_my_pme(stdlog,0,bVerbose,ir,x,xbuf,f,charge,qbuf,qqbuf,box,bSort, cr,nsb,&nrnb,&(top.atoms.excl),qtot,fr,index,NULL, bGroups ? ir->opts.ngener : 1,mdatoms->cENER); /* If we have a trajectry file, we will read the frames in it and compute * the PME energy. */ if (ftp2bSet(efTRX,NFILE,fnm)) { fprintf(stdlog,"-----\n" "Results based on trx file %s\n",ftp2fn(efTRX,NFILE,fnm)); if (MASTER(cr)) { sfree(x); natoms = read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (natoms != top.atoms.nr) gmx_fatal(FARGS,"natoms in trx = %d, in tpr = %d",natoms,top.atoms.nr); fp = xvgropen(ftp2fn(efXVG,NFILE,fnm),"PME Energy","Time (ps)","E (kJ/mol)"); } else fp = NULL; do { /* Send coordinates, box and time to the other nodes */ #ifdef GMX_MPI if (PAR(cr)) { MPI_Bcast(x[0],natoms*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD); MPI_Bcast(box[0],DIM*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD); MPI_Bcast(&t,1,GMX_MPI_REAL,root,MPI_COMM_WORLD); } #endif rm_pbc(&top.idef,nsb->natoms,box,x,x); /* Call the PME wrapper function */ do_my_pme(stdlog,t,bVerbose,ir,x,xbuf,f,charge,qbuf,qqbuf,box,bSort,cr, nsb,&nrnb,&(top.atoms.excl),qtot,fr,index,fp, bGroups ? ir->opts.ngener : 1,mdatoms->cENER); /* Only the master processor reads more data */ if (MASTER(cr)) bCont = read_next_x(status,&t,natoms,x,box); /* Check whether we need to continue */ #ifdef GMX_MPI if (PAR(cr)) MPI_Bcast(&bCont,1,MPI_INT,root,MPI_COMM_WORLD); #endif } while (bCont); /* Finish I/O, close files */ if (MASTER(cr)) { close_trx(status); ffclose(fp); } } if (bVerbose) { /* Do some final I/O about performance, might be useful in debugging */ fprintf(stdlog,"-----\n"); print_nrnb(stdlog,&nrnb); } /* Finish the parallel stuff */ if (gmx_parallel_env_initialized()) gmx_finalize(cr); /* Thank the audience, as usual */ if (MASTER(cr)) gmx_thanx(stderr); return 0; }