int gmx_nmtraj(int argc,char *argv[]) { const char *desc[] = { "[TT]g_nmtraj[tt] generates an virtual trajectory from an eigenvector, ", "corresponding to a harmonic cartesian oscillation around the average ", "structure. The eigenvectors should normally be mass-weighted, but you can ", "use non-weighted eigenvectors to generate orthogonal motions. ", "The output frames are written as a trajectory file covering an entire period, and ", "the first frame is the average structure. If you write the trajectory in (or convert to) ", "PDB format you can view it directly in PyMol and also render a photorealistic movie. ", "Motion amplitudes are calculated from the eigenvalues and a preset temperature, ", "assuming equipartition of the energy over all modes. To make the motion clearly visible ", "in PyMol you might want to amplify it by setting an unrealistic high temperature. ", "However, be aware that both the linear cartesian displacements and mass weighting will ", "lead to serious structure deformation for high amplitudes - this is is simply a limitation ", "of the cartesian normal mode model. By default the selected eigenvector is set to 7, since ", " the first six normal modes are the translational and rotational degrees of freedom." }; static real refamplitude=0.25; static int nframes=30; static real temp=300.0; static const char *eignrvec = "7"; static const char *phasevec = "0.0"; t_pargs pa[] = { { "-eignr", FALSE, etSTR, {&eignrvec}, "String of eigenvectors to use (first is 1)" }, { "-phases", FALSE, etSTR, {&phasevec}, "String of phases (default is 0.0)" }, { "-temp", FALSE, etREAL, {&temp}, "Temperature in Kelvin" }, { "-amplitude", FALSE, etREAL, {&refamplitude}, "Amplitude for modes with eigenvalue<=0" }, { "-nframes", FALSE, etINT, {&nframes}, "Number of frames to generate" } }; #define NPA asize(pa) int out; t_topology top; int ePBC; t_atoms *atoms; rvec *xtop,*xref,*xav,*xout; int nvec,*eignr=NULL; int *eigvalnr; rvec **eigvec=NULL; matrix box; int natoms; int i,j,k,kmode,d,s,v; bool bDMR,bDMA,bFit; char * indexfile; char * grpname; real * eigval; int neigval; int * dummy; real * invsqrtm; char title[STRLEN]; real fraction; int *out_eigidx; real *out_eigval; rvec * this_eigvec; real omega,Ekin,sum,m,vel; bool found; int nmodes,nphases; int *imodes; real *amplitude; real *phases; real dum; const char *p; char *pe; t_filenm fnm[] = { { efTPS, NULL, NULL, ffREAD }, { efTRN, "-v", "eigenvec", ffREAD }, { efTRO, "-o", "nmtraj", ffWRITE } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_BE_NICE, NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL); read_eigenvectors(opt2fn("-v",NFILE,fnm),&natoms,&bFit, &xref,&bDMR,&xav,&bDMA,&nvec,&eignr,&eigvec,&eigval); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,bDMA); /* Find vectors and phases */ /* first find number of args in string */ nmodes=0; p=eignrvec; while(*p!=0) { dum=strtod(p,&pe); p=pe; nmodes++; } snew(imodes,nmodes); p=eignrvec; for(i=0;i<nmodes;i++) { /* C indices start on 0 */ imodes[i]=strtol(p,&pe,10)-1; p = pe; } /* Now read phases */ nphases=0; p=phasevec; while(*p!=0) { dum=strtod(p,&pe); p=pe; nphases++; } if(nphases>nmodes) { gmx_fatal(FARGS,"More phases than eigenvector indices specified.\n"); } snew(phases,nmodes); p=phasevec; for(i=0;i<nphases;i++) { phases[i]=strtod(p,&pe); p = pe; } if(nmodes>nphases) { printf("Warning: Setting phase of last %d modes to zero...\n",nmodes-nphases); } for(i=nphases;i<nmodes;i++) { phases[i]=0; } atoms=&top.atoms; if(atoms->nr != natoms) { gmx_fatal(FARGS,"Different number of atoms in topology and eigenvectors.\n"); } snew(dummy,natoms); for(i=0;i<natoms;i++) dummy[i]=i; /* Find the eigenvalue/vector to match our select one */ snew(out_eigidx,nmodes); for(i=0;i<nmodes;i++) out_eigidx[i]=-1; for(i=0;i<nvec;i++) { for(j=0;j<nmodes;j++) { if(imodes[j]==eignr[i]) out_eigidx[j]=i; } } for(i=0;i<nmodes;i++) if(out_eigidx[i]==-1) gmx_fatal(FARGS,"Could not find mode %d in eigenvector file.\n",imodes[i]); snew(invsqrtm,natoms); if (bDMA) { for(i=0; (i<natoms); i++) invsqrtm[i] = invsqrt(atoms->atom[i].m); } else { for(i=0; (i<natoms); i++) invsqrtm[i]=1.0; } snew(xout,natoms); snew(amplitude,nmodes); printf("mode phases: %g %g\n",phases[0],phases[1]); for(i=0;i<nmodes;i++) { kmode = out_eigidx[i]; this_eigvec=eigvec[kmode]; if( (kmode >= 6) && (eigval[kmode] > 0)) { /* Derive amplitude from temperature and eigenvalue if we can */ /* Convert eigenvalue to angular frequency, in units s^(-1) */ omega = sqrt(eigval[kmode]*1.0E21/(AVOGADRO*AMU)); /* Harmonic motion will be x=x0 + A*sin(omega*t)*eigenvec. * The velocity is thus: * * v = A*omega*cos(omega*t)*eigenvec. * * And the average kinetic energy the integral of mass*v*v/2 over a * period: * * (1/4)*mass*A*omega*eigenvec * * For t =2*pi*n, all energy will be kinetic, and v=A*omega*eigenvec. * The kinetic energy will be sum(0.5*mass*v*v) if we temporarily set A to 1, * and the average over a period half of this. */ Ekin = 0; for(k=0;k<natoms;k++) { m = atoms->atom[k].m; for(d=0;d<DIM;d++) { vel = omega*this_eigvec[k][d]; Ekin += 0.5*0.5*m*vel*vel; } } /* Convert Ekin from amu*(nm/s)^2 to J, i.e., kg*(m/s)^2 * This will also be proportional to A^2 */ Ekin *= AMU*1E-18; /* Set the amplitude so the energy is kT/2 */ amplitude[i] = sqrt(0.5*BOLTZMANN*temp/Ekin); } else { amplitude[i] = refamplitude; } } out=open_trx(ftp2fn(efTRO,NFILE,fnm),"w"); /* Write a sine oscillation around the average structure, * modulated by the eigenvector with selected amplitude. */ for(i=0;i<nframes;i++) { fraction = (real)i/(real)nframes; for(j=0;j<natoms;j++) { copy_rvec(xav[j],xout[j]); } for(k=0;k<nmodes;k++) { kmode=out_eigidx[k]; this_eigvec=eigvec[kmode]; for(j=0;j<natoms;j++) { for(d=0;d<DIM;d++) { xout[j][d] += amplitude[k]*sin(2*M_PI*(fraction+phases[k]/360.0))*this_eigvec[j][d]; } } } write_trx(out,natoms,dummy,atoms,i,(real)i/(real)nframes,box,xout,NULL,NULL); } fprintf(stderr,"\n"); close_trx(out); return 0; }
/* * Gromacs nonbonded kernel nb_kernel300 * Coulomb interaction: Tabulated * VdW interaction: Not calculated * water optimization: No * Calculate forces: yes */ void nb_kernel300( int * p_nri, int * iinr, int * jindex, int * jjnr, int * shift, real * shiftvec, real * fshift, int * gid, real * pos, real * faction, real * charge, real * p_facel, real * p_krf, real * p_crf, real * Vc, int * type, int * p_ntype, real * vdwparam, real * Vvdw, real * p_tabscale, real * VFtab,real * enerd1,real * enerd2,real * enerd3,real * enerd4,int * start,int * end,int * homenr,int * nbsum, real * invsqrta, real * dvda, real * p_gbtabscale, real * GBtab, int * p_nthreads, int * count, void * mtx, int * outeriter, int * inneriter, real * work) { int nri,ntype,nthreads; real facel,krf,crf,tabscale,gbtabscale; int n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid; int nn0,nn1,nouter,ninner; real shX,shY,shZ; real fscal,tx,ty,tz; real iq; real qq,vcoul,vctot; real r,rt,eps,eps2; int n0,nnn; real Y,F,Geps,Heps2,Fp,VV; real FF; real fijC; real ix1,iy1,iz1,fix1,fiy1,fiz1; real jx1,jy1,jz1; real dx11,dy11,dz11,rsq11,rinv11; int index; nri = *p_nri; ntype = *p_ntype; nthreads = *p_nthreads; facel = *p_facel; krf = *p_krf; crf = *p_crf; tabscale = *p_tabscale; /* Reset outer and inner iteration counters */ nouter = 0; ninner = 0; /* Loop over thread workunits */ do { #ifdef GMX_THREADS gmx_thread_mutex_lock((gmx_thread_mutex_t *)mtx); nn0 = *count; /* Take successively smaller chunks (at least 10 lists) */ nn1 = nn0+(nri-nn0)/(2*nthreads)+10; *count = nn1; gmx_thread_mutex_unlock((gmx_thread_mutex_t *)mtx); if(nn1>nri) nn1=nri; #else nn0 = 0; nn1 = nri; #endif /* Start outer loop over neighborlists */ for(n=nn0; (n<nn1); n++) { /* Load shift vector for this list */ is3 = 3*shift[n]; shX = shiftvec[is3]; shY = shiftvec[is3+1]; shZ = shiftvec[is3+2]; /* Load limits for loop over neighbors */ nj0 = jindex[n]; nj1 = jindex[n+1]; /* Get outer coordinate index */ ii = iinr[n]; ii3 = 3*ii; /* Load i atom data, add shift vector */ ix1 = shX + pos[ii3+0]; iy1 = shY + pos[ii3+1]; iz1 = shZ + pos[ii3+2]; /* Load parameters for i atom */ iq = facel*charge[ii]; /* Zero the potential energy for this list */ vctot = 0; /* Clear i atom forces */ fix1 = 0; fiy1 = 0; fiz1 = 0; for(k=nj0; (k<nj1); k++) { /* Get j neighbor index, and coordinate index */ jnr = jjnr[k]; j3 = 3*jnr; if(enerd1) { if(ii<jnr) { index = start[ii]**homenr - nbsum[start[ii]] + start[jnr]; } else { index = start[jnr]**homenr - nbsum[start[jnr]] + start[ii]; } enerd1[index] = enerd1[index] - vctot; } /* load j atom coordinates */ jx1 = pos[j3+0]; jy1 = pos[j3+1]; jz1 = pos[j3+2]; /* Calculate distance */ dx11 = ix1 - jx1; dy11 = iy1 - jy1; dz11 = iz1 - jz1; rsq11 = dx11*dx11+dy11*dy11+dz11*dz11; /* Calculate 1/r and 1/r2 */ rinv11 = invsqrt(rsq11); /* Load parameters for j atom */ qq = iq*charge[jnr]; /* Calculate table index */ r = rsq11*rinv11; /* Calculate table index */ rt = r*tabscale; n0 = rt; eps = rt-n0; eps2 = eps*eps; nnn = 4*n0; /* Tabulated coulomb interaction */ Y = VFtab[nnn]; F = VFtab[nnn+1]; Geps = eps*VFtab[nnn+2]; Heps2 = eps2*VFtab[nnn+3]; Fp = F+Geps+Heps2; VV = Y+eps*Fp; FF = Fp+Geps+2.0*Heps2; vcoul = qq*VV; fijC = qq*FF; vctot = vctot + vcoul; fscal = -((fijC)*tabscale)*rinv11; if(enerd1) { enerd1[index] = enerd1[index] + vctot; } /* Calculate temporary vectorial force */ tx = fscal*dx11; ty = fscal*dy11; tz = fscal*dz11; /* Increment i atom force */ fix1 = fix1 + tx; fiy1 = fiy1 + ty; fiz1 = fiz1 + tz; /* Decrement j atom force */ faction[j3+0] = faction[j3+0] - tx; faction[j3+1] = faction[j3+1] - ty; faction[j3+2] = faction[j3+2] - tz; /* Inner loop uses 42 flops/iteration */ } /* Add i forces to mem and shifted force list */ faction[ii3+0] = faction[ii3+0] + fix1; faction[ii3+1] = faction[ii3+1] + fiy1; faction[ii3+2] = faction[ii3+2] + fiz1; fshift[is3] = fshift[is3]+fix1; fshift[is3+1] = fshift[is3+1]+fiy1; fshift[is3+2] = fshift[is3+2]+fiz1; /* Add potential energies to the group for this list */ ggid = gid[n]; Vc[ggid] = Vc[ggid] + vctot; /* Increment number of inner iterations */ ninner = ninner + nj1 - nj0; /* Outer loop uses 11 flops/iteration */ } /* Increment number of outer iterations */ nouter = nouter + nn1 - nn0; } while (nn1<nri); /* Write outer/inner iteration count to pointers */ *outeriter = nouter; *inneriter = ninner; }
/* * Gromacs nonbonded kernel nb_kernel231 * Coulomb interaction: Reaction field * VdW interaction: Tabulated * water optimization: SPC/TIP3P - other atoms * Calculate forces: yes */ void nb_kernel231( int * p_nri, int * iinr, int * jindex, int * jjnr, int * shift, real * shiftvec, real * fshift, int * gid, real * pos, real * faction, real * charge, real * p_facel, real * p_krf, real * p_crf, real * Vc, int * type, int * p_ntype, real * vdwparam, real * Vvdw, real * p_tabscale, real * VFtab,real * enerd1,real * enerd2,real * enerd3,real * enerd4,int * start,int * end,int * homenr,int * nbsum, real * invsqrta, real * dvda, real * p_gbtabscale, real * GBtab, int * p_nthreads, int * count, void * mtx, int * outeriter, int * inneriter, real * work) { int nri,ntype,nthreads; real facel,krf,crf,tabscale,gbtabscale; int n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid; int nn0,nn1,nouter,ninner; real shX,shY,shZ; real fscal,tx,ty,tz; real rinvsq; real jq; real qq,vcoul,vctot; int nti; int tj; real Vvdw6,Vvdwtot; real Vvdw12; real r,rt,eps,eps2; int n0,nnn; real Y,F,Geps,Heps2,Fp,VV; real FF; real fijD,fijR; real krsq; real ix1,iy1,iz1,fix1,fiy1,fiz1; real ix2,iy2,iz2,fix2,fiy2,fiz2; real ix3,iy3,iz3,fix3,fiy3,fiz3; real jx1,jy1,jz1,fjx1,fjy1,fjz1; real dx11,dy11,dz11,rsq11,rinv11; real dx21,dy21,dz21,rsq21,rinv21; real dx31,dy31,dz31,rsq31,rinv31; real qO,qH; real c6,c12; nri = *p_nri; ntype = *p_ntype; nthreads = *p_nthreads; facel = *p_facel; krf = *p_krf; crf = *p_crf; tabscale = *p_tabscale; /* Initialize water data */ ii = iinr[0]; qO = facel*charge[ii]; qH = facel*charge[ii+1]; nti = 2*ntype*type[ii]; /* Reset outer and inner iteration counters */ nouter = 0; ninner = 0; /* Loop over thread workunits */ do { #ifdef GMX_THREADS gmx_thread_mutex_lock((gmx_thread_mutex_t *)mtx); nn0 = *count; /* Take successively smaller chunks (at least 10 lists) */ nn1 = nn0+(nri-nn0)/(2*nthreads)+10; *count = nn1; gmx_thread_mutex_unlock((gmx_thread_mutex_t *)mtx); if(nn1>nri) nn1=nri; #else nn0 = 0; nn1 = nri; #endif /* Start outer loop over neighborlists */ for(n=nn0; (n<nn1); n++) { /* Load shift vector for this list */ is3 = 3*shift[n]; shX = shiftvec[is3]; shY = shiftvec[is3+1]; shZ = shiftvec[is3+2]; /* Load limits for loop over neighbors */ nj0 = jindex[n]; nj1 = jindex[n+1]; /* Get outer coordinate index */ ii = iinr[n]; ii3 = 3*ii; /* Load i atom data, add shift vector */ ix1 = shX + pos[ii3+0]; iy1 = shY + pos[ii3+1]; iz1 = shZ + pos[ii3+2]; ix2 = shX + pos[ii3+3]; iy2 = shY + pos[ii3+4]; iz2 = shZ + pos[ii3+5]; ix3 = shX + pos[ii3+6]; iy3 = shY + pos[ii3+7]; iz3 = shZ + pos[ii3+8]; /* Zero the potential energy for this list */ vctot = 0; Vvdwtot = 0; /* Clear i atom forces */ fix1 = 0; fiy1 = 0; fiz1 = 0; fix2 = 0; fiy2 = 0; fiz2 = 0; fix3 = 0; fiy3 = 0; fiz3 = 0; for(k=nj0; (k<nj1); k++) { /* Get j neighbor index, and coordinate index */ jnr = jjnr[k]; j3 = 3*jnr; /* load j atom coordinates */ jx1 = pos[j3+0]; jy1 = pos[j3+1]; jz1 = pos[j3+2]; /* Calculate distance */ dx11 = ix1 - jx1; dy11 = iy1 - jy1; dz11 = iz1 - jz1; rsq11 = dx11*dx11+dy11*dy11+dz11*dz11; dx21 = ix2 - jx1; dy21 = iy2 - jy1; dz21 = iz2 - jz1; rsq21 = dx21*dx21+dy21*dy21+dz21*dz21; dx31 = ix3 - jx1; dy31 = iy3 - jy1; dz31 = iz3 - jz1; rsq31 = dx31*dx31+dy31*dy31+dz31*dz31; /* Calculate 1/r and 1/r2 */ rinv11 = invsqrt(rsq11); rinv21 = invsqrt(rsq21); rinv31 = invsqrt(rsq31); /* Load parameters for j atom */ jq = charge[jnr+0]; qq = qO*jq; tj = nti+2*type[jnr]; c6 = vdwparam[tj]; c12 = vdwparam[tj+1]; rinvsq = rinv11*rinv11; /* Coulomb reaction-field interaction */ krsq = krf*rsq11; vcoul = qq*(rinv11+krsq-crf); vctot = vctot+vcoul; /* Calculate table index */ r = rsq11*rinv11; /* Calculate table index */ rt = r*tabscale; n0 = rt; eps = rt-n0; eps2 = eps*eps; nnn = 8*n0; /* Tabulated VdW interaction - dispersion */ Y = VFtab[nnn]; F = VFtab[nnn+1]; Geps = eps*VFtab[nnn+2]; Heps2 = eps2*VFtab[nnn+3]; Fp = F+Geps+Heps2; VV = Y+eps*Fp; FF = Fp+Geps+2.0*Heps2; Vvdw6 = c6*VV; fijD = c6*FF; /* Tabulated VdW interaction - repulsion */ nnn = nnn+4; Y = VFtab[nnn]; F = VFtab[nnn+1]; Geps = eps*VFtab[nnn+2]; Heps2 = eps2*VFtab[nnn+3]; Fp = F+Geps+Heps2; VV = Y+eps*Fp; FF = Fp+Geps+2.0*Heps2; Vvdw12 = c12*VV; fijR = c12*FF; Vvdwtot = Vvdwtot+ Vvdw6 + Vvdw12; fscal = (qq*(rinv11-2.0*krsq))*rinvsq-((fijD+fijR)*tabscale)*rinv11; /* Calculate temporary vectorial force */ tx = fscal*dx11; ty = fscal*dy11; tz = fscal*dz11; /* Increment i atom force */ fix1 = fix1 + tx; fiy1 = fiy1 + ty; fiz1 = fiz1 + tz; /* Decrement j atom force */ fjx1 = faction[j3+0] - tx; fjy1 = faction[j3+1] - ty; fjz1 = faction[j3+2] - tz; /* Load parameters for j atom */ qq = qH*jq; rinvsq = rinv21*rinv21; /* Coulomb reaction-field interaction */ krsq = krf*rsq21; vcoul = qq*(rinv21+krsq-crf); vctot = vctot+vcoul; fscal = (qq*(rinv21-2.0*krsq))*rinvsq; /* Calculate temporary vectorial force */ tx = fscal*dx21; ty = fscal*dy21; tz = fscal*dz21; /* Increment i atom force */ fix2 = fix2 + tx; fiy2 = fiy2 + ty; fiz2 = fiz2 + tz; /* Decrement j atom force */ fjx1 = fjx1 - tx; fjy1 = fjy1 - ty; fjz1 = fjz1 - tz; /* Load parameters for j atom */ rinvsq = rinv31*rinv31; /* Coulomb reaction-field interaction */ krsq = krf*rsq31; vcoul = qq*(rinv31+krsq-crf); vctot = vctot+vcoul; fscal = (qq*(rinv31-2.0*krsq))*rinvsq; /* Calculate temporary vectorial force */ tx = fscal*dx31; ty = fscal*dy31; tz = fscal*dz31; /* Increment i atom force */ fix3 = fix3 + tx; fiy3 = fiy3 + ty; fiz3 = fiz3 + tz; /* Decrement j atom force */ faction[j3+0] = fjx1 - tx; faction[j3+1] = fjy1 - ty; faction[j3+2] = fjz1 - tz; /* Inner loop uses 130 flops/iteration */ } /* Add i forces to mem and shifted force list */ faction[ii3+0] = faction[ii3+0] + fix1; faction[ii3+1] = faction[ii3+1] + fiy1; faction[ii3+2] = faction[ii3+2] + fiz1; faction[ii3+3] = faction[ii3+3] + fix2; faction[ii3+4] = faction[ii3+4] + fiy2; faction[ii3+5] = faction[ii3+5] + fiz2; faction[ii3+6] = faction[ii3+6] + fix3; faction[ii3+7] = faction[ii3+7] + fiy3; faction[ii3+8] = faction[ii3+8] + fiz3; fshift[is3] = fshift[is3]+fix1+fix2+fix3; fshift[is3+1] = fshift[is3+1]+fiy1+fiy2+fiy3; fshift[is3+2] = fshift[is3+2]+fiz1+fiz2+fiz3; /* Add potential energies to the group for this list */ ggid = gid[n]; Vc[ggid] = Vc[ggid] + vctot; Vvdw[ggid] = Vvdw[ggid] + Vvdwtot; /* Increment number of inner iterations */ ninner = ninner + nj1 - nj0; /* Outer loop uses 29 flops/iteration */ } /* Increment number of outer iterations */ nouter = nouter + nn1 - nn0; } while (nn1<nri); /* Write outer/inner iteration count to pointers */ *outeriter = nouter; *inneriter = ninner; }
/* * Gromacs nonbonded kernel nb_kernel410 * Coulomb interaction: Generalized-Born * VdW interaction: Lennard-Jones * water optimization: No * Calculate forces: yes */ void nb_kernel410( int * p_nri, int * iinr, int * jindex, int * jjnr, int * shift, real * shiftvec, real * fshift, int * gid, real * pos, real * faction, real * charge, real * p_facel, real * p_krf, real * p_crf, real * Vc, int * type, int * p_ntype, real * vdwparam, real * Vvdw, real * p_tabscale, real * VFtab,real * enerd1,real * enerd2,real * enerd3,real * enerd4,int * start,int * end,int * homenr,int * nbsum, real * invsqrta, real * dvda, real * p_gbtabscale, real * GBtab, int * p_nthreads, int * count, void * mtx, int * outeriter, int * inneriter, real * work) { int nri,ntype,nthreads; real facel,krf,crf,tabscale,gbtabscale; int n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid; int nn0,nn1,nouter,ninner; real shX,shY,shZ; real fscal,tx,ty,tz; real rinvsq; real iq; real qq,vcoul,vctot; int nti; int tj; real rinvsix; real Vvdw6,Vvdwtot; real Vvdw12; real r,rt,eps,eps2; int n0,nnn; real Y,F,Geps,Heps2,Fp,VV; real FF; real fijC; real isai,isaj,isaprod,gbscale,vgb,vgbtot; real dvdasum,dvdatmp,dvdaj,fgb; real ix1,iy1,iz1,fix1,fiy1,fiz1; real jx1,jy1,jz1; real dx11,dy11,dz11,rsq11,rinv11; real c6,c12; gmx_gbdata_t *gbdata; real * gpol; real scale_gb; gbdata = (gmx_gbdata_t *)work; gpol = gbdata->gpol; nri = *p_nri; ntype = *p_ntype; nthreads = *p_nthreads; facel = *p_facel; scale_gb = 1.0 - (1.0/gbdata->gb_epsilon_solvent); krf = *p_krf; crf = *p_crf; tabscale = *p_tabscale; gbtabscale = *p_gbtabscale; /* Reset outer and inner iteration counters */ nouter = 0; ninner = 0; /* Loop over thread workunits */ do { #ifdef GMX_THREADS gmx_thread_mutex_lock((gmx_thread_mutex_t *)mtx); nn0 = *count; /* Take successively smaller chunks (at least 10 lists) */ nn1 = nn0+(nri-nn0)/(2*nthreads)+10; *count = nn1; gmx_thread_mutex_unlock((gmx_thread_mutex_t *)mtx); if(nn1>nri) nn1=nri; #else nn0 = 0; nn1 = nri; #endif /* Start outer loop over neighborlists */ for(n=nn0; (n<nn1); n++) { /* Load shift vector for this list */ is3 = 3*shift[n]; shX = shiftvec[is3]; shY = shiftvec[is3+1]; shZ = shiftvec[is3+2]; /* Load limits for loop over neighbors */ nj0 = jindex[n]; nj1 = jindex[n+1]; /* Get outer coordinate index */ ii = iinr[n]; ii3 = 3*ii; /* Load i atom data, add shift vector */ ix1 = shX + pos[ii3+0]; iy1 = shY + pos[ii3+1]; iz1 = shZ + pos[ii3+2]; /* Load parameters for i atom */ iq = facel*charge[ii]; isai = invsqrta[ii]; nti = 2*ntype*type[ii]; /* Zero the potential energy for this list */ vctot = 0; Vvdwtot = 0; vgbtot = 0; dvdasum = 0; /* Clear i atom forces */ fix1 = 0; fiy1 = 0; fiz1 = 0; for(k=nj0; (k<nj1); k++) { /* Get j neighbor index, and coordinate index */ jnr = jjnr[k]; j3 = 3*jnr; /* load j atom coordinates */ jx1 = pos[j3+0]; jy1 = pos[j3+1]; jz1 = pos[j3+2]; /* Calculate distance */ dx11 = ix1 - jx1; dy11 = iy1 - jy1; dz11 = iz1 - jz1; rsq11 = dx11*dx11+dy11*dy11+dz11*dz11; /* Calculate 1/r and 1/r2 */ rinv11 = invsqrt(rsq11); /* Load parameters for j atom */ isaj = invsqrta[jnr]; isaprod = isai*isaj; qq = iq*charge[jnr]; vcoul = qq*rinv11; fscal = vcoul*rinv11; qq = isaprod*(-qq)*scale_gb; gbscale = isaprod*gbtabscale; tj = nti+2*type[jnr]; c6 = vdwparam[tj]; c12 = vdwparam[tj+1]; rinvsq = rinv11*rinv11; /* Tabulated Generalized-Born interaction */ dvdaj = dvda[jnr]; r = rsq11*rinv11; /* Calculate table index */ rt = r*gbscale; n0 = rt; eps = rt-n0; eps2 = eps*eps; nnn = 4*n0; Y = GBtab[nnn]; F = GBtab[nnn+1]; Geps = eps*GBtab[nnn+2]; Heps2 = eps2*GBtab[nnn+3]; Fp = F+Geps+Heps2; VV = Y+eps*Fp; FF = Fp+Geps+2.0*Heps2; vgb = qq*VV; fijC = qq*FF*gbscale; dvdatmp = -0.5*(vgb+fijC*r); dvdasum = dvdasum + dvdatmp; dvda[jnr] = dvdaj+dvdatmp*isaj*isaj; vctot = vctot + vcoul; vgbtot = vgbtot + vgb; /* Lennard-Jones interaction */ rinvsix = rinvsq*rinvsq*rinvsq; Vvdw6 = c6*rinvsix; Vvdw12 = c12*rinvsix*rinvsix; Vvdwtot = Vvdwtot+Vvdw12-Vvdw6; fscal = (12.0*Vvdw12-6.0*Vvdw6)*rinvsq-(fijC-fscal)*rinv11; /* Calculate temporary vectorial force */ tx = fscal*dx11; ty = fscal*dy11; tz = fscal*dz11; /* Increment i atom force */ fix1 = fix1 + tx; fiy1 = fiy1 + ty; fiz1 = fiz1 + tz; /* Decrement j atom force */ faction[j3+0] = faction[j3+0] - tx; faction[j3+1] = faction[j3+1] - ty; faction[j3+2] = faction[j3+2] - tz; /* Inner loop uses 62 flops/iteration */ } /* Add i forces to mem and shifted force list */ faction[ii3+0] = faction[ii3+0] + fix1; faction[ii3+1] = faction[ii3+1] + fiy1; faction[ii3+2] = faction[ii3+2] + fiz1; fshift[is3] = fshift[is3]+fix1; fshift[is3+1] = fshift[is3+1]+fiy1; fshift[is3+2] = fshift[is3+2]+fiz1; /* Add potential energies to the group for this list */ ggid = gid[n]; Vc[ggid] = Vc[ggid] + vctot; gpol[ggid] = gpol[ggid] + vgbtot; Vvdw[ggid] = Vvdw[ggid] + Vvdwtot; dvda[ii] = dvda[ii] + dvdasum*isai*isai; /* Increment number of inner iterations */ ninner = ninner + nj1 - nj0; /* Outer loop uses 13 flops/iteration */ } /* Increment number of outer iterations */ nouter = nouter + nn1 - nn0; } while (nn1<nri); /* Write outer/inner iteration count to pointers */ *outeriter = nouter; *inneriter = ninner; }
/* * Gromacs nonbonded kernel nb_kernel121nf * Coulomb interaction: Normal Coulomb * VdW interaction: Buckingham * water optimization: SPC/TIP3P - other atoms * Calculate forces: no */ void nb_kernel121nf( int * p_nri, int * iinr, int * jindex, int * jjnr, int * shift, real * shiftvec, real * fshift, int * gid, real * pos, real * faction, real * charge, real * p_facel, real * p_krf, real * p_crf, real * Vc, int * type, int * p_ntype, real * vdwparam, real * Vvdw, real * p_tabscale, real * VFtab,real * enerd1,real * enerd2,real * enerd3,real * enerd4,int * start,int * end,int * homenr,int * nbsum, real * invsqrta, real * dvda, real * p_gbtabscale, real * GBtab, int * p_nthreads, int * count, void * mtx, int * outeriter, int * inneriter, real * work) { int nri,ntype,nthreads; real facel,krf,crf,tabscale,gbtabscale; int n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid; int nn0,nn1,nouter,ninner; real shX,shY,shZ; real rinvsq; real jq; real qq,vcoul,vctot; int nti; int tj; real rinvsix; real Vvdw6,Vvdwtot; real Vvdwexp,br; real ix1,iy1,iz1; real ix2,iy2,iz2; real ix3,iy3,iz3; real jx1,jy1,jz1; real dx11,dy11,dz11,rsq11,rinv11; real dx21,dy21,dz21,rsq21,rinv21; real dx31,dy31,dz31,rsq31,rinv31; real qO,qH; real c6,cexp1,cexp2; nri = *p_nri; ntype = *p_ntype; nthreads = *p_nthreads; facel = *p_facel; krf = *p_krf; crf = *p_crf; tabscale = *p_tabscale; /* Initialize water data */ ii = iinr[0]; qO = facel*charge[ii]; qH = facel*charge[ii+1]; nti = 3*ntype*type[ii]; /* Reset outer and inner iteration counters */ nouter = 0; ninner = 0; /* Loop over thread workunits */ do { #ifdef GMX_THREADS gmx_thread_mutex_lock((gmx_thread_mutex_t *)mtx); nn0 = *count; /* Take successively smaller chunks (at least 10 lists) */ nn1 = nn0+(nri-nn0)/(2*nthreads)+10; *count = nn1; gmx_thread_mutex_unlock((gmx_thread_mutex_t *)mtx); if(nn1>nri) nn1=nri; #else nn0 = 0; nn1 = nri; #endif /* Start outer loop over neighborlists */ for(n=nn0; (n<nn1); n++) { /* Load shift vector for this list */ is3 = 3*shift[n]; shX = shiftvec[is3]; shY = shiftvec[is3+1]; shZ = shiftvec[is3+2]; /* Load limits for loop over neighbors */ nj0 = jindex[n]; nj1 = jindex[n+1]; /* Get outer coordinate index */ ii = iinr[n]; ii3 = 3*ii; /* Load i atom data, add shift vector */ ix1 = shX + pos[ii3+0]; iy1 = shY + pos[ii3+1]; iz1 = shZ + pos[ii3+2]; ix2 = shX + pos[ii3+3]; iy2 = shY + pos[ii3+4]; iz2 = shZ + pos[ii3+5]; ix3 = shX + pos[ii3+6]; iy3 = shY + pos[ii3+7]; iz3 = shZ + pos[ii3+8]; /* Zero the potential energy for this list */ vctot = 0; Vvdwtot = 0; /* Clear i atom forces */ for(k=nj0; (k<nj1); k++) { /* Get j neighbor index, and coordinate index */ jnr = jjnr[k]; j3 = 3*jnr; /* load j atom coordinates */ jx1 = pos[j3+0]; jy1 = pos[j3+1]; jz1 = pos[j3+2]; /* Calculate distance */ dx11 = ix1 - jx1; dy11 = iy1 - jy1; dz11 = iz1 - jz1; rsq11 = dx11*dx11+dy11*dy11+dz11*dz11; dx21 = ix2 - jx1; dy21 = iy2 - jy1; dz21 = iz2 - jz1; rsq21 = dx21*dx21+dy21*dy21+dz21*dz21; dx31 = ix3 - jx1; dy31 = iy3 - jy1; dz31 = iz3 - jz1; rsq31 = dx31*dx31+dy31*dy31+dz31*dz31; /* Calculate 1/r and 1/r2 */ rinv11 = invsqrt(rsq11); rinv21 = invsqrt(rsq21); rinv31 = invsqrt(rsq31); /* Load parameters for j atom */ jq = charge[jnr+0]; qq = qO*jq; tj = nti+3*type[jnr]; c6 = vdwparam[tj]; cexp1 = vdwparam[tj+1]; cexp2 = vdwparam[tj+2]; rinvsq = rinv11*rinv11; /* Coulomb interaction */ vcoul = qq*rinv11; vctot = vctot+vcoul; /* Buckingham interaction */ rinvsix = rinvsq*rinvsq*rinvsq; Vvdw6 = c6*rinvsix; br = cexp2*rsq11*rinv11; Vvdwexp = cexp1*exp(-br); Vvdwtot = Vvdwtot+Vvdwexp-Vvdw6; /* Load parameters for j atom */ qq = qH*jq; /* Coulomb interaction */ vcoul = qq*rinv21; vctot = vctot+vcoul; /* Load parameters for j atom */ /* Coulomb interaction */ vcoul = qq*rinv31; vctot = vctot+vcoul; /* Inner loop uses 82 flops/iteration */ } /* Add i forces to mem and shifted force list */ /* Add potential energies to the group for this list */ ggid = gid[n]; Vc[ggid] = Vc[ggid] + vctot; Vvdw[ggid] = Vvdw[ggid] + Vvdwtot; /* Increment number of inner iterations */ ninner = ninner + nj1 - nj0; /* Outer loop uses 11 flops/iteration */ } /* Increment number of outer iterations */ nouter = nouter + nn1 - nn0; } while (nn1<nri); /* Write outer/inner iteration count to pointers */ *outeriter = nouter; *inneriter = ninner; }
real orires(int nfa,t_iatom forceatoms[],t_iparams ip[], rvec x[],rvec f[],t_forcerec *fr,t_graph *g, matrix box,real lambda,real *dvdlambda, t_mdatoms *md,int ngrp,real egnb[],real egcoul[], t_fcdata *fcd) { atom_id ai,aj; int fa,d,i,type,ex,power,ki; ivec dt; real r2,invr,invr2,fc,smooth_fc,dev,devins,pfac; rvec r,Sr,fij; real vtot; t_oriresdata *od; bool bTAV; vtot = 0; od = &(fcd->orires); if (fabs(od->fc) > GMX_REAL_MIN) { bTAV = (fabs(od->edt) > GMX_REAL_MIN); /* Smoothly switch on the restraining when time averaging is used */ smooth_fc = od->fc*(1.0 - od->exp_min_t_tau); d = 0; for(fa=0; fa<nfa; fa+=3) { type = forceatoms[fa]; ai = forceatoms[fa+1]; aj = forceatoms[fa+2]; rvec_sub(x[ai],x[aj],r); r2 = norm2(r); invr = invsqrt(r2); invr2 = invr*invr; ex = ip[type].orires.ex; power = ip[type].orires.pow; fc = smooth_fc*ip[type].orires.kfac; dev = od->otav[d] - ip[type].orires.obs; /* NOTE: there is no real potential when time averaging is applied */ vtot += 0.5*fc*sqr(dev); if (bTAV) { /* Calculate the force as the sqrt of tav times instantaneous */ devins = od->oins[d] - ip[type].orires.obs; if (dev*devins <= 0) dev = 0; else { dev = sqrt(dev*devins); if (devins < 0) dev = -dev; } } pfac = fc*ip[type].orires.c*invr2; for(i=0; i<power; i++) pfac *= invr; mvmul(od->S[ex],r,Sr); for(i=0; i<DIM; i++) fij[i] = -pfac*dev*(4*Sr[i] - 2*(2+power)*invr2*iprod(Sr,r)*r[i]); ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt); ki=IVEC2IS(dt); for(i=0; i<DIM; i++) { f[ai][i] += fij[i]; f[aj][i] -= fij[i]; fr->fshift[ki][i] += fij[i]; fr->fshift[CENTRAL][i] -= fij[i]; } d++; } } return vtot; /* Approx. 80*nfa/3 flops */ }
real calc_orires_dev(t_commrec *mcr, int nfa,t_iatom forceatoms[],t_iparams ip[], t_mdatoms *md,rvec x[],t_fcdata *fcd) { int fa,d,i,j,type,ex,nref; real edt,edt1,invn,pfac,r2,invr,corrfac,weight,wsv2,sw,dev; tensor *S,R,TMP; rvec5 *Dinsl,*Dins,*Dtav,*rhs; real *mref,***T; rvec *xref,*xtmp,com,r_unrot,r; t_oriresdata *od; bool bTAV; static real two_thr=2.0/3.0; od = &(fcd->orires); bTAV = (fabs(od->edt)>GMX_REAL_MIN); edt = od->edt; edt1 = od->edt1; S = od->S; Dinsl= od->Dinsl; Dins = od->Dins; Dtav = od->Dtav; T = od->TMP; rhs = od->tmp; nref = od->nref; mref = od->mref; xref = od->xref; xtmp = od->xtmp; od->exp_min_t_tau *= edt; if (mcr) invn = 1.0/mcr->nnodes; else invn = 1.0; j=0; for(i=0; i<md->nr; i++) if (md->cORF[i] == 0) { copy_rvec(x[i],xtmp[j]); for(d=0; d<DIM; d++) com[d] += mref[j]*xref[j][d]; j++; } svmul(od->invmref,com,com); for(j=0; j<nref; j++) rvec_dec(xtmp[j],com); /* Calculate the rotation matrix to rotate x to the reference orientation */ calc_fit_R(nref,mref,xref,xtmp,R); copy_mat(R,od->R); d = 0; for(fa=0; fa<nfa; fa+=3) { type = forceatoms[fa]; rvec_sub(x[forceatoms[fa+1]],x[forceatoms[fa+2]],r_unrot); mvmul(R,r_unrot,r); r2 = norm2(r); invr = invsqrt(r2); /* Calculate the prefactor for the D tensor, this includes the factor 3! */ pfac = ip[type].orires.c*invr*invr*3; for(i=0; i<ip[type].orires.pow; i++) pfac *= invr; Dinsl[d][0] = pfac*(2*r[0]*r[0] + r[1]*r[1] - r2); Dinsl[d][1] = pfac*(2*r[0]*r[1]); Dinsl[d][2] = pfac*(2*r[0]*r[2]); Dinsl[d][3] = pfac*(2*r[1]*r[1] + r[0]*r[0] - r2); Dinsl[d][4] = pfac*(2*r[1]*r[2]); if (mcr) for(i=0; i<5; i++) Dins[d][i] = Dinsl[d][i]*invn; d++; } if (mcr) gmx_sum(5*od->nr,Dins[0],mcr); /* Correction factor to correct for the lack of history for short times */ corrfac = 1.0/(1.0-od->exp_min_t_tau); /* Calculate the order tensor S for each experiment via optimization */ for(ex=0; ex<od->nex; ex++) for(i=0; i<5; i++) { rhs[ex][i] = 0; for(j=0; j<=i; j++) T[ex][i][j] = 0; } d = 0; for(fa=0; fa<nfa; fa+=3) { if (bTAV) for(i=0; i<5; i++) Dtav[d][i] = edt*Dtav[d][i] + edt1*Dins[d][i]; type = forceatoms[fa]; ex = ip[type].orires.ex; weight = ip[type].orires.kfac; /* Calculate the vector rhs and half the matrix T for the 5 equations */ for(i=0; i<5; i++) { rhs[ex][i] += Dtav[d][i]*ip[type].orires.obs*weight; for(j=0; j<=i; j++) T[ex][i][j] += Dtav[d][i]*Dtav[d][j]*weight; } d++; } /* Now we have all the data we can calculate S */ for(ex=0; ex<od->nex; ex++) { /* Correct corrfac and copy one half of T to the other half */ for(i=0; i<5; i++) { rhs[ex][i] *= corrfac; T[ex][i][i] *= sqr(corrfac); for(j=0; j<i; j++) { T[ex][i][j] *= sqr(corrfac); T[ex][j][i] = T[ex][i][j]; } } m_inv_gen(T[ex],5,T[ex]); /* Calculate the orientation tensor S for this experiment */ S[ex][0][0] = 0; S[ex][0][1] = 0; S[ex][0][2] = 0; S[ex][1][1] = 0; S[ex][1][2] = 0; for(i=0; i<5; i++) { S[ex][0][0] += 1.5*T[ex][0][i]*rhs[ex][i]; S[ex][0][1] += 1.5*T[ex][1][i]*rhs[ex][i]; S[ex][0][2] += 1.5*T[ex][2][i]*rhs[ex][i]; S[ex][1][1] += 1.5*T[ex][3][i]*rhs[ex][i]; S[ex][1][2] += 1.5*T[ex][4][i]*rhs[ex][i]; } S[ex][1][0] = S[ex][0][1]; S[ex][2][0] = S[ex][0][2]; S[ex][2][1] = S[ex][1][2]; S[ex][2][2] = -S[ex][0][0] - S[ex][1][1]; } wsv2 = 0; sw = 0; d = 0; for(fa=0; fa<nfa; fa+=3) { type = forceatoms[fa]; ex = ip[type].orires.ex; od->otav[d] = two_thr* corrfac*(S[ex][0][0]*Dtav[d][0] + S[ex][0][1]*Dtav[d][1] + S[ex][0][2]*Dtav[d][2] + S[ex][1][1]*Dtav[d][3] + S[ex][1][2]*Dtav[d][4]); if (bTAV) od->oins[d] = two_thr*(S[ex][0][0]*Dins[d][0] + S[ex][0][1]*Dins[d][1] + S[ex][0][2]*Dins[d][2] + S[ex][1][1]*Dins[d][3] + S[ex][1][2]*Dins[d][4]); if (mcr) /* When ensemble averaging is used recalculate the local orientation * for output to the energy file. */ od->oinsl[d] = two_thr* (S[ex][0][0]*Dinsl[d][0] + S[ex][0][1]*Dinsl[d][1] + S[ex][0][2]*Dinsl[d][2] + S[ex][1][1]*Dinsl[d][3] + S[ex][1][2]*Dinsl[d][4]); dev = od->otav[d] - ip[type].orires.obs; wsv2 += ip[type].orires.kfac*sqr(dev); sw += ip[type].orires.kfac; d++; } od->rmsdev = sqrt(wsv2/sw); /* Rotate the S matrices back, so we get the correct grad(tr(S D)) */ for(ex=0; ex<od->nex; ex++) { tmmul(R,S[ex],TMP); mmul(TMP,R,S[ex]); } return od->rmsdev; /* Approx. 120*nfa/3 flops */ }
ffdotpows *subharm_ffdot_plane(int numharm, int harmnum, double fullrlo, double fullrhi, subharminfo * shi, accelobs * obs) { int ii, lobin, hibin, numdata, nice_numdata, nrs, fftlen, binoffset; static int numrs_full = 0, numzs_full = 0; float powargr, powargi; double drlo, drhi, harm_fract; ffdotpows *ffdot; fcomplex *data, **result; presto_datainf datainf; if (numrs_full == 0) { if (numharm == 1 && harmnum == 1) { numrs_full = ACCEL_USELEN; numzs_full = shi->numkern; } else { printf("You must call subharm_ffdot_plane() with numharm=1 and\n"); printf("harnum=1 before you use other values! Exiting.\n\n"); exit(7); } } ffdot = (ffdotpows *) malloc(sizeof(ffdotpows)); /* Calculate and get the required amplitudes */ harm_fract = (double) harmnum / (double) numharm; drlo = calc_required_r(harm_fract, fullrlo); drhi = calc_required_r(harm_fract, fullrhi); ffdot->rlo = (int) floor(drlo); ffdot->zlo = calc_required_z(harm_fract, obs->zlo); /* Initialize the lookup indices */ if (numharm > 1) { double rr, subr; for (ii = 0; ii < numrs_full; ii++) { rr = fullrlo + ii * ACCEL_DR; subr = calc_required_r(harm_fract, rr); shi->rinds[ii] = index_from_r(subr, ffdot->rlo); } } ffdot->rinds = shi->rinds; ffdot->numrs = (int) ((ceil(drhi) - floor(drlo)) * ACCEL_RDR + DBLCORRECT) + 1; if (numharm == 1 && harmnum == 1) { ffdot->numrs = ACCEL_USELEN; } else { if (ffdot->numrs % ACCEL_RDR) { ffdot->numrs = (ffdot->numrs / ACCEL_RDR + 1) * ACCEL_RDR; } } ffdot->numzs = shi->numkern; binoffset = shi->kern[0].kern_half_width; fftlen = shi->kern[0].fftlen; lobin = ffdot->rlo - binoffset; hibin = (int) ceil(drhi) + binoffset; numdata = hibin - lobin + 1; nice_numdata = next2_to_n(numdata); // for FFTs data = get_fourier_amplitudes(lobin, nice_numdata, obs); if (!obs->mmap_file && !obs->dat_input) printf("This is newly malloc'd!\n"); // Normalize the Fourier amplitudes if (obs->nph > 0.0) { // Use freq 0 normalization if requested (i.e. photons) double norm = 1.0 / sqrt(obs->nph); for (ii = 0; ii < numdata; ii++) { data[ii].r *= norm; data[ii].i *= norm; } } else if (obs->norm_type == 0) { // old-style block median normalization float *powers; double norm; powers = gen_fvect(numdata); for (ii = 0; ii < numdata; ii++) powers[ii] = POWER(data[ii].r, data[ii].i); norm = 1.0 / sqrt(median(powers, numdata)/log(2.0)); free(powers); for (ii = 0; ii < numdata; ii++) { data[ii].r *= norm; data[ii].i *= norm; } } else { // new-style running double-tophat local-power normalization float *powers, *loc_powers; powers = gen_fvect(nice_numdata); for (ii = 0; ii < nice_numdata; ii++) { powers[ii] = POWER(data[ii].r, data[ii].i); } loc_powers = corr_loc_pow(powers, nice_numdata); for (ii = 0; ii < numdata; ii++) { float norm = invsqrt(loc_powers[ii]); data[ii].r *= norm; data[ii].i *= norm; } free(powers); free(loc_powers); } /* Perform the correlations */ result = gen_cmatrix(ffdot->numzs, ffdot->numrs); datainf = RAW; for (ii = 0; ii < ffdot->numzs; ii++) { nrs = corr_complex(data, numdata, datainf, shi->kern[ii].data, fftlen, FFT, result[ii], ffdot->numrs, binoffset, ACCEL_NUMBETWEEN, binoffset, CORR); datainf = SAME; } // Always free data free(data); /* Convert the amplitudes to normalized powers */ ffdot->powers = gen_fmatrix(ffdot->numzs, ffdot->numrs); for (ii = 0; ii < (ffdot->numzs * ffdot->numrs); ii++) ffdot->powers[0][ii] = POWER(result[0][ii].r, result[0][ii].i); free(result[0]); free(result); return ffdot; }