/*! \brief * Sets ua a search grid for a given box. * * \param[in,out] d Grid information. * \param[in] pbc Information about the box. * \returns FALSE if grid search is not suitable. */ static gmx_bool grid_set_box(gmx_ana_nbsearch_t *d, t_pbc *pbc) { int dd; /* TODO: This check could be improved. */ if (0.5*pbc->max_cutoff2 < d->cutoff2) { return FALSE; } if (!grid_setup_cells(d, pbc)) { return FALSE; } d->bTric = TRICLINIC(pbc->box); if (d->bTric) { for (dd = 0; dd < DIM; ++dd) { svmul(1.0 / d->ncelldim[dd], pbc->box[dd], d->cellbox[dd]); } m_inv_ur0(d->cellbox, d->recipcell); } else { for (dd = 0; dd < DIM; ++dd) { d->cellbox[dd][dd] = pbc->box[dd][dd] / d->ncelldim[dd]; d->recipcell[dd][dd] = 1 / d->cellbox[dd][dd]; } } grid_init_cell_nblist(d, pbc); return TRUE; }
int gmx_vanhove(int argc,char *argv[]) { const char *desc[] = { "g_vanhove computes the Van Hove correlation function.", "The Van Hove G(r,t) is the probability that a particle that is at r0", "at time zero can be found at position r0+r at time t.", "g_vanhove determines G not for a vector r, but for the length of r.", "Thus it gives the probability that a particle moves a distance of r", "in time t.", "Jumps across the periodic boundaries are removed.", "Corrections are made for scaling due to isotropic", "or anisotropic pressure coupling.", "[PAR]", "With option [TT]-om[tt] the whole matrix can be written as a function", "of t and r or as a function of sqrt(t) and r (option [TT]-sqrt[tt]).", "[PAR]", "With option [TT]-or[tt] the Van Hove function is plotted for one", "or more values of t. Option [TT]-nr[tt] sets the number of times,", "option [TT]-fr[tt] the number spacing between the times.", "The binwidth is set with option [TT]-rbin[tt]. The number of bins", "is determined automatically.", "[PAR]", "With option [TT]-ot[tt] the integral up to a certain distance", "(option [TT]-rt[tt]) is plotted as a function of time.", "[PAR]", "For all frames that are read the coordinates of the selected particles", "are stored in memory. Therefore the program may use a lot of memory.", "For options [TT]-om[tt] and [TT]-ot[tt] the program may be slow.", "This is because the calculation scales as the number of frames times", "[TT]-fm[tt] or [TT]-ft[tt].", "Note that with the [TT]-dt[tt] option the memory usage and calculation", "time can be reduced." }; static int fmmax=0,ftmax=0,nlev=81,nr=1,fshift=0; static real sbin=0,rmax=2,rbin=0.01,mmax=0,rint=0; t_pargs pa[] = { { "-sqrt", FALSE, etREAL,{&sbin}, "Use sqrt(t) on the matrix axis which binspacing # in sqrt(ps)" }, { "-fm", FALSE, etINT, {&fmmax}, "Number of frames in the matrix, 0 is plot all" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum r in the matrix (nm)" }, { "-rbin", FALSE, etREAL, {&rbin}, "Binwidth in the matrix and for -or (nm)" }, { "-mmax", FALSE, etREAL, {&mmax}, "Maximum density in the matrix, 0 is calculate (1/nm)" }, { "-nlevels" ,FALSE, etINT, {&nlev}, "Number of levels in the matrix" }, { "-nr", FALSE, etINT, {&nr}, "Number of curves for the -or output" }, { "-fr", FALSE, etINT, {&fshift}, "Frame spacing for the -or output" }, { "-rt", FALSE, etREAL, {&rint}, "Integration limit for the -ot output (nm)" }, { "-ft", FALSE, etINT, {&ftmax}, "Number of frames in the -ot output, 0 is plot all" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXPM, "-om", "vanhove", ffOPTWR }, { efXVG, "-or", "vanhove_r", ffOPTWR }, { efXVG, "-ot", "vanhove_t", ffOPTWR } }; #define NFILE asize(fnm) output_env_t oenv; const char *matfile,*otfile,*orfile; char title[256]; t_topology top; int ePBC; matrix boxtop,box,*sbox,avbox,corr; rvec *xtop,*x,**sx; int isize,nalloc,nallocn,natom; t_trxstatus *status; atom_id *index; char *grpname; int nfr,f,ff,i,m,mat_nx=0,nbin=0,bin,mbin,fbin; real *time,t,invbin=0,rmax2=0,rint2=0,d2; real invsbin=0,matmax,normfac,dt,*tickx,*ticky; char buf[STRLEN],**legend; real **mat=NULL; int *pt=NULL,**pr=NULL,*mcount=NULL,*tcount=NULL,*rcount=NULL; FILE *fp; t_rgb rlo={1,1,1}, rhi={0,0,0}; CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); matfile = opt2fn_null("-om",NFILE,fnm); if (opt2parg_bSet("-fr",NPA,pa)) orfile = opt2fn("-or",NFILE,fnm); else orfile = opt2fn_null("-or",NFILE,fnm); if (opt2parg_bSet("-rt",NPA,pa)) otfile = opt2fn("-ot",NFILE,fnm); else otfile = opt2fn_null("-ot",NFILE,fnm); if (!matfile && !otfile && !orfile) { fprintf(stderr, "For output set one (or more) of the output file options\n"); exit(0); } read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,boxtop, FALSE); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname); nalloc = 0; time = NULL; sbox = NULL; sx = NULL; clear_mat(avbox); natom=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); nfr = 0; do { if (nfr >= nalloc) { nalloc += 100; srenew(time,nalloc); srenew(sbox,nalloc); srenew(sx,nalloc); } time[nfr] = t; copy_mat(box,sbox[nfr]); /* This assumes that the off-diagonal box elements * are not affected by jumps across the periodic boundaries. */ m_add(avbox,box,avbox); snew(sx[nfr],isize); for(i=0; i<isize; i++) copy_rvec(x[index[i]],sx[nfr][i]); nfr++; } while (read_next_x(oenv,status,&t,natom,x,box)); /* clean up */ sfree(x); close_trj(status); fprintf(stderr,"Read %d frames\n",nfr); dt = (time[nfr-1] - time[0])/(nfr - 1); /* Some ugly rounding to get nice nice times in the output */ dt = (int)(10000.0*dt + 0.5)/10000.0; invbin = 1.0/rbin; if (matfile) { if (fmmax <= 0 || fmmax >= nfr) fmmax = nfr - 1; snew(mcount,fmmax); nbin = (int)(rmax*invbin + 0.5); if (sbin == 0) { mat_nx = fmmax + 1; } else { invsbin = 1.0/sbin; mat_nx = sqrt(fmmax*dt)*invsbin + 1; } snew(mat,mat_nx); for(f=0; f<mat_nx; f++) snew(mat[f],nbin); rmax2 = sqr(nbin*rbin); /* Initialize time zero */ mat[0][0] = nfr*isize; mcount[0] += nfr; } else { fmmax = 0; } if (orfile) { snew(pr,nr); nalloc = 0; snew(rcount,nr); } if (otfile) { if (ftmax <= 0) ftmax = nfr - 1; snew(tcount,ftmax); snew(pt,nfr); rint2 = rint*rint; /* Initialize time zero */ pt[0] = nfr*isize; tcount[0] += nfr; } else { ftmax = 0; } msmul(avbox,1.0/nfr,avbox); for(f=0; f<nfr; f++) { if (f % 100 == 0) fprintf(stderr,"\rProcessing frame %d",f); /* Scale all the configuration to the average box */ m_inv_ur0(sbox[f],corr); mmul_ur0(avbox,corr,corr); for(i=0; i<isize; i++) { mvmul_ur0(corr,sx[f][i],sx[f][i]); if (f > 0) { /* Correct for periodic jumps */ for(m=DIM-1; m>=0; m--) { while(sx[f][i][m] - sx[f-1][i][m] > 0.5*avbox[m][m]) rvec_dec(sx[f][i],avbox[m]); while(sx[f][i][m] - sx[f-1][i][m] <= -0.5*avbox[m][m]) rvec_inc(sx[f][i],avbox[m]); } } } for(ff=0; ff<f; ff++) { fbin = f - ff; if (fbin <= fmmax || fbin <= ftmax) { if (sbin == 0) mbin = fbin; else mbin = (int)(sqrt(fbin*dt)*invsbin + 0.5); for(i=0; i<isize; i++) { d2 = distance2(sx[f][i],sx[ff][i]); if (mbin < mat_nx && d2 < rmax2) { bin = (int)(sqrt(d2)*invbin + 0.5); if (bin < nbin) { mat[mbin][bin] += 1; } } if (fbin <= ftmax && d2 <= rint2) pt[fbin]++; } if (matfile) mcount[mbin]++; if (otfile) tcount[fbin]++; } } if (orfile) { for(fbin=0; fbin<nr; fbin++) { ff = f - (fbin + 1)*fshift; if (ff >= 0) { for(i=0; i<isize; i++) { d2 = distance2(sx[f][i],sx[ff][i]); bin = (int)(sqrt(d2)*invbin); if (bin >= nalloc) { nallocn = 10*(bin/10) + 11; for(m=0; m<nr; m++) { srenew(pr[m],nallocn); for(i=nalloc; i<nallocn; i++) pr[m][i] = 0; } nalloc = nallocn; } pr[fbin][bin]++; } rcount[fbin]++; } } } } fprintf(stderr,"\n"); if (matfile) { matmax = 0; for(f=0; f<mat_nx; f++) { normfac = 1.0/(mcount[f]*isize*rbin); for(i=0; i<nbin; i++) { mat[f][i] *= normfac; if (mat[f][i] > matmax && (f!=0 || i!=0)) matmax = mat[f][i]; } } fprintf(stdout,"Value at (0,0): %.3f, maximum of the rest %.3f\n", mat[0][0],matmax); if (mmax > 0) matmax = mmax; snew(tickx,mat_nx); for(f=0; f<mat_nx; f++) { if (sbin == 0) tickx[f] = f*dt; else tickx[f] = f*sbin; } snew(ticky,nbin+1); for(i=0; i<=nbin; i++) ticky[i] = i*rbin; fp = ffopen(matfile,"w"); write_xpm(fp,MAT_SPATIAL_Y,"Van Hove function","G (1/nm)", sbin==0 ? "time (ps)" : "sqrt(time) (ps^1/2)","r (nm)", mat_nx,nbin,tickx,ticky,mat,0,matmax,rlo,rhi,&nlev); ffclose(fp); } if (orfile) { fp = xvgropen(orfile,"Van Hove function","r (nm)","G (nm\\S-1\\N)",oenv); fprintf(fp,"@ subtitle \"for particles in group %s\"\n",grpname); snew(legend,nr); for(fbin=0; fbin<nr; fbin++) { sprintf(buf,"%g ps",(fbin + 1)*fshift*dt); legend[fbin] = strdup(buf); } xvgr_legend(fp,nr,(const char**)legend,oenv); for(i=0; i<nalloc; i++) { fprintf(fp,"%g",i*rbin); for(fbin=0; fbin<nr; fbin++) fprintf(fp," %g", (real)pr[fbin][i]/(rcount[fbin]*isize*rbin*(i==0 ? 0.5 : 1))); fprintf(fp,"\n"); } ffclose(fp); } if (otfile) { sprintf(buf,"Probability of moving less than %g nm",rint); fp = xvgropen(otfile,buf,"t (ps)","",oenv); fprintf(fp,"@ subtitle \"for particles in group %s\"\n",grpname); for(f=0; f<=ftmax; f++) fprintf(fp,"%g %g\n",f*dt,(real)pt[f]/(tcount[f]*isize)); ffclose(fp); } do_view(oenv, matfile,NULL); do_view(oenv, orfile,NULL); do_view(oenv, otfile,NULL); thanx(stderr); return 0; }
void parrinellorahman_pcoupl(FILE *fplog,gmx_step_t step, t_inputrec *ir,real dt,tensor pres, tensor box,tensor box_rel,tensor boxv, tensor M,matrix mu,bool bFirstStep) { /* This doesn't do any coordinate updating. It just * integrates the box vector equations from the calculated * acceleration due to pressure difference. We also compute * the tensor M which is used in update to couple the particle * coordinates to the box vectors. * * In Nose and Klein (Mol.Phys 50 (1983) no 5., p 1055) this is * given as * -1 . . -1 * M_nk = (h') * (h' * h + h' h) * h * * with the dots denoting time derivatives and h is the transformation from * the scaled frame to the real frame, i.e. the TRANSPOSE of the box. * This also goes for the pressure and M tensors - they are transposed relative * to ours. Our equation thus becomes: * * -1 . . -1 * M_gmx = M_nk' = b * (b * b' + b * b') * b' * * where b is the gromacs box matrix. * Our box accelerations are given by * .. .. * b = vol/W inv(box') * (P-ref_P) (=h') */ int d,n; tensor winv; real vol=box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]; real atot,arel,change,maxchange,xy_pressure; tensor invbox,pdiff,t1,t2; real maxl; m_inv_ur0(box,invbox); if (!bFirstStep) { /* Note that PRESFAC does not occur here. * The pressure and compressibility always occur as a product, * therefore the pressure unit drops out. */ maxl=max(box[XX][XX],box[YY][YY]); maxl=max(maxl,box[ZZ][ZZ]); for(d=0;d<DIM;d++) for(n=0;n<DIM;n++) winv[d][n]= (4*M_PI*M_PI*ir->compress[d][n])/(3*ir->tau_p*ir->tau_p*maxl); m_sub(pres,ir->ref_p,pdiff); if(ir->epct==epctSURFACETENSION) { /* Unlike Berendsen coupling it might not be trivial to include a z * pressure correction here? On the other hand we don't scale the * box momentarily, but change accelerations, so it might not be crucial. */ xy_pressure=0.5*(pres[XX][XX]+pres[YY][YY]); for(d=0;d<ZZ;d++) pdiff[d][d]=(xy_pressure-(pres[ZZ][ZZ]-ir->ref_p[d][d]/box[d][d])); } tmmul(invbox,pdiff,t1); /* Move the off-diagonal elements of the 'force' to one side to ensure * that we obey the box constraints. */ for(d=0;d<DIM;d++) { for(n=0;n<d;n++) { t1[d][n] += t1[n][d]; t1[n][d] = 0; } } switch (ir->epct) { case epctANISOTROPIC: for(d=0;d<DIM;d++) for(n=0;n<=d;n++) t1[d][n] *= winv[d][n]*vol; break; case epctISOTROPIC: /* calculate total volume acceleration */ atot=box[XX][XX]*box[YY][YY]*t1[ZZ][ZZ]+ box[XX][XX]*t1[YY][YY]*box[ZZ][ZZ]+ t1[XX][XX]*box[YY][YY]*box[ZZ][ZZ]; arel=atot/(3*vol); /* set all RELATIVE box accelerations equal, and maintain total V * change speed */ for(d=0;d<DIM;d++) for(n=0;n<=d;n++) t1[d][n] = winv[0][0]*vol*arel*box[d][n]; break; case epctSEMIISOTROPIC: case epctSURFACETENSION: /* Note the correction to pdiff above for surftens. coupling */ /* calculate total XY volume acceleration */ atot=box[XX][XX]*t1[YY][YY]+t1[XX][XX]*box[YY][YY]; arel=atot/(2*box[XX][XX]*box[YY][YY]); /* set RELATIVE XY box accelerations equal, and maintain total V * change speed. Dont change the third box vector accelerations */ for(d=0;d<ZZ;d++) for(n=0;n<=d;n++) t1[d][n] = winv[d][n]*vol*arel*box[d][n]; for(n=0;n<DIM;n++) t1[ZZ][n] *= winv[d][n]*vol; break; default: gmx_fatal(FARGS,"Parrinello-Rahman pressure coupling type %s " "not supported yet\n",EPCOUPLTYPETYPE(ir->epct)); break; } maxchange=0; for(d=0;d<DIM;d++) for(n=0;n<=d;n++) { boxv[d][n] += dt*t1[d][n]; /* We do NOT update the box vectors themselves here, since * we need them for shifting later. It is instead done last * in the update() routine. */ /* Calculate the change relative to diagonal elements - * since it's perfectly ok for the off-diagonal ones to * be zero it doesn't make sense to check the change relative * to its current size. */ change=fabs(dt*boxv[d][n]/box[d][d]); if(change>maxchange) maxchange=change; } if (maxchange > 0.01 && fplog) { char buf[22]; fprintf(fplog,"\nStep %s Warning: Pressure scaling more than 1%%.\n", gmx_step_str(step,buf)); } } preserve_box_shape(ir,box_rel,boxv); mtmul(boxv,box,t1); /* t1=boxv * b' */ mmul(invbox,t1,t2); mtmul(t2,invbox,M); /* Determine the scaling matrix mu for the coordinates */ for(d=0;d<DIM;d++) for(n=0;n<=d;n++) t1[d][n] = box[d][n] + dt*boxv[d][n]; preserve_box_shape(ir,box_rel,t1); /* t1 is the box at t+dt, determine mu as the relative change */ mmul_ur0(invbox,t1,mu); }
static void read_posres(gmx_mtop_t *mtop,t_molinfo *molinfo,bool bTopB, char *fn, int rc_scaling, int ePBC, rvec com) { bool bFirst = TRUE; rvec *x,*v,*xp; dvec sum; double totmass; t_atoms dumat; matrix box,invbox; int natoms,npbcdim=0; char title[STRLEN]; int a,i,ai,j,k,mb,nat_molb; gmx_molblock_t *molb; t_params *pr; t_atom *atom; get_stx_coordnum(fn,&natoms); if (natoms != mtop->natoms) { sprintf(warn_buf,"The number of atoms in %s (%d) does not match the number of atoms in the topology (%d). Will assume that the first %d atoms in the topology and %s match.",fn,natoms,mtop->natoms,min(mtop->natoms,natoms),fn); warning(NULL); } snew(x,natoms); snew(v,natoms); init_t_atoms(&dumat,natoms,FALSE); read_stx_conf(fn,title,&dumat,x,v,NULL,box); npbcdim = ePBC2npbcdim(ePBC); clear_rvec(com); if (rc_scaling != erscNO) { copy_mat(box,invbox); for(j=npbcdim; j<DIM; j++) { clear_rvec(invbox[j]); invbox[j][j] = 1; } m_inv_ur0(invbox,invbox); } /* Copy the reference coordinates to mtop */ clear_dvec(sum); totmass = 0; a = 0; for(mb=0; mb<mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr; pr = &(molinfo[molb->type].plist[F_POSRES]); if (pr->nr > 0) { atom = mtop->moltype[molb->type].atoms.atom; for(i=0; (i<pr->nr); i++) { ai=pr->param[i].AI; if (ai >= natoms) { gmx_fatal(FARGS,"Position restraint atom index (%d) in moltype '%s' is larger than number of atoms in %s (%d).\n", ai+1,*molinfo[molb->type].name,fn,natoms); } if (rc_scaling == erscCOM) { /* Determine the center of mass of the posres reference coordinates */ for(j=0; j<npbcdim; j++) { sum[j] += atom[ai].m*x[a+ai][j]; } totmass += atom[ai].m; } } if (!bTopB) { molb->nposres_xA = nat_molb; snew(molb->posres_xA,molb->nposres_xA); for(i=0; i<nat_molb; i++) { copy_rvec(x[a+i],molb->posres_xA[i]); } } else { molb->nposres_xB = nat_molb; snew(molb->posres_xB,molb->nposres_xB); for(i=0; i<nat_molb; i++) { copy_rvec(x[a+i],molb->posres_xB[i]); } } } a += nat_molb; } if (rc_scaling == erscCOM) { if (totmass == 0) gmx_fatal(FARGS,"The total mass of the position restraint atoms is 0"); for(j=0; j<npbcdim; j++) com[j] = sum[j]/totmass; fprintf(stderr,"The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f\n",com[XX],com[YY],com[ZZ]); } if (rc_scaling != erscNO) { for(mb=0; mb<mtop->nmolblock; mb++) { molb = &mtop->molblock[mb]; nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr; if (molb->nposres_xA > 0 || molb->nposres_xB > 0) { xp = (!bTopB ? molb->posres_xA : molb->posres_xB); for(i=0; i<nat_molb; i++) { for(j=0; j<npbcdim; j++) { if (rc_scaling == erscALL) { /* Convert from Cartesian to crystal coordinates */ xp[i][j] *= invbox[j][j]; for(k=j+1; k<npbcdim; k++) { xp[i][j] += invbox[k][j]*xp[i][k]; } } else if (rc_scaling == erscCOM) { /* Subtract the center of mass */ xp[i][j] -= com[j]; } } } } } if (rc_scaling == erscCOM) { /* Convert the COM from Cartesian to crystal coordinates */ for(j=0; j<npbcdim; j++) { com[j] *= invbox[j][j]; for(k=j+1; k<npbcdim; k++) { com[j] += invbox[k][j]*com[k]; } } } } free_t_atoms(&dumat,TRUE); sfree(x); sfree(v); }