void do_four(const char *fn, const char *cn, int nx, real x[], real dy[], real eps0, real epsRF, const output_env_t oenv) { FILE *fp, *cp; t_complex *tmp, gw, hw, kw; int i, nnx, nxsav; real fac, nu, dt, *ptr, maxeps, numax; nxsav = nx; /*while ((dy[nx-1] == 0.0) && (nx > 0)) nx--;*/ if (nx == 0) { gmx_fatal(FARGS, "Empty dataset in %s, line %d!", __FILE__, __LINE__); } nnx = 1; while (nnx < 2*nx) { nnx *= 2; } snew(tmp, 2*nnx); printf("Doing FFT of %d points\n", nnx); for (i = 0; (i < nx); i++) { tmp[i].re = dy[i]; } ptr = &tmp[0].re; four1(ptr-1, nnx, -1); dt = x[1]-x[0]; if (epsRF == 0) { fac = (eps0-1)/tmp[0].re; } else { fac = ((eps0-1)/(2*epsRF+eps0))/tmp[0].re; } fp = xvgropen(fn, "Epsilon(\\8w\\4)", "Freq. (GHz)", "eps", oenv); cp = xvgropen(cn, "Cole-Cole plot", "Eps'", "Eps''", oenv); maxeps = 0; numax = 0; for (i = 0; (i < nxsav); i++) { if (epsRF == 0) { kw.re = 1+fac*tmp[i].re; kw.im = 1+fac*tmp[i].im; } else { gw = rcmul(fac, tmp[i]); hw = rcmul(2*epsRF, gw); hw.re += 1.0; gw.re = 1.0 - gw.re; gw.im = -gw.im; kw = cdiv(hw, gw); } kw.im *= -1; nu = (i+1)*1000.0/(nnx*dt); if (kw.im > maxeps) { maxeps = kw.im; numax = nu; } fprintf(fp, "%10.5e %10.5e %10.5e\n", nu, kw.re, kw.im); fprintf(cp, "%10.5e %10.5e\n", kw.re, kw.im); } printf("MAXEPS = %10.5e at frequency %10.5e GHz (tauD = %8.1f ps)\n", maxeps, numax, 1000/(2*M_PI*numax)); ffclose(fp); ffclose(cp); sfree(tmp); }
real do_ewald(t_inputrec *ir, rvec x[], rvec f[], real chargeA[], real chargeB[], rvec box, t_commrec *cr, int natoms, matrix lrvir, real ewaldcoeff, real lambda, real *dvdlambda, struct gmx_ewald_tab_t *et) { real factor = -1.0/(4*ewaldcoeff*ewaldcoeff); real scaleRecip = 4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; /* 1/(Vol*e0) */ real *charge, energy_AB[2], energy; rvec lll; int lowiy, lowiz, ix, iy, iz, n, q; real tmp, cs, ss, ak, akv, mx, my, mz, m2, scale; gmx_bool bFreeEnergy; if (cr != NULL) { if (PAR(cr)) { gmx_fatal(FARGS, "No parallel Ewald. Use PME instead.\n"); } } if (!et->eir) /* allocate if we need to */ { snew(et->eir, et->kmax); for (n = 0; n < et->kmax; n++) { snew(et->eir[n], natoms); } snew(et->tab_xy, natoms); snew(et->tab_qxyz, natoms); } bFreeEnergy = (ir->efep != efepNO); clear_mat(lrvir); calc_lll(box, lll); /* make tables for the structure factor parts */ tabulate_eir(natoms, x, et->kmax, et->eir, lll); for (q = 0; q < (bFreeEnergy ? 2 : 1); q++) { if (!bFreeEnergy) { charge = chargeA; scale = 1.0; } else if (q == 0) { charge = chargeA; scale = 1.0 - lambda; } else { charge = chargeB; scale = lambda; } lowiy = 0; lowiz = 1; energy_AB[q] = 0; for (ix = 0; ix < et->nx; ix++) { mx = ix*lll[XX]; for (iy = lowiy; iy < et->ny; iy++) { my = iy*lll[YY]; if (iy >= 0) { for (n = 0; n < natoms; n++) { et->tab_xy[n] = cmul(et->eir[ix][n][XX], et->eir[iy][n][YY]); } } else { for (n = 0; n < natoms; n++) { et->tab_xy[n] = conjmul(et->eir[ix][n][XX], et->eir[-iy][n][YY]); } } for (iz = lowiz; iz < et->nz; iz++) { mz = iz*lll[ZZ]; m2 = mx*mx+my*my+mz*mz; ak = exp(m2*factor)/m2; akv = 2.0*ak*(1.0/m2-factor); if (iz >= 0) { for (n = 0; n < natoms; n++) { et->tab_qxyz[n] = rcmul(charge[n], cmul(et->tab_xy[n], et->eir[iz][n][ZZ])); } } else { for (n = 0; n < natoms; n++) { et->tab_qxyz[n] = rcmul(charge[n], conjmul(et->tab_xy[n], et->eir[-iz][n][ZZ])); } } cs = ss = 0; for (n = 0; n < natoms; n++) { cs += et->tab_qxyz[n].re; ss += et->tab_qxyz[n].im; } energy_AB[q] += ak*(cs*cs+ss*ss); tmp = scale*akv*(cs*cs+ss*ss); lrvir[XX][XX] -= tmp*mx*mx; lrvir[XX][YY] -= tmp*mx*my; lrvir[XX][ZZ] -= tmp*mx*mz; lrvir[YY][YY] -= tmp*my*my; lrvir[YY][ZZ] -= tmp*my*mz; lrvir[ZZ][ZZ] -= tmp*mz*mz; for (n = 0; n < natoms; n++) { /*tmp=scale*ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re);*/ tmp = scale*ak*(cs*et->tab_qxyz[n].im-ss*et->tab_qxyz[n].re); f[n][XX] += tmp*mx*2*scaleRecip; f[n][YY] += tmp*my*2*scaleRecip; f[n][ZZ] += tmp*mz*2*scaleRecip; #if 0 f[n][XX] += tmp*mx; f[n][YY] += tmp*my; f[n][ZZ] += tmp*mz; #endif } lowiz = 1-et->nz; } lowiy = 1-et->ny; } } } if (!bFreeEnergy) { energy = energy_AB[0]; } else { energy = (1.0 - lambda)*energy_AB[0] + lambda*energy_AB[1]; *dvdlambda += scaleRecip*(energy_AB[1] - energy_AB[0]); } lrvir[XX][XX] = -0.5*scaleRecip*(lrvir[XX][XX]+energy); lrvir[XX][YY] = -0.5*scaleRecip*(lrvir[XX][YY]); lrvir[XX][ZZ] = -0.5*scaleRecip*(lrvir[XX][ZZ]); lrvir[YY][YY] = -0.5*scaleRecip*(lrvir[YY][YY]+energy); lrvir[YY][ZZ] = -0.5*scaleRecip*(lrvir[YY][ZZ]); lrvir[ZZ][ZZ] = -0.5*scaleRecip*(lrvir[ZZ][ZZ]+energy); lrvir[YY][XX] = lrvir[XX][YY]; lrvir[ZZ][XX] = lrvir[XX][ZZ]; lrvir[ZZ][YY] = lrvir[YY][ZZ]; energy *= scaleRecip; return energy; }
real do_ewald(FILE *log, bool bVerbose, t_inputrec *ir, rvec x[], rvec f[], real charge[], rvec box, t_commrec *cr, t_nsborder *nsb, matrix lrvir, real ewaldcoeff) { static bool bFirst = TRUE; static int nx,ny,nz,kmax; static cvec **eir; static t_complex *tab_xy,*tab_qxyz; real factor=-1.0/(4*ewaldcoeff*ewaldcoeff); real energy; rvec lll; int lowiy,lowiz,ix,iy,iz,n; real tmp,cs,ss,ak,akv,mx,my,mz,m2; if (bFirst) { if (bVerbose) fprintf(log,"Will do ordinary reciprocal space Ewald sum.\n"); if (cr != NULL) { if (cr->nnodes > 1 || cr->nthreads>1) fatal_error(0,"No parallel Ewald. Use PME instead.\n"); } nx = ir->nkx+1; ny = ir->nky+1; nz = ir->nkz+1; kmax = max(nx,max(ny,nz)); snew(eir,kmax); for(n=0;n<kmax;n++) snew(eir[n],HOMENR(nsb)); snew(tab_xy,HOMENR(nsb)); snew(tab_qxyz,HOMENR(nsb)); bFirst = FALSE; } clear_mat(lrvir); calc_lll(box,lll); /* make tables for the structure factor parts */ tabulate_eir(HOMENR(nsb),x,kmax,eir,lll); lowiy=0; lowiz=1; energy=0; for(ix=0;ix<nx;ix++) { mx=ix*lll[XX]; for(iy=lowiy;iy<ny;iy++) { my=iy*lll[YY]; if(iy>=0) for(n=0;n<HOMENR(nsb);n++) tab_xy[n]=cmul(eir[ix][n][XX],eir[iy][n][YY]); else for(n=0;n<HOMENR(nsb);n++) tab_xy[n]=conjmul(eir[ix][n][XX],eir[-iy][n][YY]); for(iz=lowiz;iz<nz;iz++) { mz=iz*lll[ZZ]; m2=mx*mx+my*my+mz*mz; ak=exp(m2*factor)/m2; akv=2.0*ak*(1.0/m2-factor); if(iz>=0) for(n=0;n<HOMENR(nsb);n++) tab_qxyz[n]=rcmul(charge[n],cmul(tab_xy[n],eir[iz][n][ZZ])); else for(n=0;n<HOMENR(nsb);n++) tab_qxyz[n]=rcmul(charge[n],conjmul(tab_xy[n],eir[-iz][n][ZZ])); cs=ss=0; for(n=0;n<HOMENR(nsb);n++) { cs+=tab_qxyz[n].re; ss+=tab_qxyz[n].im; } energy+=ak*(cs*cs+ss*ss); tmp=akv*(cs*cs+ss*ss); lrvir[XX][XX]-=tmp*mx*mx; lrvir[XX][YY]-=tmp*mx*my; lrvir[XX][ZZ]-=tmp*mx*mz; lrvir[YY][YY]-=tmp*my*my; lrvir[YY][ZZ]-=tmp*my*mz; lrvir[ZZ][ZZ]-=tmp*mz*mz; for(n=0;n<HOMENR(nsb);n++) { tmp=ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re); f[n][XX]+=tmp*mx; f[n][YY]+=tmp*my; f[n][ZZ]+=tmp*mz; } lowiz=1-nz; } lowiy=1-ny; } } tmp=4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0; for(n=0;n<HOMENR(nsb);n++) { f[n][XX]*=2*tmp; f[n][YY]*=2*tmp; f[n][ZZ]*=2*tmp; } lrvir[XX][XX]=-0.5*tmp*(lrvir[XX][XX]+energy); lrvir[XX][YY]=-0.5*tmp*(lrvir[XX][YY]); lrvir[XX][ZZ]=-0.5*tmp*(lrvir[XX][ZZ]); lrvir[YY][YY]=-0.5*tmp*(lrvir[YY][YY]+energy); lrvir[YY][ZZ]=-0.5*tmp*(lrvir[YY][ZZ]); lrvir[ZZ][ZZ]=-0.5*tmp*(lrvir[ZZ][ZZ]+energy); lrvir[YY][XX]=lrvir[XX][YY]; lrvir[ZZ][XX]=lrvir[XX][ZZ]; lrvir[ZZ][YY]=lrvir[YY][ZZ]; energy*=tmp; return energy; }
real do_ewald(FILE *log, bool bVerbose, t_inputrec *ir, rvec x[], rvec f[], real chargeA[], real chargeB[], rvec box, t_commrec *cr, int natoms, matrix lrvir, real ewaldcoeff, real lambda, real *dvdlambda) { static bool bFirst = TRUE; static int nx,ny,nz,kmax; static cvec **eir; static t_complex *tab_xy,*tab_qxyz; real factor=-1.0/(4*ewaldcoeff*ewaldcoeff); real *charge,energy_AB[2],energy; rvec lll; int lowiy,lowiz,ix,iy,iz,n,q; real tmp,cs,ss,ak,akv,mx,my,mz,m2,scale; bool bFreeEnergy; bFreeEnergy = (ir->efep != efepNO); if (bFirst) { if (bVerbose) fprintf(log,"Will do ordinary reciprocal space Ewald sum.\n"); if (cr != NULL) { if (cr->nnodes > 1 || cr->nthreads>1) gmx_fatal(FARGS,"No parallel Ewald. Use PME instead.\n"); } nx = ir->nkx+1; ny = ir->nky+1; nz = ir->nkz+1; kmax = max(nx,max(ny,nz)); snew(eir,kmax); for(n=0;n<kmax;n++) snew(eir[n],natoms); snew(tab_xy,natoms); snew(tab_qxyz,natoms); bFirst = FALSE; } clear_mat(lrvir); calc_lll(box,lll); /* make tables for the structure factor parts */ tabulate_eir(natoms,x,kmax,eir,lll); for(q=0; q<(bFreeEnergy ? 2 : 1); q++) { if (!bFreeEnergy) { charge = chargeA; scale = 1.0; } else if (q==0) { charge = chargeA; scale = 1.0 - lambda; } else { charge = chargeB; scale = lambda; } lowiy=0; lowiz=1; energy_AB[q]=0; for(ix=0;ix<nx;ix++) { mx=ix*lll[XX]; for(iy=lowiy;iy<ny;iy++) { my=iy*lll[YY]; if(iy>=0) for(n=0;n<natoms;n++) tab_xy[n]=cmul(eir[ix][n][XX],eir[iy][n][YY]); else for(n=0;n<natoms;n++) tab_xy[n]=conjmul(eir[ix][n][XX],eir[-iy][n][YY]); for(iz=lowiz;iz<nz;iz++) { mz=iz*lll[ZZ]; m2=mx*mx+my*my+mz*mz; ak=exp(m2*factor)/m2; akv=2.0*ak*(1.0/m2-factor); if(iz>=0) for(n=0;n<natoms;n++) tab_qxyz[n]=rcmul(charge[n],cmul(tab_xy[n],eir[iz][n][ZZ])); else for(n=0;n<natoms;n++) tab_qxyz[n]=rcmul(charge[n],conjmul(tab_xy[n],eir[-iz][n][ZZ])); cs=ss=0; for(n=0;n<natoms;n++) { cs+=tab_qxyz[n].re; ss+=tab_qxyz[n].im; } energy_AB[q]+=ak*(cs*cs+ss*ss); tmp=scale*akv*(cs*cs+ss*ss); lrvir[XX][XX]-=tmp*mx*mx; lrvir[XX][YY]-=tmp*mx*my; lrvir[XX][ZZ]-=tmp*mx*mz; lrvir[YY][YY]-=tmp*my*my; lrvir[YY][ZZ]-=tmp*my*mz; lrvir[ZZ][ZZ]-=tmp*mz*mz; for(n=0;n<natoms;n++) { tmp=scale*ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re); f[n][XX]+=tmp*mx; f[n][YY]+=tmp*my; f[n][ZZ]+=tmp*mz; } lowiz=1-nz; } lowiy=1-ny; } } } tmp=4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; if (!bFreeEnergy) { energy = energy_AB[0]; } else { energy = (1.0 - lambda)*energy_AB[0] + lambda*energy_AB[1]; *dvdlambda += tmp*(energy_AB[1] - energy_AB[0]); } for(n=0;n<natoms;n++) { f[n][XX]*=2*tmp; f[n][YY]*=2*tmp; f[n][ZZ]*=2*tmp; } lrvir[XX][XX]=-0.5*tmp*(lrvir[XX][XX]+energy); lrvir[XX][YY]=-0.5*tmp*(lrvir[XX][YY]); lrvir[XX][ZZ]=-0.5*tmp*(lrvir[XX][ZZ]); lrvir[YY][YY]=-0.5*tmp*(lrvir[YY][YY]+energy); lrvir[YY][ZZ]=-0.5*tmp*(lrvir[YY][ZZ]); lrvir[ZZ][ZZ]=-0.5*tmp*(lrvir[ZZ][ZZ]+energy); lrvir[YY][XX]=lrvir[XX][YY]; lrvir[ZZ][XX]=lrvir[XX][ZZ]; lrvir[ZZ][YY]=lrvir[YY][ZZ]; energy*=tmp; return energy; }