diff --git a/src/compute_epair_atom.cpp b/src/compute_epair_atom.cpp index a4a8160202..36a16d92be 100644 --- a/src/compute_epair_atom.cpp +++ b/src/compute_epair_atom.cpp @@ -72,10 +72,11 @@ void ComputeEpairAtom::init() void ComputeEpairAtom::compute_peratom() { - int i,j,k,n,itype,jtype,numneigh; + int i,j,k,n,itype,jtype,numneigh,iflag; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; - double factor_coul,factor_lj,e; + double factor_coul,factor_lj,eng; int *neighs; + Pair::One one; // grow energy array if necessary @@ -90,8 +91,11 @@ void ComputeEpairAtom::compute_peratom() // clear energy array // n includes ghosts only if newton_pair flag is set - if (force->newton_pair) n = atom->nlocal + atom->nghost; - else n = atom->nlocal; + int nlocal = atom->nlocal; + int newton_pair = force->newton_pair; + + if (newton_pair) n = nlocal + atom->nghost; + else n = nlocal; for (i = 0; i < n; i++) energy[i] = 0.0; @@ -99,30 +103,30 @@ void ComputeEpairAtom::compute_peratom() if (!neighbor->half_every) neighbor->build_half(); - // compute pairwise energy for all atoms via pair->single() - // ignore compute group, since using half neighbor list + // compute pairwise energy for atoms via pair->single() + // if neither atom is in compute group, skip that pair double *special_coul = force->special_coul; double *special_lj = force->special_lj; double **cutsq = force->pair->cutsq; double **x = atom->x; + int *mask = atom->mask; int *type = atom->type; - int nlocal = atom->nlocal; - int nall = atom->nlocal + atom->nghost; - - Pair::One one; + int nall = nlocal + atom->nghost; for (i = 0; i < nlocal; i++) { xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; + iflag = mask[i] & groupbit; neighs = neighbor->firstneigh[i]; numneigh = neighbor->numneigh[i]; for (k = 0; k < numneigh; k++) { j = neighs[k]; + if (iflag == 0 && (mask[j] & groupbit) == 0) continue; if (j < nall) factor_coul = factor_lj = 1.0; else { @@ -139,30 +143,30 @@ void ComputeEpairAtom::compute_peratom() if (rsq < cutsq[itype][jtype]) { force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,1,one); - e = one.eng_coul + one.eng_vdwl; - energy[i] += e; - energy[j] += e; + eng = one.eng_coul + one.eng_vdwl; + energy[i] += eng; + if (newton_pair || j < nlocal) energy[j] += eng; } } } // communicate energy between neigchbor procs - if (force->newton_pair) comm->reverse_comm_compute(this); + if (newton_pair) comm->reverse_comm_compute(this); // remove double counting of per-atom energy for (i = 0; i < nlocal; i++) energy[i] *= 0.5; // for EAM, include embedding function contribution to energy + // only for atoms in compute group if (eamstyle) { - int *type = atom->type; - double etmp = 0.0; - for (i = 0; i < nlocal; i++) { - force->pair->single_embed(i,type[i],etmp); - energy[i] += etmp; + if (mask[i] & groupbit) { + force->pair->single_embed(i,type[i],eng); + energy[i] += eng; + } } } } diff --git a/src/compute_stress_atom.cpp b/src/compute_stress_atom.cpp index 7353c32723..1ff7541124 100644 --- a/src/compute_stress_atom.cpp +++ b/src/compute_stress_atom.cpp @@ -19,7 +19,9 @@ #include "comm.h" #include "update.h" #include "force.h" +#include "bond.h" #include "pair.h" +#include "domain.h" #include "memory.h" #include "error.h" @@ -33,13 +35,37 @@ using namespace LAMMPS_NS; ComputeStressAtom::ComputeStressAtom(LAMMPS *lmp, int narg, char **arg) : Compute(lmp, narg, arg) { - if (narg != 3) error->all("Illegal compute stress/atom command"); + if (narg < 3) error->all("Illegal compute stress/atom command"); peratom_flag = 1; size_peratom = 6; comm_reverse = 6; neigh_half_once = 1; + // process args + + kerequest = pairrequest = bondrequest = 1; + + int iarg = 3; + while (iarg < narg) { + if (strcmp(arg[iarg],"ke") == 0) { + if (iarg+2 > narg) error->all("Illegal compute ebond/atom command"); + if (strcmp(arg[iarg+1],"yes") == 0) kerequest = 1; + else if (strcmp(arg[iarg+1],"no") == 0) kerequest = 0; + iarg += 2; + } else if (strcmp(arg[iarg],"pair") == 0) { + if (iarg+2 > narg) error->all("Illegal compute ebond/atom command"); + if (strcmp(arg[iarg+1],"yes") == 0) pairrequest = 1; + else if (strcmp(arg[iarg+1],"no") == 0) pairrequest = 0; + iarg += 2; + } else if (strcmp(arg[iarg],"bond") == 0) { + if (iarg+2 > narg) error->all("Illegal compute ebond/atom command"); + if (strcmp(arg[iarg+1],"yes") == 0) bondrequest = 1; + else if (strcmp(arg[iarg+1],"no") == 0) bondrequest = 0; + iarg += 2; + } else error->all("Illegal compute ebond/atom command"); + } + nmax = 0; stress = NULL; } @@ -55,8 +81,14 @@ ComputeStressAtom::~ComputeStressAtom() void ComputeStressAtom::init() { - if (force->pair == NULL || force->pair->single_enable == 0) - error->all("Pair style does not support computing per-atom stress"); + if (pairrequest) { + if (force->pair == NULL || force->pair->single_enable == 0) + error->all("Pair style does not support computing per-atom stress"); + pairflag = 1; + } else pairflag = 0; + + if (bondrequest && force->bond) bondflag = 1; + else bondflag = 0; int count = 0; for (int i = 0; i < modify->ncompute; i++) @@ -69,8 +101,8 @@ void ComputeStressAtom::init() void ComputeStressAtom::compute_peratom() { - int i,j,k,n,itype,jtype,numneigh; - double xtmp,ytmp,ztmp,delx,dely,delz,rsq; + int i,j,k,n,i1,i2,itype,jtype,numneigh,iflag; + double xtmp,ytmp,ztmp,delx,dely,delz,rsq,eng; double factor_coul,factor_lj,fforce,rmass; int *neighs; Pair::One one; @@ -86,10 +118,12 @@ void ComputeStressAtom::compute_peratom() } // clear stress array - // n includes ghosts only if newton_pair flag is set + // n includes ghosts only if newton flag is set - if (force->newton_pair) n = atom->nlocal + atom->nghost; - else n = atom->nlocal; + int nlocal = atom->nlocal; + + if (force->newton) n = nlocal + atom->nghost; + else n = nlocal; for (i = 0; i < n; i++) { stress[i][0] = 0.0; @@ -100,73 +134,123 @@ void ComputeStressAtom::compute_peratom() stress[i][5] = 0.0; } - // if needed, build a half neighbor list + // compute pairwise stress for atoms via pair->single() + // if neither atom is in compute group, skip that pair - if (!neighbor->half_every) neighbor->build_half(); + if (pairflag) { - // compute pairwise stress for all atoms via pair->single() - // use half neighbor list + // if needed, build a half neighbor list - double *special_coul = force->special_coul; - double *special_lj = force->special_lj; - double **cutsq = force->pair->cutsq; + if (!neighbor->half_every) neighbor->build_half(); - double **x = atom->x; - int *type = atom->type; - int nlocal = atom->nlocal; - int nall = atom->nlocal + atom->nghost; + double *special_coul = force->special_coul; + double *special_lj = force->special_lj; + double **cutsq = force->pair->cutsq; + int newton_pair = force->newton_pair; - for (i = 0; i < nlocal; i++) { - xtmp = x[i][0]; - ytmp = x[i][1]; - ztmp = x[i][2]; - itype = type[i]; - neighs = neighbor->firstneigh[i]; - numneigh = neighbor->numneigh[i]; - - for (k = 0; k < numneigh; k++) { - j = neighs[k]; + double **x = atom->x; + int *mask = atom->mask; + int *type = atom->type; + int nall = nlocal + atom->nghost; - if (j < nall) factor_coul = factor_lj = 1.0; - else { - factor_coul = special_coul[j/nall]; - factor_lj = special_lj[j/nall]; - j %= nall; - } + for (i = 0; i < nlocal; i++) { + xtmp = x[i][0]; + ytmp = x[i][1]; + ztmp = x[i][2]; + itype = type[i]; + iflag = mask[i] & groupbit; + neighs = neighbor->firstneigh[i]; + numneigh = neighbor->numneigh[i]; + + for (k = 0; k < numneigh; k++) { + j = neighs[k]; + if (iflag == 0 && (mask[j] & groupbit) == 0) continue; - delx = xtmp - x[j][0]; - dely = ytmp - x[j][1]; - delz = ztmp - x[j][2]; - rsq = delx*delx + dely*dely + delz*delz; - jtype = type[j]; - - if (rsq < cutsq[itype][jtype]) { - force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,0,one); - fforce = one.fforce; - - stress[i][0] -= delx*delx*fforce; - stress[i][1] -= dely*dely*fforce; - stress[i][2] -= delz*delz*fforce; - stress[i][3] -= delx*dely*fforce; - stress[i][4] -= delx*delz*fforce; - stress[i][5] -= dely*delz*fforce; - if (force->newton_pair || j < nlocal) { - stress[j][0] -= delx*delx*fforce; - stress[j][1] -= dely*dely*fforce; - stress[j][2] -= delz*delz*fforce; - stress[j][3] -= delx*dely*fforce; - stress[j][4] -= delx*delz*fforce; - stress[j][5] -= dely*delz*fforce; + if (j < nall) factor_coul = factor_lj = 1.0; + else { + factor_coul = special_coul[j/nall]; + factor_lj = special_lj[j/nall]; + j %= nall; } + + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx*delx + dely*dely + delz*delz; + jtype = type[j]; + + if (rsq < cutsq[itype][jtype]) { + force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,0,one); + fforce = one.fforce; + + stress[i][0] -= delx*delx*fforce; + stress[i][1] -= dely*dely*fforce; + stress[i][2] -= delz*delz*fforce; + stress[i][3] -= delx*dely*fforce; + stress[i][4] -= delx*delz*fforce; + stress[i][5] -= dely*delz*fforce; + if (newton_pair || j < nlocal) { + stress[j][0] -= delx*delx*fforce; + stress[j][1] -= dely*dely*fforce; + stress[j][2] -= delz*delz*fforce; + stress[j][3] -= delx*dely*fforce; + stress[j][4] -= delx*delz*fforce; + stress[j][5] -= dely*delz*fforce; + } + } + } + } + + } + + // compute bond stress for atoms via bond->single() + // if neither atom is in compute group, skip that bond + + if (bondflag) { + double **x = atom->x; + int *mask = atom->mask; + int **bondlist = neighbor->bondlist; + int nbondlist = neighbor->nbondlist; + int newton_bond = force->newton_bond; + int type; + + for (n = 0; n < nbondlist; n++) { + i1 = bondlist[n][0]; + i2 = bondlist[n][1]; + type = bondlist[n][2]; + if ((mask[i1] & groupbit) == 0 && (mask[i2] & groupbit) == 0) continue; + + delx = x[i1][0] - x[i2][0]; + dely = x[i1][1] - x[i2][1]; + delz = x[i1][2] - x[i2][2]; + domain->minimum_image(delx,dely,delz); + + rsq = delx*delx + dely*dely + delz*delz; + force->bond->single(type,rsq,i1,i2,0,fforce,eng); + + stress[i1][0] -= delx*delx*fforce; + stress[i1][1] -= dely*dely*fforce; + stress[i1][2] -= delz*delz*fforce; + stress[i1][3] -= delx*dely*fforce; + stress[i1][4] -= delx*delz*fforce; + stress[i1][5] -= dely*delz*fforce; + + if (newton_bond || i2 < nlocal) { + stress[i2][0] -= delx*delx*fforce; + stress[i2][1] -= dely*dely*fforce; + stress[i2][2] -= delz*delz*fforce; + stress[i2][3] -= delx*dely*fforce; + stress[i2][4] -= delx*delz*fforce; + stress[i2][5] -= dely*delz*fforce; } } } // communicate stress between neighbor procs - if (force->newton_pair) comm->reverse_comm_compute(this); + if (force->newton) comm->reverse_comm_compute(this); - // remove double counting of per-atom stress + // remove double counting for (i = 0; i < nlocal; i++) { stress[i][0] *= 0.5; @@ -177,21 +261,27 @@ void ComputeStressAtom::compute_peratom() stress[i][5] *= 0.5; } - // include kinetic energy term for each atom + // include kinetic energy term for each atom in group // mvv2e converts mv^2 to energy - double **v = atom->v; - double *mass = atom->mass; - double mvv2e = force->mvv2e; - - for (i = 0; i < nlocal; i++) { - rmass = mvv2e * mass[type[i]]; - stress[i][0] -= rmass*v[i][0]*v[i][0]; - stress[i][1] -= rmass*v[i][1]*v[i][1]; - stress[i][2] -= rmass*v[i][2]*v[i][2]; - stress[i][3] -= rmass*v[i][0]*v[i][1]; - stress[i][4] -= rmass*v[i][0]*v[i][2]; - stress[i][5] -= rmass*v[i][1]*v[i][2]; + if (kerequest) { + double **v = atom->v; + double *mass = atom->mass; + int *mask = atom->mask; + int *type = atom->type; + double mvv2e = force->mvv2e; + + for (i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + rmass = mvv2e * mass[type[i]]; + stress[i][0] -= rmass*v[i][0]*v[i][0]; + stress[i][1] -= rmass*v[i][1]*v[i][1]; + stress[i][2] -= rmass*v[i][2]*v[i][2]; + stress[i][3] -= rmass*v[i][0]*v[i][1]; + stress[i][4] -= rmass*v[i][0]*v[i][2]; + stress[i][5] -= rmass*v[i][1]*v[i][2]; + } + } } // convert to pressure units (actually stress/volume = pressure) diff --git a/src/compute_stress_atom.h b/src/compute_stress_atom.h index f795a7899a..469fc331e3 100644 --- a/src/compute_stress_atom.h +++ b/src/compute_stress_atom.h @@ -30,7 +30,10 @@ class ComputeStressAtom : public Compute { int memory_usage(); private: + int pairrequest,bondrequest,kerequest; + int pairflag,bondflag; int nmax; + double **stress; }; diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 3456b3ab0d..3561aea034 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -33,7 +33,7 @@ enum{TAG,MOL,TYPE,X,Y,Z,XS,YS,ZS,XU,YU,ZU,IX,IY,IZ, VX,VY,VZ,FX,FY,FZ, Q,MUX,MUY,MUZ, QUATW,QUATI,QUATJ,QUATK,TQX,TQY,TQZ, - EPAIR,KE,ETOTAL,CENTRO,SXX,SYY,SZZ,SXY,SXZ,SYZ, + EPAIR,EBOND,KE,ETOTAL,CENTRO,SXX,SYY,SZZ,SXY,SXZ,SYZ, COMPUTE}; enum{LT,LE,GT,GE,EQ,NEQ}; enum{INT,DOUBLE}; @@ -57,9 +57,11 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) : // flags, IDs, and memory for compute objects dump may create - index_epair = index_ke = index_etotal = index_centro = index_stress = -1; + index_epair = index_ebond = index_ke = + index_etotal = index_centro = index_stress = -1; style_epair = "epair/atom"; + style_ebond = "ebond/atom"; style_ke = "ke/atom"; style_etotal = "etotal/atom"; style_centro = "centro/atom"; @@ -79,6 +81,7 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) : // create the requested Computes if (index_epair >= 0) create_compute(style_epair,NULL); + if (index_ebond >= 0) create_compute(style_ebond,NULL); if (index_ke >= 0) create_compute(style_ke,NULL); if (index_etotal >= 0) create_compute(style_etotal,style_epair); if (index_centro >= 0) create_compute(style_centro,NULL); @@ -122,6 +125,7 @@ DumpCustom::~DumpCustom() // delete Compute classes if dump custom created them if (index_epair >= 0) modify->delete_compute(id_compute[index_epair]); + if (index_ebond >= 0) modify->delete_compute(id_compute[index_ebond]); if (index_ke >= 0) modify->delete_compute(id_compute[index_ke]); if (index_etotal >= 0) modify->delete_compute(id_compute[index_etotal]); if (index_centro >= 0) modify->delete_compute(id_compute[index_centro]); @@ -430,6 +434,9 @@ int DumpCustom::count() } else if (thresh_array[ithresh] == EPAIR) { ptr = compute[index_epair]->scalar_atom; nstride = 1; + } else if (thresh_array[ithresh] == EBOND) { + ptr = compute[index_ebond]->scalar_atom; + nstride = 1; } else if (thresh_array[ithresh] == KE) { ptr = compute[index_ke]->scalar_atom; nstride = 1; @@ -701,6 +708,10 @@ void DumpCustom::parse_fields(int narg, char **arg) pack_choice[i] = &DumpCustom::pack_epair; vtype[i] = DOUBLE; index_epair = add_compute(style_epair,1); + } else if (strcmp(arg[iarg],"ebond") == 0) { + pack_choice[i] = &DumpCustom::pack_ebond; + vtype[i] = DOUBLE; + index_ebond = add_compute(style_ebond,1); } else if (strcmp(arg[iarg],"ke") == 0) { pack_choice[i] = &DumpCustom::pack_ke; vtype[i] = DOUBLE; @@ -943,6 +954,12 @@ int DumpCustom::modify_param(int narg, char **arg) index_epair = add_compute(style_epair,1); create_compute(style_epair,NULL); } + } else if (strcmp(arg[1],"ebond") == 0) { + thresh_array[nthresh] = EBOND; + if (index_ebond < 0) { + index_ebond = add_compute(style_ebond,1); + create_compute(style_ebond,NULL); + } } else if (strcmp(arg[1],"ke") == 0) { thresh_array[nthresh] = KE; if (index_ke < 0) { @@ -1591,6 +1608,20 @@ void DumpCustom::pack_epair(int n) /* ---------------------------------------------------------------------- */ +void DumpCustom::pack_ebond(int n) +{ + double *ebond = compute[index_ebond]->scalar_atom; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) + if (choose[i]) { + buf[n] = ebond[i]; + n += size_one; + } +} + +/* ---------------------------------------------------------------------- */ + void DumpCustom::pack_ke(int n) { double *ke = compute[index_ke]->scalar_atom; diff --git a/src/dump_custom.h b/src/dump_custom.h index 62a4801e27..501a9fa03e 100644 --- a/src/dump_custom.h +++ b/src/dump_custom.h @@ -50,8 +50,9 @@ class DumpCustom : public Dump { // index = where keyword's Compute is in list // style = style of Compute object - int index_epair,index_ke,index_etotal,index_centro,index_stress; - char *style_epair,*style_ke,*style_etotal,*style_centro,*style_stress; + int index_epair,index_ebond,index_ke,index_etotal,index_centro,index_stress; + char *style_epair,*style_ebond,*style_ke,*style_etotal; + char *style_centro,*style_stress; // private methods @@ -117,6 +118,7 @@ class DumpCustom : public Dump { void pack_etotal(int); void pack_ke(int); void pack_epair(int); + void pack_ebond(int); void pack_centro(int); void pack_sxx(int); void pack_syy(int);