git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@1189 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp 2007-11-30 21:38:34 +00:00
parent bf7903653b
commit 5d0e722080
2 changed files with 77 additions and 82 deletions

View File

@ -795,7 +795,7 @@ void PPPM::deallocate()
void PPPM::set_grid()
{
// see JCP 109, pg. 7698 for derivation of coefficients
// see JCP 109, pg 7698 for derivation of coefficients
// higher order coefficients may be computed if needed
double **acons = memory->create_2d_double_array(8,7,"pppm:acons");
@ -846,119 +846,91 @@ void PPPM::set_grid()
// fluid-occupied volume used to estimate real-space error
// zprd used rather than zprd_slab
double hx,hy,hz;
if (!gewaldflag)
g_ewald = sqrt(-log(precision*sqrt(natoms*cutoff*xprd*yprd*zprd) /
(2.0*q2))) / cutoff;
// set optimal nx_pppm,ny_pppm,nz_pppm based on order and precision
// nz_pppm uses extended zprd_slab instead of zprd
double h,h1,h2,err,er1,er2,lpr;
int ncount;
// h = 1/g_ewald is upper bound on h such that h*g_ewald <= 1
// reduce it until precision target is met
if (!gridflag) {
h = 1.0;
h1 = 2.0;
double err;
hx = hy = hz = 1/g_ewald;
ncount = 0;
err = LARGE;
er1 = 0.0;
while (fabs(err) > SMALL) {
lpr = rms(h,xprd,natoms,q2,acons);
err = log(lpr) - log(precision);
er2 = er1;
er1 = err;
h2 = h1;
h1 = h;
if ((er1 - er2) == 0.0) h = h1 + er1;
else h = h1 + er1*(h2 - h1)/(er1 - er2);
ncount++;
if (ncount > LARGE) error->all("Cannot compute PPPM X grid spacing");
nx_pppm = static_cast<int> (xprd/hx + 1);
ny_pppm = static_cast<int> (yprd/hy + 1);
nz_pppm = static_cast<int> (zprd_slab/hz + 1);
err = rms(hx,xprd,natoms,q2,acons);
while (err > precision) {
err = rms(hx,xprd,natoms,q2,acons);
nx_pppm++;
hx = xprd/nx_pppm;
}
nx_pppm = static_cast<int> (xprd/h + 1);
ncount = 0;
err = LARGE;
er1 = 0.0;
while (fabs(err) > SMALL) {
lpr = rms(h,yprd,natoms,q2,acons);
err = log(lpr) - log(precision);
er2 = er1;
er1 = err;
h2 = h1;
h1 = h;
if ((er1 - er2) == 0.0) h = h1 + er1;
else h = h1 + er1*(h2 - h1)/(er1 - er2);
ncount++;
if (ncount > LARGE) error->all("Cannot compute PPPM Y grid spacing");
err = rms(hy,yprd,natoms,q2,acons);
while (err > precision) {
err = rms(hy,yprd,natoms,q2,acons);
ny_pppm++;
hy = yprd/ny_pppm;
}
ny_pppm = static_cast<int> (yprd/h + 1);
ncount = 0;
err = LARGE;
er1 = 0.0;
while (fabs(err) > SMALL) {
lpr = rms(h,zprd_slab,natoms,q2,acons);
err = log(lpr) - log(precision);
er2 = er1;
er1 = err;
h2 = h1;
h1 = h;
if ((er1 - er2) == 0.0) h = h1 + er1;
else h = h1 + er1*(h2 - h1)/(er1 - er2);
ncount++;
if (ncount > LARGE) error->all("Cannot compute PPPM Z grid spacing");
err = rms(hz,zprd_slab,natoms,q2,acons);
while (err > precision) {
err = rms(hz,zprd_slab,natoms,q2,acons);
nz_pppm++;
hz = zprd_slab/nz_pppm;
}
nz_pppm = static_cast<int> (zprd_slab/h + 1);
}
// convert grid into sizes that are factorable
// boost grid size until it is factorable
while (!factorable(nx_pppm)) nx_pppm++;
while (!factorable(ny_pppm)) ny_pppm++;
while (!factorable(nz_pppm)) nz_pppm++;
// adjust g_ewald for new grid
// adjust g_ewald for new grid size
double dx = xprd/nx_pppm;
double dy = yprd/ny_pppm;
double dz = zprd_slab/nz_pppm;
hx = xprd/nx_pppm;
hy = yprd/ny_pppm;
hz = zprd_slab/nz_pppm;
if (!gewaldflag) {
double gew1,gew2,lprx,lpry,lprz,spr;
double gew1,gew2,dgew,f,fmid,hmin,rtb;
int ncount;
gew1 = g_ewald + 0.01;
gew1 = 0.0;
g_ewald = gew1;
f = diffpr(hx,hy,hz,q2,acons);
hmin = MIN(hx,MIN(hy,hz));
gew2 = 10/hmin;
g_ewald = gew2;
fmid = diffpr(hx,hy,hz,q2,acons);
if (f*fmid >= 0.0) error->all("Cannot compute PPPM G");
rtb = f < 0.0 ? (dgew=gew2-gew1,gew1) : (dgew=gew1-gew2,gew2);
ncount = 0;
err = LARGE;
er1 = 0.0;
while (fabs(err) > SMALL) {
lprx = rms(dx,xprd,natoms,q2,acons);
lpry = rms(dy,yprd,natoms,q2,acons);
lprz = rms(dz,zprd_slab,natoms,q2,acons);
lpr = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
spr = 2.0*q2 * exp(-g_ewald*g_ewald*cutoff*cutoff) /
sqrt(natoms*cutoff*xprd*yprd*zprd_slab);
err = log(lpr) - log(spr);
er2 = er1;
er1 = err;
gew2 = gew1;
gew1 = g_ewald;
if ((er1 - er2) == 0.0) g_ewald = gew1 + er1;
else g_ewald = gew1 + er1*(gew2 - gew1)/(er1 - er2);
while (fabs(dgew) > SMALL && fmid != 0.0) {
dgew *= 0.5;
g_ewald = rtb + dgew;
fmid = diffpr(hx,hy,hz,q2,acons);
if (fmid <= 0.0) rtb = g_ewald;
ncount++;
if (ncount > LARGE) error->all("Cannot compute PPPM G");
}
}
// compute final RMS precision
// final RMS precision
double lprx = rms(dx,xprd,natoms,q2,acons);
double lpry = rms(dy,yprd,natoms,q2,acons);
double lprz = rms(dz,zprd_slab,natoms,q2,acons);
lpr = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
double lprx = rms(hx,xprd,natoms,q2,acons);
double lpry = rms(hy,yprd,natoms,q2,acons);
double lprz = rms(hz,zprd_slab,natoms,q2,acons);
double lpr = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
double spr = 2.0*q2 * exp(-g_ewald*g_ewald*cutoff*cutoff) /
sqrt(natoms*cutoff*xprd*yprd*zprd_slab);
@ -1019,6 +991,28 @@ double PPPM::rms(double h, double prd, double natoms,
return value;
}
/* ----------------------------------------------------------------------
compute difference in real-space and kspace RMS precision
------------------------------------------------------------------------- */
double PPPM::diffpr(double hx, double hy, double hz, double q2, double **acons)
{
double lprx,lpry,lprz,kspace_prec,real_prec;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double natoms = atom->natoms;
lprx = rms(hx,xprd,natoms,q2,acons);
lpry = rms(hy,yprd,natoms,q2,acons);
lprz = rms(hz,zprd*slab_volfactor,natoms,q2,acons);
kspace_prec = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
real_prec = 2.0*q2 * exp(-g_ewald*g_ewald*cutoff*cutoff) /
sqrt(natoms*cutoff*xprd*yprd*zprd);
double value = kspace_prec - real_prec;
return value;
}
/* ----------------------------------------------------------------------
denominator for Hockney-Eastwood Green's function
of x,y,z = sin(kx*deltax/2), etc

View File

@ -78,6 +78,7 @@ class PPPM : public KSpace {
void deallocate();
int factorable(int);
double rms(double, double, double, double, double **);
double diffpr(double, double, double, double, double **);
void compute_gf_denom();
double gf_denom(double, double, double);
virtual void particle_map();