diff --git a/src/CORESHELL/pair_lj_cut_coul_long_cs.cpp b/src/CORESHELL/pair_lj_cut_coul_long_cs.cpp index e2ffda148..d418cf20a 100644 --- a/src/CORESHELL/pair_lj_cut_coul_long_cs.cpp +++ b/src/CORESHELL/pair_lj_cut_coul_long_cs.cpp @@ -1,572 +1,572 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Hendrik Heenen (hendrik.heenen@mytum.de) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_cut_coul_long_cs.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; #define EWALD_F 1.12837917 #define EWALD_P 9.95473818e-1 #define B0 -0.1335096380159268 #define B1 -2.57839507e-1 #define B2 -1.37203639e-1 #define B3 -8.88822059e-3 #define B4 -5.80844129e-3 #define B5 1.14652755e-1 #define EPSILON 1.0e-20 #define EPS_EWALD 1.0e-6 #define EPS_EWALD_SQR 1.0e-12 /* ---------------------------------------------------------------------- */ PairLJCutCoulLongCS::PairLJCutCoulLongCS(LAMMPS *lmp) : PairLJCutCoulLong(lmp) { ewaldflag = pppmflag = 1; respa_enable = 1; writedata = 1; ftable = NULL; qdist = 0.0; } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongCS::compute(int eflag, int vflag) { int i,ii,j,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc,u; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { rsq += EPSILON; // Add Epsilon for case: r = 0; Interaction must be removed by special bond; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); prefactor = qqrd2e * qtmp*q[j]; if (factor_coul < 1.0) { // When bonded parts are being calculated a minimal distance (EPS_EWALD) // has to be added to the prefactor and erfc in order to make the // used approximation functions for the Ewald correction valid grij = g_ewald * (r+EPS_EWALD); expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); u = 1.0 - t; erfc = t * (1.+u*(B0+u*(B1+u*(B2+u*(B3+u*(B4+u*B5)))))) * expm2; prefactor /= (r+EPS_EWALD); forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - (1.0-factor_coul)); // Additionally r2inv needs to be accordingly modified since the later // scaling of the overall force shall be consistent r2inv = 1.0/(rsq + EPS_EWALD_SQR); } else { grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); u = 1.0 - t; erfc = t * (1.+u*(B0+u*(B1+u*(B2+u*(B3+u*(B4+u*B5)))))) * expm2; prefactor /= r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongCS::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { rsq += EPSILON; // Add Epsilon for case: r = 0; Interaction must be removed by special bond; r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; jtype = type[j]; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongCS::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; jtype = type[j]; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongCS::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc,u; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { rsq += EPSILON; // Add Epsilon for case: r = 0; Interaction must be removed by special bond; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); u = 1. - t; erfc = t * (1.+u*(B0+u*(B1+u*(B2+u*(B3+u*(B4+u*B5)))))) * expm2; //erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += prefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype] && rsq > cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = (forcecoul + forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { ecoul = prefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; ecoul -= (1.0-factor_coul)*prefactor; } } } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { table = vtable[itable] + fraction*dvtable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else if (rsq <= cut_in_on_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } fpair = (forcecoul + factor_lj*forcelj) * r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } diff --git a/src/KSPACE/pair_buck_long_coul_long.cpp b/src/KSPACE/pair_buck_long_coul_long.cpp index 4cfb9b726..7df8ebac6 100644 --- a/src/KSPACE/pair_buck_long_coul_long.cpp +++ b/src/KSPACE/pair_buck_long_coul_long.cpp @@ -1,1051 +1,1026 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Pieter J. in 't Veld (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "math_vector.h" #include "pair_buck_long_coul_long.h" #include "atom.h" #include "comm.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairBuckLongCoulLong::PairBuckLongCoulLong(LAMMPS *lmp) : Pair(lmp) { dispersionflag = ewaldflag = pppmflag = 1; respa_enable = 1; writedata = 1; ftable = NULL; fdisptable = NULL; } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::options(char **arg, int order) { const char *option[] = {"long", "cut", "off", NULL}; int i; if (!*arg) error->all(FLERR,"Illegal pair_style buck/long/coul/long command"); for (i=0; option[i]&&strcmp(arg[0], option[i]); ++i); switch (i) { default: error->all(FLERR,"Illegal pair_style buck/long/coul/long command"); case 0: ewald_order |= 1<all(FLERR,"Illegal pair_style command"); ewald_order = 0; ewald_off = 0; options(arg,6); options(++arg,1); if (!comm->me && ewald_order == ((1<<1) | (1<<6))) error->warning(FLERR,"Using largest cutoff for buck/long/coul/long"); if (!*(++arg)) error->all(FLERR,"Cutoffs missing in pair_style buck/long/coul/long"); if (ewald_off & (1<<6)) error->all(FLERR,"LJ6 off not supported in pair_style buck/long/coul/long"); if (!((ewald_order^ewald_off) & (1<<1))) error->all(FLERR, "Coulomb cut not supported in pair_style buck/long/coul/coul"); cut_buck_global = force->numeric(FLERR,*(arg++)); if (narg == 4 && ((ewald_order & 0x42) == 0x42)) error->all(FLERR,"Only one cutoff allowed when requesting all long"); if (narg == 4) cut_coul = force->numeric(FLERR,*arg); else cut_coul = cut_buck_global; if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut_buck[i][j] = cut_buck_global; } } /* ---------------------------------------------------------------------- free all arrays ------------------------------------------------------------------------- */ PairBuckLongCoulLong::~PairBuckLongCoulLong() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut_buck_read); memory->destroy(cut_buck); memory->destroy(cut_bucksq); memory->destroy(buck_a_read); memory->destroy(buck_a); memory->destroy(buck_c_read); memory->destroy(buck_c); memory->destroy(buck_rho_read); memory->destroy(buck_rho); memory->destroy(buck1); memory->destroy(buck2); memory->destroy(rhoinv); memory->destroy(offset); } if (ftable) free_tables(); if (fdisptable) free_disp_tables(); } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut_buck_read,n+1,n+1,"pair:cut_buck_read"); memory->create(cut_buck,n+1,n+1,"pair:cut_buck"); memory->create(cut_bucksq,n+1,n+1,"pair:cut_bucksq"); memory->create(buck_a_read,n+1,n+1,"pair:buck_a_read"); memory->create(buck_a,n+1,n+1,"pair:buck_a"); memory->create(buck_c_read,n+1,n+1,"pair:buck_c_read"); memory->create(buck_c,n+1,n+1,"pair:buck_c"); memory->create(buck_rho_read,n+1,n+1,"pair:buck_rho_read"); memory->create(buck_rho,n+1,n+1,"pair:buck_rho"); memory->create(buck1,n+1,n+1,"pair:buck1"); memory->create(buck2,n+1,n+1,"pair:buck2"); memory->create(rhoinv,n+1,n+1,"pair:rhoinv"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- extract protected data from object ------------------------------------------------------------------------- */ void *PairBuckLongCoulLong::extract(const char *id, int &dim) { const char *ids[] = { "B", "ewald_order", "ewald_cut", "ewald_mix", "cut_coul", "cut_LJ", NULL}; void *ptrs[] = { buck_c, &ewald_order, &cut_coul, &mix_flag, &cut_coul, &cut_buck_global, NULL}; int i; for (i=0; ids[i]&&strcmp(ids[i], id); ++i); if (i == 0) dim = 2; else dim = 0; return ptrs[i]; } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::coeff(int narg, char **arg) { if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,*(arg++),atom->ntypes,ilo,ihi); force->bounds(FLERR,*(arg++),atom->ntypes,jlo,jhi); double buck_a_one = force->numeric(FLERR,*(arg++)); double buck_rho_one = force->numeric(FLERR,*(arg++)); double buck_c_one = force->numeric(FLERR,*(arg++)); double cut_buck_one = cut_buck_global; if (narg == 6) cut_buck_one = force->numeric(FLERR,*(arg++)); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { buck_a_read[i][j] = buck_a_one; buck_c_read[i][j] = buck_c_one; buck_rho_read[i][j] = buck_rho_one; cut_buck_read[i][j] = cut_buck_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::init_style() { // require an atom style with charge defined if (!atom->q_flag && (ewald_order&(1<<1))) error->all(FLERR, - "Invoking coulombic in pair style buck/long/coul/long requires atom attribute q"); + "Invoking coulombic in pair style buck/long/coul/long " + "requires atom attribute q"); // ensure use of KSpace long-range solver, set two g_ewalds if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); if (ewald_order&(1<<1)) g_ewald = force->kspace->g_ewald; if (ewald_order&(1<<6)) g_ewald_6 = force->kspace->g_ewald_6; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; // setup force tables if (ncoultablebits && (ewald_order&(1<<1))) init_tables(cut_coul,cut_respa); if (ndisptablebits && (ewald_order&(1<<6))) init_tables_disp(cut_buck_global); // request regular or rRESPA neighbor lists if neighrequest_flag != 0 if (force->kspace->neighrequest_flag) { int irequest; + int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; + } - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } + irequest = neighbor->request(this,instance_me); - } else irequest = neighbor->request(this,instance_me); + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; } cut_coulsq = cut_coul * cut_coul; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairBuckLongCoulLong::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairBuckLongCoulLong::init_one(int i, int j) { if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set"); if (ewald_order&(1<<6)) cut_buck[i][j] = cut_buck_global; else cut_buck[i][j] = cut_buck_read[i][j]; buck_a[i][j] = buck_a_read[i][j]; buck_c[i][j] = buck_c_read[i][j]; buck_rho[i][j] = buck_rho_read[i][j]; double cut = MAX(cut_buck[i][j],cut_coul); cutsq[i][j] = cut*cut; cut_bucksq[i][j] = cut_buck[i][j] * cut_buck[i][j]; buck1[i][j] = buck_a[i][j]/buck_rho[i][j]; buck2[i][j] = 6.0*buck_c[i][j]; rhoinv[i][j] = 1.0/buck_rho[i][j]; // check interior rRESPA cutoff if (cut_respa && MIN(cut_buck[i][j],cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); if (offset_flag && (cut_buck[i][j] > 0.0)) { double rexp = exp(-cut_buck[i][j]/buck_rho[i][j]); offset[i][j] = buck_a[i][j]*rexp - buck_c[i][j]/pow(cut_buck[i][j],6.0); } else offset[i][j] = 0.0; cutsq[j][i] = cutsq[i][j]; cut_bucksq[j][i] = cut_bucksq[i][j]; buck_a[j][i] = buck_a[i][j]; buck_c[j][i] = buck_c[i][j]; rhoinv[j][i] = rhoinv[i][j]; buck1[j][i] = buck1[i][j]; buck2[j][i] = buck2[i][j]; offset[j][i] = offset[i][j]; return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&buck_a_read[i][j],sizeof(double),1,fp); fwrite(&buck_rho_read[i][j],sizeof(double),1,fp); fwrite(&buck_c_read[i][j],sizeof(double),1,fp); fwrite(&cut_buck_read[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&buck_a_read[i][j],sizeof(double),1,fp); fread(&buck_rho_read[i][j],sizeof(double),1,fp); fread(&buck_c_read[i][j],sizeof(double),1,fp); fread(&cut_buck_read[i][j],sizeof(double),1,fp); } MPI_Bcast(&buck_a_read[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&buck_rho_read[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&buck_c_read[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_buck_read[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::write_restart_settings(FILE *fp) { fwrite(&cut_buck_global,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&ncoultablebits,sizeof(int),1,fp); fwrite(&tabinner,sizeof(double),1,fp); fwrite(&ewald_order,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&cut_buck_global,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&ncoultablebits,sizeof(int),1,fp); fread(&tabinner,sizeof(double),1,fp); fread(&ewald_order,sizeof(int),1,fp); } MPI_Bcast(&cut_buck_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&ncoultablebits,1,MPI_INT,0,world); MPI_Bcast(&tabinner,1,MPI_DOUBLE,0,world); MPI_Bcast(&ewald_order,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g %g\n",i, buck_a_read[i][i],buck_rho_read[i][i],buck_c_read[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g\n",i,j, buck_a_read[i][j],buck_rho_read[i][j],buck_c_read[i][j]); } /* ---------------------------------------------------------------------- compute pair interactions ------------------------------------------------------------------------- */ void PairBuckLongCoulLong::compute(int eflag, int vflag) { double evdwl,ecoul,fpair; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x, *x0 = x[0]; double **f = atom->f, *f0 = f[0], *fi = f0; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6); int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni; double qi = 0.0, qri = 0.0, *cutsqi, *cut_bucksqi, *buck1i, *buck2i, *buckai, *buckci, *rhoinvi, *offseti; double r, rsq, r2inv, force_coul, force_buck; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2; vector xi, d; ineighn = (ineigh = list->ilist)+list->inum; for (; ineighfirstneigh[i])+list->numneigh[i]; for (; jneigh= cutsqi[typej = type[j]]) continue; r2inv = 1.0/rsq; r = sqrt(rsq); if (order1 && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double x = g_ewald*r; register double s = qri*q[j], t = 1.0/(1.0+EWALD_P*x); if (ni == 0) { s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s; if (eflag) ecoul = t; } else { // special case register double f = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-f; if (eflag) ecoul = t-f; } } // table real space else { register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask) >> ncoulshiftbits; register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j]; if (ni == 0) { force_coul = qiqj*(ftable[k]+f*dftable[k]); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]); } else { // special case t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]-t.f); } } } else force_coul = ecoul = 0.0; if (rsq < cut_bucksqi[typej]) { // buckingham register double rn = r2inv*r2inv*r2inv, expr = exp(-r*rhoinvi[typej]); if (order6) { // long-range if (!ndisptablebits || rsq <= tabinnerdispsq) { register double x2 = g2*rsq, a2 = 1.0/x2; x2 = a2*exp(-x2)*buckci[typej]; if (ni == 0) { force_buck = r*expr*buck1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq; if (eflag) evdwl = expr*buckai[typej]-g6*((a2+1.0)*a2+0.5)*x2; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); force_buck = f*r*expr*buck1i[typej]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*buck2i[typej]; if (eflag) evdwl = f*expr*buckai[typej] - g6*((a2+1.0)*a2+0.5)*x2+t*buckci[typej]; } } else { //table real space register union_int_float_t disp_t; disp_t.f = rsq; register const int disp_k = (disp_t.i & ndispmask)>>ndispshiftbits; register double f_disp = (rsq-rdisptable[disp_k])*drdisptable[disp_k]; if (ni == 0) { force_buck = r*expr*buck1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*buckci[typej]; if (eflag) evdwl = expr*buckai[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*buckci[typej]; } else { //speial case register double f = special_lj[ni], t = rn*(1.0-f); force_buck = f*r*expr*buck1i[typej] -(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*buckci[typej] +t*buck2i[typej]; if (eflag) evdwl = f*expr*buckai[typej] -(edisptable[disp_k]+f_disp*dedisptable[disp_k])*buckci[typej]+t*buckci[typej]; } } } else { // cut if (ni == 0) { force_buck = r*expr*buck1i[typej]-rn*buck2i[typej]; if (eflag) evdwl = expr*buckai[typej] - rn*buckci[typej]-offseti[typej]; } else { // special case register double f = special_lj[ni]; force_buck = f*(r*expr*buck1i[typej]-rn*buck2i[typej]); if (eflag) evdwl = f*(expr*buckai[typej]-rn*buckci[typej]-offseti[typej]); } } } else force_buck = evdwl = 0.0; fpair = (force_coul+force_buck)*r2inv; if (newton_pair || j < nlocal) { register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,d[0],d[1],d[2]); } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairBuckLongCoulLong::compute_inner() { double r, rsq, r2inv, force_coul = 0.0, force_buck, fpair; int *type = atom->type; int nlocal = atom->nlocal; double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni; int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1); double qri, *cut_bucksqi, *buck1i, *buck2i, *rhoinvi; vector xi, d; - ineighn = (ineigh = listinner->ilist) + listinner->inum; + ineighn = (ineigh = list->ilist_inner) + list->inum_inner; for (; ineighfirstneigh[i])+listinner->numneigh[i]; + jneighn = (jneigh = list->firstneigh_inner[i])+list->numneigh_inner[i]; for (; jneigh= cut_out_off_sq) continue; r2inv = 1.0/rsq; r = sqrt(rsq); if (order1 && (rsq < cut_coulsq)) // coulombic force_coul = ni == 0 ? qri*q[j]/r : qri*q[j]/r*special_coul[ni]; if (rsq < cut_bucksqi[typej = type[j]]) { // buckingham register double rn = r2inv*r2inv*r2inv, expr = exp(-r*rhoinvi[typej]); force_buck = ni == 0 ? (r*expr*buck1i[typej]-rn*buck2i[typej]) : (r*expr*buck1i[typej]-rn*buck2i[typej])*special_lj[ni]; } else force_buck = 0.0; fpair = (force_coul + force_buck) * r2inv; if (rsq > cut_out_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } if (newton_pair || j < nlocal) { // force update register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } } } } /* ---------------------------------------------------------------------- */ void PairBuckLongCoulLong::compute_middle() { double r, rsq, r2inv, force_coul = 0.0, force_buck, fpair; int *type = atom->type; int nlocal = atom->nlocal; double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni; int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1); double qri, *cut_bucksqi, *buck1i, *buck2i, *rhoinvi; vector xi, d; - ineighn = (ineigh = listmiddle->ilist)+listmiddle->inum; + ineighn = (ineigh = list->ilist_middle)+list->inum_middle; for (; ineighfirstneigh[i])+listmiddle->numneigh[i]; + jneighn = (jneigh = list->firstneigh_middle[i])+list->numneigh_middle[i]; for (; jneigh= cut_out_off_sq) continue; if (rsq <= cut_in_off_sq) continue; r2inv = 1.0/rsq; r = sqrt(rsq); if (order1 && (rsq < cut_coulsq)) // coulombic force_coul = ni == 0 ? qri*q[j]/r : qri*q[j]/r*special_coul[ni]; if (rsq < cut_bucksqi[typej = type[j]]) { // buckingham register double rn = r2inv*r2inv*r2inv, expr = exp(-r*rhoinvi[typej]); force_buck = ni == 0 ? (r*expr*buck1i[typej]-rn*buck2i[typej]) : (r*expr*buck1i[typej]-rn*buck2i[typej])*special_lj[ni]; } else force_buck = 0.0; fpair = (force_coul + force_buck) * r2inv; if (rsq < cut_in_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } if (newton_pair || j < nlocal) { // force update register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } } } } /* ---------------------------------------------------------------------- */ void PairBuckLongCoulLong::compute_outer(int eflag, int vflag) { double evdwl,ecoul,fpair,fvirial; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x, *x0 = x[0]; double **f = atom->f, *f0 = f[0], *fi = f0; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6); int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni, respa_flag; double qi = 0.0, qri = 0.0, *cutsqi, *cut_bucksqi, *buck1i, *buck2i, *buckai, *buckci, *rhoinvi, *offseti; double r, rsq, r2inv, force_coul, force_buck; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2; double respa_buck = 0.0, respa_coul = 0.0, frespa = 0.0; vector xi, d; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; - ineighn = (ineigh = listouter->ilist)+listouter->inum; + ineighn = (ineigh = list->ilist)+list->inum; for (; ineighfirstneigh[i])+listouter->numneigh[i]; + jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i]; for (; jneigh= cutsqi[typej = type[j]]) continue; r2inv = 1.0/rsq; r = sqrt(rsq); frespa = 1.0; //check whether and how to compute respa corrections respa_coul = 0.0; respa_buck = 0.0; respa_flag = rsq < cut_in_on_sq ? 1 : 0; if (respa_flag && (rsq > cut_in_off_sq)) { register double rsw = (r-cut_in_off)/cut_in_diff; frespa = 1-rsw*rsw*(3.0-2.0*rsw); } if (order1 && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double s = qri*q[j]; if (respa_flag) // correct for respa respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni]; register double x = g_ewald*r, t = 1.0/(1.0+EWALD_P*x); if (ni == 0) { s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-respa_coul; if (eflag) ecoul = t; } else { // correct for special register double ri = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-ri-respa_coul; if (eflag) ecoul = t-ri; } } // table real space else { if (respa_flag) { register double s = qri*q[j]; respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni]; } register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask) >> ncoulshiftbits; register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j]; if (ni == 0) { force_coul = qiqj*(ftable[k]+f*dftable[k]); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]); } else { // correct for special t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f); if (eflag) { t.f = (1.0-special_coul[ni])*(ptable[k]+f*dptable[k]); ecoul = qiqj*(etable[k]+f*detable[k]-t.f); } } } } else force_coul = respa_coul = ecoul = 0.0; if (rsq < cut_bucksqi[typej]) { // buckingham register double rn = r2inv*r2inv*r2inv, expr = exp(-r*rhoinvi[typej]); if (respa_flag) respa_buck = ni == 0 ? // correct for respa frespa*(r*expr*buck1i[typej]-rn*buck2i[typej]) : frespa*(r*expr*buck1i[typej]-rn*buck2i[typej])*special_lj[ni]; if (order6) { // long-range form if (!ndisptablebits || rsq <= tabinnerdispsq) { register double x2 = g2*rsq, a2 = 1.0/x2; x2 = a2*exp(-x2)*buckci[typej]; if (ni == 0) { force_buck = r*expr*buck1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq-respa_buck; if (eflag) evdwl = expr*buckai[typej]-g6*((a2+1.0)*a2+0.5)*x2; } else { // correct for special register double f = special_lj[ni], t = rn*(1.0-f); force_buck = f*r*expr*buck1i[typej]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*buck2i[typej]-respa_buck; if (eflag) evdwl = f*expr*buckai[typej] - g6*((a2+1.0)*a2+0.5)*x2+t*buckci[typej]; } } else { // table real space register union_int_float_t disp_t; disp_t.f = rsq; register const int disp_k = (disp_t.i & ndispmask)>>ndispshiftbits; register double f_disp = (rsq-rdisptable[disp_k])*drdisptable[disp_k]; register double rn = r2inv*r2inv*r2inv; if (ni == 0) { force_buck = r*expr*buck1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*buckci[typej]-respa_buck; if (eflag) evdwl = expr*buckai[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*buckci[typej]; } else { //special case register double f = special_lj[ni], t = rn*(1.0-f); force_buck = f*r*expr*buck1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*buckci[typej]+t*buck2i[typej]-respa_buck; if (eflag) evdwl = f*expr*buckai[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*buckci[typej]+t*buckci[typej]; } } } else { // cut form if (ni == 0) { force_buck = r*expr*buck1i[typej]-rn*buck2i[typej]-respa_buck; if (eflag) evdwl = expr*buckai[typej]-rn*buckci[typej]-offseti[typej]; } else { // correct for special register double f = special_lj[ni]; force_buck = f*(r*expr*buck1i[typej]-rn*buck2i[typej])-respa_buck; if (eflag) evdwl = f*(expr*buckai[typej]-rn*buckci[typej]-offseti[typej]); } } } else force_buck = respa_buck = evdwl = 0.0; fpair = (force_coul+force_buck)*r2inv; if (newton_pair || j < nlocal) { register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } if (evflag) { fvirial = (force_coul + force_buck + respa_coul + respa_buck)*r2inv; ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fvirial,d[0],d[1],d[2]); } } } } /* ---------------------------------------------------------------------- */ double PairBuckLongCoulLong::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_buck, double &fforce) { double f, r, r2inv, r6inv, force_coul, force_buck; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2, *q = atom->q; r = sqrt(rsq); r2inv = 1.0/rsq; double eng = 0.0; if ((ewald_order&2) && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double x = g_ewald*r; register double s = force->qqrd2e*q[i]*q[j], t = 1.0/(1.0+EWALD_P*x); f = s*(1.0-factor_coul)/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-f; eng += t-f; } else { // table real space register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask) >> ncoulshiftbits; register double f = (rsq-rtable[k])*drtable[k], qiqj = q[i]*q[j]; t.f = (1.0-factor_coul)*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f); eng += qiqj*(etable[k]+f*detable[k]-t.f); } } else force_coul = 0.0; if (rsq < cut_bucksq[itype][jtype]) { // buckingham register double expr = factor_buck*exp(-sqrt(rsq)*rhoinv[itype][jtype]); r6inv = r2inv*r2inv*r2inv; if (ewald_order&64) { // long-range register double x2 = g2*rsq, a2 = 1.0/x2, t = r6inv*(1.0-factor_buck); x2 = a2*exp(-x2)*buck_c[itype][jtype]; force_buck = buck1[itype][jtype]*r*expr- g8*(((6.0*a2+6.0)*a2+3.0)*a2+a2)*x2*rsq+t*buck2[itype][jtype]; eng += buck_a[itype][jtype]*expr- g6*((a2+1.0)*a2+0.5)*x2+t*buck_c[itype][jtype]; } else { // cut force_buck = buck1[itype][jtype]*r*expr-factor_buck*buck_c[itype][jtype]*r6inv; eng += buck_a[itype][jtype]*expr- factor_buck*(buck_c[itype][jtype]*r6inv-offset[itype][jtype]); } } else force_buck = 0.0; fforce = (force_coul+force_buck)*r2inv; return eng; } diff --git a/src/KSPACE/pair_buck_long_coul_long.h b/src/KSPACE/pair_buck_long_coul_long.h index cf752a09b..40fe7c417 100644 --- a/src/KSPACE/pair_buck_long_coul_long.h +++ b/src/KSPACE/pair_buck_long_coul_long.h @@ -1,123 +1,122 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(buck/long/coul/long,PairBuckLongCoulLong) #else #ifndef LMP_PAIR_BUCK_LONG_COUL_LONG_H #define LMP_PAIR_BUCK_LONG_COUL_LONG_H #include "pair.h" namespace LAMMPS_NS { class PairBuckLongCoulLong : public Pair { public: double cut_coul; PairBuckLongCoulLong(class LAMMPS *); ~PairBuckLongCoulLong(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); void init_style(); - void init_list(int, class NeighList *); double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); double single(int, int, int, int, double, double, double, double &); void *extract(const char *, int &); virtual void compute_inner(); virtual void compute_middle(); virtual void compute_outer(int, int); protected: double cut_buck_global; double **cut_buck, **cut_buck_read, **cut_bucksq; double cut_coulsq; double **buck_a_read, **buck_a, **buck_c_read, **buck_c; double **buck1, **buck2, **buck_rho_read, **buck_rho, **rhoinv, **offset; double *cut_respa; double g_ewald; double g_ewald_6; int ewald_order, ewald_off; void options(char **arg, int order); void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. W: Using largest cutoff for buck/long/coul/long Self-explanatory. E: Cutoffs missing in pair_style buck/long/coul/long Self-explanatory. E: LJ6 off not supported in pair_style buck/long/coul/long Self-explanatory. E: Coulomb cut not supported in pair_style buck/long/coul/coul Must use long-range Coulombic interactions. E: Only one cutoff allowed when requesting all long Self-explanatory. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair style buck/long/coul/long requires atom attribute q The atom style defined does not have this attribute. E: Pair style requires a KSpace style No kspace style is defined. E: All pair coeffs are not set All pair coefficients must be set in the data file or by the pair_coeff command before running a simulation. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/KSPACE/pair_lj_charmm_coul_long.cpp b/src/KSPACE/pair_lj_charmm_coul_long.cpp index 7b3fdd4b5..daa493cef 100644 --- a/src/KSPACE/pair_lj_charmm_coul_long.cpp +++ b/src/KSPACE/pair_lj_charmm_coul_long.cpp @@ -1,1027 +1,1001 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_charmm_coul_long.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJCharmmCoulLong::PairLJCharmmCoulLong(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; ewaldflag = pppmflag = 1; ftable = NULL; implicit = 0; mix_flag = ARITHMETIC; writedata = 1; } /* ---------------------------------------------------------------------- */ PairLJCharmmCoulLong::~PairLJCharmmCoulLong() { if (!copymode) { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(eps14); memory->destroy(sigma14); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(lj14_1); memory->destroy(lj14_2); memory->destroy(lj14_3); memory->destroy(lj14_4); memory->destroy(offset); } if (ftable) free_tables(); } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLong::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double philj,switch1,switch2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_bothsq) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (rsq < cut_ljsq) { evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; evdwl *= switch1; } evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLong::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)*cut_out_diff_inv; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLong::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double philj,switch1,switch2; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)*cut_in_diff_inv; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)*cut_out_diff_inv; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLong::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double philj,switch1,switch2; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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 < cut_bothsq) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += prefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq && rsq > cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = (forcecoul + forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { ecoul = prefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; ecoul -= (1.0-factor_coul)*prefactor; } } } else ecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; evdwl *= switch1; } evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { table = vtable[itable] + fraction*dvtable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } else if (rsq <= cut_in_on_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } fpair = (forcecoul + factor_lj*forcelj) * r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(eps14,n+1,n+1,"pair:eps14"); memory->create(sigma14,n+1,n+1,"pair:sigma14"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(lj14_1,n+1,n+1,"pair:lj14_1"); memory->create(lj14_2,n+1,n+1,"pair:lj14_2"); memory->create(lj14_3,n+1,n+1,"pair:lj14_3"); memory->create(lj14_4,n+1,n+1,"pair:lj14_4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings unlike other pair styles, there are no individual pair settings that these override ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::settings(int narg, char **arg) { if (narg != 2 && narg != 3) error->all(FLERR,"Illegal pair_style command"); cut_lj_inner = force->numeric(FLERR,arg[0]); cut_lj = force->numeric(FLERR,arg[1]); if (narg == 2) cut_coul = cut_lj; else cut_coul = force->numeric(FLERR,arg[2]); } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::coeff(int narg, char **arg) { if (narg != 4 && narg != 6) error->all(FLERR,"Illegal pair_coeff command"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double eps14_one = epsilon_one; double sigma14_one = sigma_one; if (narg == 6) { eps14_one = force->numeric(FLERR,arg[4]); sigma14_one = force->numeric(FLERR,arg[5]); } int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; eps14[i][j] = eps14_one; sigma14[i][j] = sigma14_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::init_style() { if (!atom->q_flag) error->all(FLERR, "Pair style lj/charmm/coul/long requires atom attribute q"); - // request regular or rRESPA neighbor lists + // request regular or rRESPA neighbor list int irequest; + int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; + } - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } + irequest = neighbor->request(this,instance_me); - } else irequest = neighbor->request(this,instance_me); + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; // require cut_lj_inner < cut_lj if (cut_lj_inner >= cut_lj) error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff"); cut_lj_innersq = cut_lj_inner * cut_lj_inner; cut_ljsq = cut_lj * cut_lj; cut_coulsq = cut_coul * cut_coul; cut_bothsq = MAX(cut_ljsq,cut_coulsq); denom_lj = ( (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) ); denom_lj_inv = 1.0 / denom_lj; // set & error check interior rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) { cut_respa = ((Respa *) update->integrate)->cutoff; cut_in_off = cut_respa[0]; cut_in_on = cut_respa[1]; cut_out_on = cut_respa[2]; cut_out_off = cut_respa[3]; cut_in_diff = cut_in_on - cut_in_off; cut_out_diff = cut_out_off - cut_out_on; cut_in_diff_inv = 1.0 / (cut_in_diff); cut_out_diff_inv = 1.0 / (cut_out_diff); cut_in_off_sq = cut_in_off*cut_in_off; cut_in_on_sq = cut_in_on*cut_in_on; cut_out_on_sq = cut_out_on*cut_out_on; cut_out_off_sq = cut_out_off*cut_out_off; if (MIN(cut_lj,cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); if (cut_lj_inner < cut_respa[1]) error->all(FLERR,"Pair inner cutoff < Respa interior cutoff"); } else cut_respa = NULL; // insure use of KSpace long-range solver, set g_ewald if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); g_ewald = force->kspace->g_ewald; // setup force tables if (ncoultablebits) init_tables(cut_coul,cut_respa); } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJCharmmCoulLong::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCharmmCoulLong::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); eps14[i][j] = mix_energy(eps14[i][i],eps14[j][j], sigma14[i][i],sigma14[j][j]); sigma14[i][j] = mix_distance(sigma14[i][i],sigma14[j][j]); } double cut = MAX(cut_lj,cut_coul); lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj14_1[i][j] = 48.0 * eps14[i][j] * pow(sigma14[i][j],12.0); lj14_2[i][j] = 24.0 * eps14[i][j] * pow(sigma14[i][j],6.0); lj14_3[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],12.0); lj14_4[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],6.0); lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; lj14_1[j][i] = lj14_1[i][j]; lj14_2[j][i] = lj14_2[i][j]; lj14_3[j][i] = lj14_3[i][j]; lj14_4[j][i] = lj14_4[i][j]; return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&eps14[i][j],sizeof(double),1,fp); fwrite(&sigma14[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&eps14[i][j],sizeof(double),1,fp); fread(&sigma14[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&eps14[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma14[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::write_restart_settings(FILE *fp) { fwrite(&cut_lj_inner,sizeof(double),1,fp); fwrite(&cut_lj,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&ncoultablebits,sizeof(int),1,fp); fwrite(&tabinner,sizeof(double),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&cut_lj_inner,sizeof(double),1,fp); fread(&cut_lj,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&ncoultablebits,sizeof(int),1,fp); fread(&tabinner,sizeof(double),1,fp); } MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&ncoultablebits,1,MPI_INT,0,world); MPI_Bcast(&tabinner,1,MPI_DOUBLE,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g %g %g\n", i,epsilon[i][i],sigma[i][i],eps14[i][i],sigma14[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLong::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g %g\n",i,j, epsilon[i][j],sigma[i][j],eps14[i][j],sigma14[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCharmmCoulLong::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv,r6inv,r,grij,expm2,t,erfc,prefactor; double switch1,switch2,fraction,table,forcecoul,forcelj,phicoul,philj; int itable; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = atom->q[i]*atom->q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = atom->q[i]*atom->q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; fforce = (forcecoul + factor_lj*forcelj) * r2inv; double eng = 0.0; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) phicoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; phicoul = atom->q[i]*atom->q[j] * table; } if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq) { philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; philj *= switch1; } eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCharmmCoulLong::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"lj14_1") == 0) return (void *) lj14_1; if (strcmp(str,"lj14_2") == 0) return (void *) lj14_2; if (strcmp(str,"lj14_3") == 0) return (void *) lj14_3; if (strcmp(str,"lj14_4") == 0) return (void *) lj14_4; dim = 0; if (strcmp(str,"implicit") == 0) return (void *) &implicit; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; return NULL; } diff --git a/src/KSPACE/pair_lj_charmm_coul_long.h b/src/KSPACE/pair_lj_charmm_coul_long.h index 1544f3bc1..95c6d0d1c 100644 --- a/src/KSPACE/pair_lj_charmm_coul_long.h +++ b/src/KSPACE/pair_lj_charmm_coul_long.h @@ -1,110 +1,109 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/charmm/coul/long,PairLJCharmmCoulLong) #else #ifndef LMP_PAIR_LJ_CHARMM_COUL_LONG_H #define LMP_PAIR_LJ_CHARMM_COUL_LONG_H #include "pair.h" namespace LAMMPS_NS { class PairLJCharmmCoulLong : public Pair { public: PairLJCharmmCoulLong(class LAMMPS *); virtual ~PairLJCharmmCoulLong(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); virtual void init_style(); - void init_list(int, class NeighList *); virtual double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); virtual double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); virtual void compute_outer(int, int); virtual void *extract(const char *, int &); protected: int implicit; double cut_lj_inner,cut_lj; double cut_lj_innersq,cut_ljsq; double cut_coul,cut_coulsq; double cut_bothsq; double cut_in_off, cut_in_on, cut_out_off, cut_out_on; double cut_in_diff, cut_out_diff; double cut_in_diff_inv, cut_out_diff_inv; double cut_in_off_sq, cut_in_on_sq, cut_out_off_sq, cut_out_on_sq; double denom_lj, denom_lj_inv; double **epsilon,**sigma,**eps14,**sigma14; double **lj1,**lj2,**lj3,**lj4,**offset; double **lj14_1,**lj14_2,**lj14_3,**lj14_4; double *cut_respa; double g_ewald; virtual void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair style lj/charmm/coul/long requires atom attribute q The atom style defined does not have these attributes. E: Pair inner cutoff >= Pair outer cutoff The specified cutoffs for the pair style are inconsistent. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair inner cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair style requires a KSpace style No kspace style is defined. */ diff --git a/src/KSPACE/pair_lj_charmm_coul_msm.cpp b/src/KSPACE/pair_lj_charmm_coul_msm.cpp index 76c9ef0cc..00617c0bf 100644 --- a/src/KSPACE/pair_lj_charmm_coul_msm.cpp +++ b/src/KSPACE/pair_lj_charmm_coul_msm.cpp @@ -1,551 +1,551 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing authors: Paul Crozier (SNL), Stan Moore (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_charmm_coul_msm.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ PairLJCharmmCoulMSM::PairLJCharmmCoulMSM(LAMMPS *lmp) : PairLJCharmmCoulLong(lmp) { ewaldflag = pppmflag = 0; msmflag = 1; nmax = 0; ftmp = NULL; } /* ---------------------------------------------------------------------- */ PairLJCharmmCoulMSM::~PairLJCharmmCoulMSM() { if (ftmp) memory->destroy(ftmp); } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulMSM::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair,fcoul; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double egamma,fgamma,prefactor; double philj,switch1,switch2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; int eflag_old = eflag; if (force->kspace->scalar_pressure_flag && vflag) { if (vflag > 2) error->all(FLERR,"Must use 'kspace_modify pressure/scalar no' " "to obtain per-atom virial with kspace_style MSM"); if (atom->nmax > nmax) { if (ftmp) memory->destroy(ftmp); nmax = atom->nmax; memory->create(ftmp,nmax,3,"pair:ftmp"); } memset(&ftmp[0][0],0,nmax*3*sizeof(double)); // must switch on global energy computation if not already on if (eflag == 0 || eflag == 2) { eflag++; } } evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_bothsq) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); prefactor = qqrd2e * qtmp*q[j]/r; egamma = 1.0 - (r/cut_coul)*force->kspace->gamma(r/cut_coul); fgamma = 1.0 + (rsq/cut_coulsq)*force->kspace->dgamma(r/cut_coul); forcecoul = prefactor * fgamma; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; if (!(force->kspace->scalar_pressure_flag && vflag)) { fpair = (forcecoul + factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } else { // separate LJ and Coulombic forces fpair = (factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } fcoul = (forcecoul) * r2inv; ftmp[i][0] += delx*fcoul; ftmp[i][1] += dely*fcoul; ftmp[i][2] += delz*fcoul; if (newton_pair || j < nlocal) { ftmp[j][0] -= delx*fcoul; ftmp[j][1] -= dely*fcoul; ftmp[j][2] -= delz*fcoul; } } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*egamma; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (eflag_old && rsq < cut_ljsq) { evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; evdwl *= switch1; } evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); if (force->kspace->scalar_pressure_flag && vflag) { for (i = 0; i < 3; i++) virial[i] += force->pair->eng_coul/3.0; for (int i = 0; i < nmax; i++) { f[i][0] += ftmp[i][0]; f[i][1] += ftmp[i][1]; f[i][2] += ftmp[i][2]; } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulMSM::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double egamma,fgamma,prefactor; double philj,switch1,switch2; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; if (force->kspace->scalar_pressure_flag) error->all(FLERR,"Must use 'kspace_modify pressure/scalar no' " "for rRESPA with kspace_style MSM"); evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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 < cut_bothsq) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); prefactor = qqrd2e * qtmp*q[j]/r; egamma = 1.0 - (r/cut_coul)*force->kspace->gamma(r/cut_coul); fgamma = 1.0 + (rsq/cut_coulsq)*force->kspace->dgamma(r/cut_coul); forcecoul = prefactor * (fgamma - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += prefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq && rsq > cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = (forcecoul + forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { ecoul = prefactor*egamma; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; ecoul -= (1.0-factor_coul)*prefactor; } } } else ecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; evdwl *= switch1; } evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { forcecoul = prefactor * fgamma; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { table = vtable[itable] + fraction*dvtable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } else if (rsq <= cut_in_on_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } fpair = (forcecoul + factor_lj*forcelj) * r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- */ double PairLJCharmmCoulMSM::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv,r6inv,r,egamma,fgamma,prefactor; double switch1,switch2,fraction,table,forcecoul,forcelj,phicoul,philj; int itable; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); egamma = 1.0 - (r/cut_coul)*force->kspace->gamma(r/cut_coul); fgamma = 1.0 + (rsq/cut_coulsq)*force->kspace->dgamma(r/cut_coul); prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r; forcecoul = prefactor * fgamma; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = atom->q[i]*atom->q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = atom->q[i]*atom->q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; switch2 = 12.0*rsq * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) * denom_lj_inv; philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]); forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; fforce = (forcecoul + factor_lj*forcelj) * r2inv; double eng = 0.0; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) phicoul = prefactor*egamma; else { table = etable[itable] + fraction*detable[itable]; phicoul = atom->q[i]*atom->q[j] * table; } if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq) { philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) * denom_lj_inv; philj *= switch1; } eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCharmmCoulMSM::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"lj14_1") == 0) return (void *) lj14_1; if (strcmp(str,"lj14_2") == 0) return (void *) lj14_2; if (strcmp(str,"lj14_3") == 0) return (void *) lj14_3; if (strcmp(str,"lj14_4") == 0) return (void *) lj14_4; dim = 0; if (strcmp(str,"implicit") == 0) return (void *) &implicit; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; return NULL; } diff --git a/src/KSPACE/pair_lj_charmmfsw_coul_long.cpp b/src/KSPACE/pair_lj_charmmfsw_coul_long.cpp index 30d8ab64b..859f42176 100644 --- a/src/KSPACE/pair_lj_charmmfsw_coul_long.cpp +++ b/src/KSPACE/pair_lj_charmmfsw_coul_long.cpp @@ -1,1097 +1,1084 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) The lj-fsw sections (force-switched) were provided by Robert Meissner and Lucio Colombi Ciacchi of Bremen University, Bremen, Germany, with additional assistance from Robert A. Latour, Clemson University ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_charmmfsw_coul_long.h" #include "atom.h" #include "update.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJCharmmfswCoulLong::PairLJCharmmfswCoulLong(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; ewaldflag = pppmflag = 1; ftable = NULL; implicit = 0; mix_flag = ARITHMETIC; writedata = 1; // short-range/long-range flag accessed by DihedralCharmmfsw dihedflag = 1; // switch qqr2e from LAMMPS value to CHARMM value if (strcmp(update->unit_style,"real") == 0) { if ((comm->me == 0) && (force->qqr2e != force->qqr2e_charmm_real)) error->message(FLERR,"Switching to CHARMM coulomb energy" " conversion constant"); force->qqr2e = force->qqr2e_charmm_real; } } /* ---------------------------------------------------------------------- */ PairLJCharmmfswCoulLong::~PairLJCharmmfswCoulLong() { if (!copymode) { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(eps14); memory->destroy(sigma14); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(lj14_1); memory->destroy(lj14_2); memory->destroy(lj14_3); memory->destroy(lj14_4); } if (ftable) free_tables(); } // switch qqr2e back from CHARMM value to LAMMPS value if (update && strcmp(update->unit_style,"real") == 0) { if ((comm->me == 0) && (force->qqr2e == force->qqr2e_charmm_real)) error->message(FLERR,"Restoring original LAMMPS coulomb energy" " conversion constant"); force->qqr2e = force->qqr2e_lammps_real; } } /* ---------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,evdwl12,evdwl6,ecoul,fpair; double fraction,table; double r,rinv,r2inv,r3inv,r6inv,rsq,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double switch1; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_bothsq) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; forcelj = forcelj*switch1; } } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (rsq < cut_ljsq) { if (rsq > cut_lj_innersq) { r = sqrt(rsq); rinv = 1.0/r; r3inv = rinv*rinv*rinv; evdwl12 = lj3[itype][jtype]*cut_lj6*denom_lj12 * (r6inv - cut_lj6inv)*(r6inv - cut_lj6inv); evdwl6 = -lj4[itype][jtype]*cut_lj3*denom_lj6 * (r3inv - cut_lj3inv)*(r3inv - cut_lj3inv);; evdwl = evdwl12 + evdwl6; } else { evdwl12 = r6inv*lj3[itype][jtype]*r6inv - lj3[itype][jtype]*cut_lj_inner6inv*cut_lj6inv; evdwl6 = -lj4[itype][jtype]*r6inv + lj4[itype][jtype]*cut_lj_inner3inv*cut_lj3inv; evdwl = evdwl12 + evdwl6; } evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double switch1; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; forcelj = forcelj*switch1; } fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,evdwl6,evdwl12,ecoul,fpair; double fraction,table; double r,rinv,r2inv,r3inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double switch1; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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 < cut_bothsq) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += prefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq && rsq > cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; forcelj = forcelj*switch1; } if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = (forcecoul + forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { ecoul = prefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; ecoul -= (1.0-factor_coul)*prefactor; } } } else ecoul = 0.0; if (rsq < cut_ljsq) { r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); if (rsq > cut_lj_innersq) { rinv = 1.0/r; r3inv = rinv*rinv*rinv; evdwl12 = lj3[itype][jtype]*cut_lj6*denom_lj12 * (r6inv - cut_lj6inv)*(r6inv - cut_lj6inv); evdwl6 = -lj4[itype][jtype]*cut_lj3*denom_lj6 * (r3inv - cut_lj3inv)*(r3inv - cut_lj3inv);; evdwl = evdwl12 + evdwl6; } else { evdwl12 = r6inv*lj3[itype][jtype]*r6inv - lj3[itype][jtype]*cut_lj_inner6inv*cut_lj6inv; evdwl6 = -lj4[itype][jtype]*r6inv + lj4[itype][jtype]*cut_lj_inner3inv*cut_lj3inv; evdwl = evdwl12 + evdwl6; } evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { table = vtable[itable] + fraction*dvtable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; forcelj = forcelj*switch1; } } else if (rsq <= cut_in_on_sq) { forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; forcelj = forcelj*switch1; } } fpair = (forcecoul + factor_lj*forcelj) * r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(eps14,n+1,n+1,"pair:eps14"); memory->create(sigma14,n+1,n+1,"pair:sigma14"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(lj14_1,n+1,n+1,"pair:lj14_1"); memory->create(lj14_2,n+1,n+1,"pair:lj14_2"); memory->create(lj14_3,n+1,n+1,"pair:lj14_3"); memory->create(lj14_4,n+1,n+1,"pair:lj14_4"); } /* ---------------------------------------------------------------------- global settings unlike other pair styles, there are no individual pair settings that these override ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::settings(int narg, char **arg) { if (narg != 2 && narg != 3) error->all(FLERR,"Illegal pair_style command"); cut_lj_inner = force->numeric(FLERR,arg[0]); cut_lj = force->numeric(FLERR,arg[1]); if (narg == 2) cut_coul = cut_lj; else cut_coul = force->numeric(FLERR,arg[2]); } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::coeff(int narg, char **arg) { if (narg != 4 && narg != 6) error->all(FLERR,"Illegal pair_coeff command"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double eps14_one = epsilon_one; double sigma14_one = sigma_one; if (narg == 6) { eps14_one = force->numeric(FLERR,arg[4]); sigma14_one = force->numeric(FLERR,arg[5]); } int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; eps14[i][j] = eps14_one; sigma14[i][j] = sigma14_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::init_style() { if (!atom->q_flag) error->all(FLERR, "Pair style lj/charmmfsw/coul/long requires atom attribute q"); // request regular or rRESPA neighbor lists int irequest; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; if (respa == 0) irequest = neighbor->request(this,instance_me); else if (respa == 1) { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } else { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 2; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respamiddle = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } } else irequest = neighbor->request(this,instance_me); // require cut_lj_inner < cut_lj if (cut_lj_inner >= cut_lj) error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff"); cut_lj_innersq = cut_lj_inner * cut_lj_inner; cut_ljsq = cut_lj * cut_lj; cut_ljinv = 1.0/cut_lj; cut_lj_innerinv = 1.0/cut_lj_inner; cut_lj3 = cut_lj * cut_lj * cut_lj; cut_lj3inv = cut_ljinv * cut_ljinv * cut_ljinv; cut_lj_inner3inv = cut_lj_innerinv * cut_lj_innerinv * cut_lj_innerinv; cut_lj_inner3 = cut_lj_inner * cut_lj_inner * cut_lj_inner; cut_lj6 = cut_ljsq * cut_ljsq * cut_ljsq; cut_lj6inv = cut_lj3inv * cut_lj3inv; cut_lj_inner6inv = cut_lj_inner3inv * cut_lj_inner3inv; cut_lj_inner6 = cut_lj_innersq * cut_lj_innersq * cut_lj_innersq; cut_coulsq = cut_coul * cut_coul; cut_bothsq = MAX(cut_ljsq,cut_coulsq); denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq); denom_lj12 = 1.0/(cut_lj6 - cut_lj_inner6); denom_lj6 = 1.0/(cut_lj3 - cut_lj_inner3); // set & error check interior rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) { cut_respa = ((Respa *) update->integrate)->cutoff; if (MIN(cut_lj,cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); if (cut_lj_inner < cut_respa[1]) error->all(FLERR,"Pair inner cutoff < Respa interior cutoff"); } else cut_respa = NULL; // insure use of KSpace long-range solver, set g_ewald if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); g_ewald = force->kspace->g_ewald; // setup force tables if (ncoultablebits) init_tables(cut_coul,cut_respa); } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJCharmmfswCoulLong::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCharmmfswCoulLong::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); eps14[i][j] = mix_energy(eps14[i][i],eps14[j][j], sigma14[i][i],sigma14[j][j]); sigma14[i][j] = mix_distance(sigma14[i][i],sigma14[j][j]); } double cut = MAX(cut_lj,cut_coul); lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj14_1[i][j] = 48.0 * eps14[i][j] * pow(sigma14[i][j],12.0); lj14_2[i][j] = 24.0 * eps14[i][j] * pow(sigma14[i][j],6.0); lj14_3[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],12.0); lj14_4[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],6.0); lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; lj14_1[j][i] = lj14_1[i][j]; lj14_2[j][i] = lj14_2[i][j]; lj14_3[j][i] = lj14_3[i][j]; lj14_4[j][i] = lj14_4[i][j]; return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&eps14[i][j],sizeof(double),1,fp); fwrite(&sigma14[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&eps14[i][j],sizeof(double),1,fp); fread(&sigma14[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&eps14[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma14[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::write_restart_settings(FILE *fp) { fwrite(&cut_lj_inner,sizeof(double),1,fp); fwrite(&cut_lj,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&ncoultablebits,sizeof(int),1,fp); fwrite(&tabinner,sizeof(double),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&cut_lj_inner,sizeof(double),1,fp); fread(&cut_lj,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&ncoultablebits,sizeof(int),1,fp); fread(&tabinner,sizeof(double),1,fp); } MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&ncoultablebits,1,MPI_INT,0,world); MPI_Bcast(&tabinner,1,MPI_DOUBLE,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g %g %g\n", i,epsilon[i][i],sigma[i][i],eps14[i][i],sigma14[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCharmmfswCoulLong::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g %g\n",i,j, epsilon[i][j],sigma[i][j],eps14[i][j],sigma14[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCharmmfswCoulLong::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r,rinv,r2inv,r3inv,r6inv,grij,expm2,t,erfc,prefactor; double switch1,fraction,table,forcecoul,forcelj,phicoul,philj,philj12,philj6; int itable; r = sqrt(rsq); rinv = 1.0/r; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = atom->q[i]*atom->q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = atom->q[i]*atom->q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq) { r3inv = rinv*rinv*rinv; r6inv = r3inv*r3inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; forcelj = forcelj*switch1; } } else forcelj = 0.0; fforce = (forcecoul + factor_lj*forcelj) * r2inv; double eng = 0.0; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) phicoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; phicoul = atom->q[i]*atom->q[j] * table; } if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq) { if (rsq > cut_lj_innersq) { philj12 = lj3[itype][jtype]*cut_lj6*denom_lj12 * (r6inv - cut_lj6inv)*(r6inv - cut_lj6inv); philj6 = -lj4[itype][jtype]*cut_lj3*denom_lj6 * (r3inv - cut_lj3inv)*(r3inv - cut_lj3inv);; philj = philj12 + philj6; } else { philj12 = r6inv*lj3[itype][jtype]*r6inv - lj3[itype][jtype]*cut_lj_inner6inv*cut_lj6inv; philj6 = -lj4[itype][jtype]*r6inv + lj4[itype][jtype]*cut_lj_inner3inv*cut_lj3inv; philj = philj12 + philj6; } eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCharmmfswCoulLong::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"lj14_1") == 0) return (void *) lj14_1; if (strcmp(str,"lj14_2") == 0) return (void *) lj14_2; if (strcmp(str,"lj14_3") == 0) return (void *) lj14_3; if (strcmp(str,"lj14_4") == 0) return (void *) lj14_4; dim = 0; if (strcmp(str,"implicit") == 0) return (void *) &implicit; // info extracted by dihedral_charmmfsw if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; if (strcmp(str,"cut_lj_inner") == 0) return (void *) &cut_lj_inner; if (strcmp(str,"cut_lj") == 0) return (void *) &cut_lj; if (strcmp(str,"dihedflag") == 0) return (void *) &dihedflag; return NULL; } diff --git a/src/KSPACE/pair_lj_charmmfsw_coul_long.h b/src/KSPACE/pair_lj_charmmfsw_coul_long.h index 650a908e4..135b82ea7 100644 --- a/src/KSPACE/pair_lj_charmmfsw_coul_long.h +++ b/src/KSPACE/pair_lj_charmmfsw_coul_long.h @@ -1,110 +1,109 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/charmmfsw/coul/long,PairLJCharmmfswCoulLong) #else #ifndef LMP_PAIR_LJ_CHARMMFSW_COUL_LONG_H #define LMP_PAIR_LJ_CHARMMFSW_COUL_LONG_H #include "pair.h" namespace LAMMPS_NS { class PairLJCharmmfswCoulLong : public Pair { public: PairLJCharmmfswCoulLong(class LAMMPS *); virtual ~PairLJCharmmfswCoulLong(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); virtual void init_style(); - void init_list(int, class NeighList *); virtual double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); virtual double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); virtual void compute_outer(int, int); virtual void *extract(const char *, int &); protected: int implicit; int dihedflag; double cut_lj_inner,cut_lj,cut_ljinv,cut_lj_innerinv; double cut_lj_innersq,cut_ljsq; double cut_lj3inv,cut_lj_inner3inv,cut_lj3,cut_lj_inner3; double cut_lj6inv,cut_lj_inner6inv,cut_lj6,cut_lj_inner6; double cut_coul,cut_coulsq; double cut_bothsq; double denom_lj,denom_lj12,denom_lj6; double **epsilon,**sigma,**eps14,**sigma14; double **lj1,**lj2,**lj3,**lj4,**offset; double **lj14_1,**lj14_2,**lj14_3,**lj14_4; double *cut_respa; double g_ewald; virtual void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair style lj/charmmfsw/coul/long requires atom attribute q The atom style defined does not have these attributes. E: Pair inner cutoff >= Pair outer cutoff The specified cutoffs for the pair style are inconsistent. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair inner cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair style requires a KSpace style No kspace style is defined. */ diff --git a/src/KSPACE/pair_lj_cut_coul_long.cpp b/src/KSPACE/pair_lj_cut_coul_long.cpp index f8be9fdb7..3096df2b0 100644 --- a/src/KSPACE/pair_lj_cut_coul_long.cpp +++ b/src/KSPACE/pair_lj_cut_coul_long.cpp @@ -1,978 +1,952 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_cut_coul_long.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJCutCoulLong::PairLJCutCoulLong(LAMMPS *lmp) : Pair(lmp) { ewaldflag = pppmflag = 1; respa_enable = 1; writedata = 1; ftable = NULL; qdist = 0.0; } /* ---------------------------------------------------------------------- */ PairLJCutCoulLong::~PairLJCutCoulLong() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut_lj); memory->destroy(cut_ljsq); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(offset); } if (ftable) free_tables(); } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLong::compute(int eflag, int vflag) { int i,ii,j,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLong::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; jtype = type[j]; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLong::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { r2inv = 1.0/rsq; forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; jtype = type[j]; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fpair = (forcecoul + factor_lj*forcelj) * r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLong::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += prefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype] && rsq > cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = (forcecoul + forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { ecoul = prefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; ecoul -= (1.0-factor_coul)*prefactor; } } } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { table = vtable[itable] + fraction*dvtable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else if (rsq <= cut_in_on_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } fpair = (forcecoul + factor_lj*forcelj) * r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCutCoulLong::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut_lj,n+1,n+1,"pair:cut_lj"); memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJCutCoulLong::settings(int narg, char **arg) { if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command"); cut_lj_global = force->numeric(FLERR,arg[0]); if (narg == 1) cut_coul = cut_lj_global; else cut_coul = force->numeric(FLERR,arg[1]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut_lj[i][j] = cut_lj_global; } } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCutCoulLong::coeff(int narg, char **arg) { if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double cut_lj_one = cut_lj_global; if (narg == 5) cut_lj_one = force->numeric(FLERR,arg[4]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; cut_lj[i][j] = cut_lj_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCutCoulLong::init_style() { if (!atom->q_flag) error->all(FLERR,"Pair style lj/cut/coul/long requires atom attribute q"); - // request regular or rRESPA neighbor lists + // request regular or rRESPA neighbor list int irequest; + int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; + } - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } + irequest = neighbor->request(this,instance_me); - } else irequest = neighbor->request(this,instance_me); + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; cut_coulsq = cut_coul * cut_coul; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; // insure use of KSpace long-range solver, set g_ewald if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); g_ewald = force->kspace->g_ewald; // setup force tables if (ncoultablebits) init_tables(cut_coul,cut_respa); } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJCutCoulLong::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCutCoulLong::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]); } // include TIP4P qdist in full cutoff, qdist = 0.0 if not TIP4P double cut = MAX(cut_lj[i][j],cut_coul+2.0*qdist); cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j]; lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0); if (offset_flag && (cut_lj[i][j] > 0.0)) { double ratio = sigma[i][j] / cut_lj[i][j]; offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0)); } else offset[i][j] = 0.0; cut_ljsq[j][i] = cut_ljsq[i][j]; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; offset[j][i] = offset[i][j]; // check interior rRESPA cutoff if (cut_respa && MIN(cut_lj[i][j],cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); // compute I,J contribution to long-range tail correction // count total # of atoms of type I and J via Allreduce if (tail_flag) { int *type = atom->type; int nlocal = atom->nlocal; double count[2],all[2]; count[0] = count[1] = 0.0; for (int k = 0; k < nlocal; k++) { if (type[k] == i) count[0] += 1.0; if (type[k] == j) count[1] += 1.0; } MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world); double sig2 = sigma[i][j]*sigma[i][j]; double sig6 = sig2*sig2*sig2; double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j]; double rc6 = rc3*rc3; double rc9 = rc3*rc6; etail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] * sig6 * (sig6 - 3.0*rc6) / (9.0*rc9); ptail_ij = 16.0*MY_PI*all[0]*all[1]*epsilon[i][j] * sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9); } return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCutCoulLong::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&cut_lj[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCutCoulLong::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&cut_lj[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCutCoulLong::write_restart_settings(FILE *fp) { fwrite(&cut_lj_global,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&tail_flag,sizeof(int),1,fp); fwrite(&ncoultablebits,sizeof(int),1,fp); fwrite(&tabinner,sizeof(double),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCutCoulLong::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&cut_lj_global,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&tail_flag,sizeof(int),1,fp); fread(&ncoultablebits,sizeof(int),1,fp); fread(&tabinner,sizeof(double),1,fp); } MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&tail_flag,1,MPI_INT,0,world); MPI_Bcast(&ncoultablebits,1,MPI_INT,0,world); MPI_Bcast(&tabinner,1,MPI_DOUBLE,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCutCoulLong::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g\n",i,epsilon[i][i],sigma[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCutCoulLong::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g\n",i,j,epsilon[i][j],sigma[i][j],cut_lj[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCutCoulLong::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv,r6inv,r,grij,expm2,t,erfc,prefactor; double fraction,table,forcecoul,forcelj,phicoul,philj; int itable; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup_single; rsq_lookup_single.f = rsq; itable = rsq_lookup_single.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup_single.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = atom->q[i]*atom->q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = atom->q[i]*atom->q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fforce = (forcecoul + factor_lj*forcelj) * r2inv; double eng = 0.0; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) phicoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; phicoul = atom->q[i]*atom->q[j] * table; } if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq[itype][jtype]) { philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCutCoulLong::extract(const char *str, int &dim) { dim = 0; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; dim = 2; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; return NULL; } diff --git a/src/KSPACE/pair_lj_cut_coul_long.h b/src/KSPACE/pair_lj_cut_coul_long.h index 886542d07..e6f97c088 100644 --- a/src/KSPACE/pair_lj_cut_coul_long.h +++ b/src/KSPACE/pair_lj_cut_coul_long.h @@ -1,94 +1,93 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/cut/coul/long,PairLJCutCoulLong) #else #ifndef LMP_PAIR_LJ_CUT_COUL_LONG_H #define LMP_PAIR_LJ_CUT_COUL_LONG_H #include "pair.h" namespace LAMMPS_NS { class PairLJCutCoulLong : public Pair { public: PairLJCutCoulLong(class LAMMPS *); virtual ~PairLJCutCoulLong(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); virtual void init_style(); - void init_list(int, class NeighList *); virtual double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); virtual void write_restart_settings(FILE *); virtual void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); virtual double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); virtual void compute_outer(int, int); virtual void *extract(const char *, int &); protected: double cut_lj_global; double **cut_lj,**cut_ljsq; double cut_coul,cut_coulsq; double **epsilon,**sigma; double **lj1,**lj2,**lj3,**lj4,**offset; double *cut_respa; double qdist; // TIP4P distance from O site to negative charge double g_ewald; virtual void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair style lj/cut/coul/long requires atom attribute q The atom style defined does not have this attribute. E: Pair style requires a KSpace style No kspace style is defined. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/KSPACE/pair_lj_cut_coul_msm.cpp b/src/KSPACE/pair_lj_cut_coul_msm.cpp index e3b3f58fc..9f901db9f 100644 --- a/src/KSPACE/pair_lj_cut_coul_msm.cpp +++ b/src/KSPACE/pair_lj_cut_coul_msm.cpp @@ -1,494 +1,494 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing authors: Stan Moore (SNL), Paul Crozier (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_cut_coul_msm.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; /* ---------------------------------------------------------------------- */ PairLJCutCoulMSM::PairLJCutCoulMSM(LAMMPS *lmp) : PairLJCutCoulLong(lmp) { ewaldflag = pppmflag = 0; msmflag = 1; nmax = 0; ftmp = NULL; } /* ---------------------------------------------------------------------- */ PairLJCutCoulMSM::~PairLJCutCoulMSM() { if (ftmp) memory->destroy(ftmp); } /* ---------------------------------------------------------------------- */ void PairLJCutCoulMSM::compute(int eflag, int vflag) { int i,ii,j,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair,fcoul; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double egamma,fgamma,prefactor; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; int eflag_old = eflag; if (force->kspace->scalar_pressure_flag && vflag) { if (vflag > 2) error->all(FLERR,"Must use 'kspace_modify pressure/scalar no' " "to obtain per-atom virial with kspace_style MSM"); if (atom->nmax > nmax) { if (ftmp) memory->destroy(ftmp); nmax = atom->nmax; memory->create(ftmp,nmax,3,"pair:ftmp"); } memset(&ftmp[0][0],0,nmax*3*sizeof(double)); // must switch on global energy computation if not already on if (eflag == 0 || eflag == 2) { eflag++; } } evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); prefactor = qqrd2e * qtmp*q[j]/r; egamma = 1.0 - (r/cut_coul)*force->kspace->gamma(r/cut_coul); fgamma = 1.0 + (rsq/cut_coulsq)*force->kspace->dgamma(r/cut_coul); forcecoul = prefactor * fgamma; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; if (!(force->kspace->scalar_pressure_flag && vflag)) { fpair = (forcecoul + factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } else { // separate LJ and Coulombic forces fpair = (factor_lj*forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } fcoul = (forcecoul) * r2inv; ftmp[i][0] += delx*fcoul; ftmp[i][1] += dely*fcoul; ftmp[i][2] += delz*fcoul; if (newton_pair || j < nlocal) { ftmp[j][0] -= delx*fcoul; ftmp[j][1] -= dely*fcoul; ftmp[j][2] -= delz*fcoul; } } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*egamma; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (eflag_old && rsq < cut_ljsq[itype][jtype]) { evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); if (force->kspace->scalar_pressure_flag && vflag) { for (i = 0; i < 3; i++) virial[i] += force->pair->eng_coul/3.0; for (int i = 0; i < nmax; i++) { f[i][0] += ftmp[i][0]; f[i][1] += ftmp[i][1]; f[i][2] += ftmp[i][2]; } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulMSM::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double fraction,table; double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj; double egamma,fgamma,prefactor; double rsw; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; if (force->kspace->scalar_pressure_flag) error->all(FLERR,"Must use 'kspace_modify pressure/scalar no' " "for rRESPA with kspace_style MSM"); evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); prefactor = qqrd2e * qtmp*q[j]/r; egamma = 1.0 - (r/cut_coul)*force->kspace->gamma(r/cut_coul); fgamma = 1.0 + (rsq/cut_coulsq)*force->kspace->dgamma(r/cut_coul); forcecoul = prefactor * (fgamma - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += prefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype] && rsq > cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = (forcecoul + forcelj) * r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { ecoul = prefactor*egamma; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; ecoul -= (1.0-factor_coul)*prefactor; } } } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { forcecoul = prefactor * fgamma; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { table = vtable[itable] + fraction*dvtable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ptable[itable] + fraction*dptable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else if (rsq <= cut_in_on_sq) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } fpair = (forcecoul + factor_lj*forcelj) * r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- */ double PairLJCutCoulMSM::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv,r6inv,r,egamma,fgamma,prefactor; double fraction,table,forcecoul,forcelj,phicoul,philj; int itable; r2inv = 1.0/rsq; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r; egamma = 1.0 - (r/cut_coul)*force->kspace->gamma(r/cut_coul); fgamma = 1.0 + (rsq/cut_coulsq)*force->kspace->dgamma(r/cut_coul); forcecoul = prefactor * fgamma; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else { union_int_float_t rsq_lookup_single; rsq_lookup_single.f = rsq; itable = rsq_lookup_single.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup_single.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = atom->q[i]*atom->q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = atom->q[i]*atom->q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; fforce = (forcecoul + factor_lj*forcelj) * r2inv; double eng = 0.0; if (rsq < cut_coulsq) { if (!ncoultablebits || rsq <= tabinnersq) phicoul = prefactor*egamma; else { table = etable[itable] + fraction*detable[itable]; phicoul = atom->q[i]*atom->q[j] * table; } if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq[itype][jtype]) { philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCutCoulMSM::extract(const char *str, int &dim) { dim = 0; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; dim = 2; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; return NULL; } diff --git a/src/KSPACE/pair_lj_long_coul_long.cpp b/src/KSPACE/pair_lj_long_coul_long.cpp index 7c6adfcb4..61b69011f 100644 --- a/src/KSPACE/pair_lj_long_coul_long.cpp +++ b/src/KSPACE/pair_lj_long_coul_long.cpp @@ -1,1039 +1,1013 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Pieter J. in 't Veld (SNL) Tabulation for long-range dispersion added by Wayne Mitchell (Loyola University New Orleans) ------------------------------------------------------------------------- */ #include #include #include #include #include "math_vector.h" #include "pair_lj_long_coul_long.h" #include "atom.h" #include "comm.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJLongCoulLong::PairLJLongCoulLong(LAMMPS *lmp) : Pair(lmp) { dispersionflag = ewaldflag = pppmflag = 1; respa_enable = 1; writedata = 1; ftable = NULL; fdisptable = NULL; qdist = 0.0; } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJLongCoulLong::options(char **arg, int order) { const char *option[] = {"long", "cut", "off", NULL}; int i; if (!*arg) error->all(FLERR,"Illegal pair_style lj/long/coul/long command"); for (i=0; option[i]&&strcmp(arg[0], option[i]); ++i); switch (i) { default: error->all(FLERR,"Illegal pair_style lj/long/coul/long command"); case 0: ewald_order |= 1<all(FLERR,"Illegal pair_style command"); ewald_order = 0; ewald_off = 0; options(arg,6); options(++arg,1); if (!comm->me && ewald_order == ((1<<1) | (1<<6))) error->warning(FLERR,"Using largest cutoff for lj/long/coul/long"); if (!*(++arg)) error->all(FLERR,"Cutoffs missing in pair_style lj/long/coul/long"); if (!((ewald_order^ewald_off) & (1<<1))) error->all(FLERR, "Coulomb cut not supported in pair_style lj/long/coul/long"); cut_lj_global = force->numeric(FLERR,*(arg++)); if (narg == 4 && ((ewald_order & 0x42) == 0x42)) error->all(FLERR,"Only one cutoff allowed when requesting all long"); if (narg == 4) cut_coul = force->numeric(FLERR,*arg); else cut_coul = cut_lj_global; if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut_lj[i][j] = cut_lj_global; } } /* ---------------------------------------------------------------------- free all arrays ------------------------------------------------------------------------- */ PairLJLongCoulLong::~PairLJLongCoulLong() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut_lj_read); memory->destroy(cut_lj); memory->destroy(cut_ljsq); memory->destroy(epsilon_read); memory->destroy(epsilon); memory->destroy(sigma_read); memory->destroy(sigma); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(offset); } if (ftable) free_tables(); if (fdisptable) free_disp_tables(); } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJLongCoulLong::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut_lj_read,n+1,n+1,"pair:cut_lj_read"); memory->create(cut_lj,n+1,n+1,"pair:cut_lj"); memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq"); memory->create(epsilon_read,n+1,n+1,"pair:epsilon_read"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma_read,n+1,n+1,"pair:sigma_read"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- extract protected data from object ------------------------------------------------------------------------- */ void *PairLJLongCoulLong::extract(const char *id, int &dim) { const char *ids[] = { "B", "sigma", "epsilon", "ewald_order", "ewald_cut", "ewald_mix", "cut_coul", "cut_LJ", NULL}; void *ptrs[] = { lj4, sigma, epsilon, &ewald_order, &cut_coul, &mix_flag, &cut_coul, &cut_lj_global, NULL}; int i; for (i=0; ids[i]&&strcmp(ids[i], id); ++i); if (i <= 2) dim = 2; else dim = 0; return ptrs[i]; } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJLongCoulLong::coeff(int narg, char **arg) { if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double cut_lj_one = cut_lj_global; if (narg == 5) cut_lj_one = force->numeric(FLERR,arg[4]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon_read[i][j] = epsilon_one; sigma_read[i][j] = sigma_one; cut_lj_read[i][j] = cut_lj_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJLongCoulLong::init_style() { // require an atom style with charge defined if (!atom->q_flag && (ewald_order&(1<<1))) error->all(FLERR, "Invoking coulombic in pair style lj/long/coul/long requires atom attribute q"); // ensure use of KSpace long-range solver, set two g_ewalds if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); if (ewald_order&(1<<1)) g_ewald = force->kspace->g_ewald; if (ewald_order&(1<<6)) g_ewald_6 = force->kspace->g_ewald_6; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; // setup force tables if (ncoultablebits && (ewald_order&(1<<1))) init_tables(cut_coul,cut_respa); if (ndisptablebits && (ewald_order&(1<<6))) init_tables_disp(cut_lj_global); // request regular or rRESPA neighbor lists if neighrequest_flag != 0 if (force->kspace->neighrequest_flag) { int irequest; - + int respa = 0; + if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; - - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } - - } else irequest = neighbor->request(this,instance_me); + } + + irequest = neighbor->request(this,instance_me); + + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; } cut_coulsq = cut_coul * cut_coul; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJLongCoulLong::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJLongCoulLong::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon_read[i][i],epsilon_read[j][j], sigma_read[i][i],sigma_read[j][j]); sigma[i][j] = mix_distance(sigma_read[i][i],sigma_read[j][j]); if (ewald_order&(1<<6)) cut_lj[i][j] = cut_lj_global; else cut_lj[i][j] = mix_distance(cut_lj_read[i][i],cut_lj_read[j][j]); } else { sigma[i][j] = sigma_read[i][j]; epsilon[i][j] = epsilon_read[i][j]; cut_lj[i][j] = cut_lj_read[i][j]; } double cut = MAX(cut_lj[i][j], cut_coul + 2.0*qdist); cutsq[i][j] = cut*cut; cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j]; lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0); // check interior rRESPA cutoff if (cut_respa && MIN(cut_lj[i][j],cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); if (offset_flag && (cut_lj[i][j] > 0.0)) { double ratio = sigma[i][j] / cut_lj[i][j]; offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0)); } else offset[i][j] = 0.0; cutsq[j][i] = cutsq[i][j]; cut_ljsq[j][i] = cut_ljsq[i][j]; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; offset[j][i] = offset[i][j]; return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJLongCoulLong::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon_read[i][j],sizeof(double),1,fp); fwrite(&sigma_read[i][j],sizeof(double),1,fp); fwrite(&cut_lj_read[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJLongCoulLong::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon_read[i][j],sizeof(double),1,fp); fread(&sigma_read[i][j],sizeof(double),1,fp); fread(&cut_lj_read[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon_read[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma_read[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj_read[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJLongCoulLong::write_restart_settings(FILE *fp) { fwrite(&cut_lj_global,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&ncoultablebits,sizeof(int),1,fp); fwrite(&tabinner,sizeof(double),1,fp); fwrite(&ewald_order,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJLongCoulLong::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&cut_lj_global,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&ncoultablebits,sizeof(int),1,fp); fread(&tabinner,sizeof(double),1,fp); fread(&ewald_order,sizeof(int),1,fp); } MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&ncoultablebits,1,MPI_INT,0,world); MPI_Bcast(&tabinner,1,MPI_DOUBLE,0,world); MPI_Bcast(&ewald_order,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJLongCoulLong::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g\n",i,epsilon_read[i][i],sigma_read[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJLongCoulLong::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g\n",i,j, epsilon_read[i][j],sigma_read[i][j],cut_lj_read[i][j]); } /* ---------------------------------------------------------------------- compute pair interactions ------------------------------------------------------------------------- */ void PairLJLongCoulLong::compute(int eflag, int vflag) { double evdwl,ecoul,fpair; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x, *x0 = x[0]; double **f = atom->f, *f0 = f[0], *fi = f0; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6); int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni; double qi = 0.0, qri = 0.0; double *cutsqi, *cut_ljsqi, *lj1i, *lj2i, *lj3i, *lj4i, *offseti; double rsq, r2inv, force_coul, force_lj; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2; vector xi, d; ineighn = (ineigh = list->ilist)+list->inum; for (; ineighfirstneigh[i])+list->numneigh[i]; for (; jneigh= cutsqi[typej = type[j]]) continue; r2inv = 1.0/rsq; if (order1 && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double r = sqrt(rsq), x = g_ewald*r; register double s = qri*q[j], t = 1.0/(1.0+EWALD_P*x); if (ni == 0) { s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s; if (eflag) ecoul = t; } else { // special case r = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r; if (eflag) ecoul = t-r; } } // table real space else { register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask)>>ncoulshiftbits; register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j]; if (ni == 0) { force_coul = qiqj*(ftable[k]+f*dftable[k]); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]); } else { // special case t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]-t.f); } } } else force_coul = ecoul = 0.0; if (rsq < cut_ljsqi[typej]) { // lj if (order6) { // long-range lj if(!ndisptablebits || rsq <= tabinnerdispsq) { // series real space register double rn = r2inv*r2inv*r2inv; register double x2 = g2*rsq, a2 = 1.0/x2; x2 = a2*exp(-x2)*lj4i[typej]; if (ni == 0) { force_lj = (rn*=rn)*lj1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq; if (eflag) evdwl = rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); force_lj = f*(rn *= rn)*lj1i[typej]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*lj2i[typej]; if (eflag) evdwl = f*rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2+t*lj4i[typej]; } } else { // table real space register union_int_float_t disp_t; disp_t.f = rsq; register const int disp_k = (disp_t.i & ndispmask)>>ndispshiftbits; register double f_disp = (rsq-rdisptable[disp_k])*drdisptable[disp_k]; register double rn = r2inv*r2inv*r2inv; if (ni == 0) { force_lj = (rn*=rn)*lj1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[typej]; if (eflag) evdwl = rn*lj3i[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[typej]; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); force_lj = f*(rn *= rn)*lj1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[typej]+t*lj2i[typej]; if (eflag) evdwl = f*rn*lj3i[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[typej]+t*lj4i[typej]; } } } else { // cut lj register double rn = r2inv*r2inv*r2inv; if (ni == 0) { force_lj = rn*(rn*lj1i[typej]-lj2i[typej]); if (eflag) evdwl = rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej]; } else { // special case register double f = special_lj[ni]; force_lj = f*rn*(rn*lj1i[typej]-lj2i[typej]); if (eflag) evdwl = f * (rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej]); } } } else force_lj = evdwl = 0.0; fpair = (force_coul+force_lj)*r2inv; if (newton_pair || j < nlocal) { register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,d[0],d[1],d[2]); } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJLongCoulLong::compute_inner() { double rsq, r2inv, force_coul = 0.0, force_lj, fpair; int *type = atom->type; int nlocal = atom->nlocal; double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni; int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1); double qri, *cut_ljsqi, *lj1i, *lj2i; vector xi, d; - ineighn = (ineigh = listinner->ilist)+listinner->inum; + ineighn = (ineigh = list->ilist_inner)+list->inum_inner; for (; ineighfirstneigh[i])+listinner->numneigh[i]; + jneighn = (jneigh = list->firstneigh_inner[i])+list->numneigh_inner[i]; for (; jneigh= cut_out_off_sq) continue; r2inv = 1.0/rsq; if (order1 && (rsq < cut_coulsq)) { // coulombic qri = qqrd2e*q[i]; force_coul = ni == 0 ? qri*q[j]*sqrt(r2inv) : qri*q[j]*sqrt(r2inv)*special_coul[ni]; } if (rsq < cut_ljsqi[typej = type[j]]) { // lennard-jones register double rn = r2inv*r2inv*r2inv; force_lj = ni == 0 ? rn*(rn*lj1i[typej]-lj2i[typej]) : rn*(rn*lj1i[typej]-lj2i[typej])*special_lj[ni]; } else force_lj = 0.0; fpair = (force_coul + force_lj) * r2inv; if (rsq > cut_out_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } if (newton_pair || j < nlocal) { // force update register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } } } } /* ---------------------------------------------------------------------- */ void PairLJLongCoulLong::compute_middle() { double rsq, r2inv, force_coul = 0.0, force_lj, fpair; int *type = atom->type; int nlocal = atom->nlocal; double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni; int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1); double qri, *cut_ljsqi, *lj1i, *lj2i; vector xi, d; - ineighn = (ineigh = listmiddle->ilist)+listmiddle->inum; + ineighn = (ineigh = list->ilist_middle)+list->inum_middle; for (; ineighfirstneigh[i])+listmiddle->numneigh[i]; + jneighn = (jneigh = list->firstneigh_middle[i])+list->numneigh_middle[i]; for (; jneigh= cut_out_off_sq) continue; if (rsq <= cut_in_off_sq) continue; r2inv = 1.0/rsq; if (order1 && (rsq < cut_coulsq)) // coulombic force_coul = ni == 0 ? qri*q[j]*sqrt(r2inv) : qri*q[j]*sqrt(r2inv)*special_coul[ni]; if (rsq < cut_ljsqi[typej = type[j]]) { // lennard-jones register double rn = r2inv*r2inv*r2inv; force_lj = ni == 0 ? rn*(rn*lj1i[typej]-lj2i[typej]) : rn*(rn*lj1i[typej]-lj2i[typej])*special_lj[ni]; } else force_lj = 0.0; fpair = (force_coul + force_lj) * r2inv; if (rsq < cut_in_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } if (newton_pair || j < nlocal) { // force update register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } } } } /* ---------------------------------------------------------------------- */ void PairLJLongCoulLong::compute_outer(int eflag, int vflag) { double evdwl,ecoul,fvirial,fpair; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x, *x0 = x[0]; double **f = atom->f, *f0 = f[0], *fi = f0; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6); int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni, respa_flag; double qi = 0.0, qri = 0.0; double *cutsqi, *cut_ljsqi, *lj1i, *lj2i, *lj3i, *lj4i, *offseti; double rsq, r2inv, force_coul, force_lj; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2; double respa_lj = 0.0, respa_coul = 0.0, frespa = 0.0; vector xi, d; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; - ineighn = (ineigh = listouter->ilist)+listouter->inum; + ineighn = (ineigh = list->ilist)+list->inum; for (; ineighfirstneigh[i])+listouter->numneigh[i]; + jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i]; for (; jneigh= cutsqi[typej = type[j]]) continue; r2inv = 1.0/rsq; frespa = 1.0; // check whether and how to compute respa corrections respa_coul = 0; respa_lj = 0; respa_flag = rsq < cut_in_on_sq ? 1 : 0; if (respa_flag && (rsq > cut_in_off_sq)) { register double rsw = (sqrt(rsq)-cut_in_off)/cut_in_diff; frespa = 1-rsw*rsw*(3.0-2.0*rsw); } if (order1 && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double r = sqrt(rsq), s = qri*q[j]; if (respa_flag) // correct for respa respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni]; register double x = g_ewald*r, t = 1.0/(1.0+EWALD_P*x); if (ni == 0) { s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-respa_coul; if (eflag) ecoul = t; } else { // correct for special r = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r-respa_coul; if (eflag) ecoul = t-r; } } // table real space else { if (respa_flag) { register double r = sqrt(rsq), s = qri*q[j]; respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni]; } register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask) >> ncoulshiftbits; register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j]; if (ni == 0) { force_coul = qiqj*(ftable[k]+f*dftable[k]); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]); } else { // correct for special t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f); if (eflag) { t.f = (1.0-special_coul[ni])*(ptable[k]+f*dptable[k]); ecoul = qiqj*(etable[k]+f*detable[k]-t.f); } } } } else force_coul = respa_coul = ecoul = 0.0; if (rsq < cut_ljsqi[typej]) { // lennard-jones register double rn = r2inv*r2inv*r2inv; if (respa_flag) respa_lj = ni == 0 ? // correct for respa frespa*rn*(rn*lj1i[typej]-lj2i[typej]) : frespa*rn*(rn*lj1i[typej]-lj2i[typej])*special_lj[ni]; if (order6) { // long-range form if (!ndisptablebits || rsq <= tabinnerdispsq) { register double x2 = g2*rsq, a2 = 1.0/x2; x2 = a2*exp(-x2)*lj4i[typej]; if (ni == 0) { force_lj = (rn*=rn)*lj1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq-respa_lj; if (eflag) evdwl = rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2; } else { // correct for special register double f = special_lj[ni], t = rn*(1.0-f); force_lj = f*(rn *= rn)*lj1i[typej]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*lj2i[typej]-respa_lj; if (eflag) evdwl = f*rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2+t*lj4i[typej]; } } else { // table real space register union_int_float_t disp_t; disp_t.f = rsq; register const int disp_k = (disp_t.i & ndispmask)>>ndispshiftbits; register double f_disp = (rsq-rdisptable[disp_k])*drdisptable[disp_k]; register double rn = r2inv*r2inv*r2inv; if (ni == 0) { force_lj = (rn*=rn)*lj1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[typej]-respa_lj; if (eflag) evdwl = rn*lj3i[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[typej]; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); force_lj = f*(rn *= rn)*lj1i[typej]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[typej]+t*lj2i[typej]-respa_lj; if (eflag) evdwl = f*rn*lj3i[typej]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[typej]+t*lj4i[typej]; } } } else { // cut form if (ni == 0) { force_lj = rn*(rn*lj1i[typej]-lj2i[typej])-respa_lj; if (eflag) evdwl = rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej]; } else { // correct for special register double f = special_lj[ni]; force_lj = f*rn*(rn*lj1i[typej]-lj2i[typej])-respa_lj; if (eflag) evdwl = f*(rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej]); } } } else force_lj = respa_lj = evdwl = 0.0; fpair = (force_coul+force_lj)*r2inv; if (newton_pair || j < nlocal) { register double *fj = f0+(j+(j<<1)), f; fi[0] += f = d[0]*fpair; fj[0] -= f; fi[1] += f = d[1]*fpair; fj[1] -= f; fi[2] += f = d[2]*fpair; fj[2] -= f; } else { fi[0] += d[0]*fpair; fi[1] += d[1]*fpair; fi[2] += d[2]*fpair; } if (evflag) { fvirial = (force_coul + force_lj + respa_coul + respa_lj)*r2inv; ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fvirial,d[0],d[1],d[2]); } } } } /* ---------------------------------------------------------------------- */ double PairLJLongCoulLong::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv, r6inv, force_coul, force_lj; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2, *q = atom->q; double eng = 0.0; r2inv = 1.0/rsq; if ((ewald_order&2) && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double r = sqrt(rsq), x = g_ewald*r; register double s = force->qqrd2e*q[i]*q[j], t = 1.0/(1.0+EWALD_P*x); r = s*(1.0-factor_coul)/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r; eng += t-r; } else { // table real space register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask) >> ncoulshiftbits; register double f = (rsq-rtable[k])*drtable[k], qiqj = q[i]*q[j]; t.f = (1.0-factor_coul)*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f); eng += qiqj*(etable[k]+f*detable[k]-t.f); } } else force_coul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { // lennard-jones r6inv = r2inv*r2inv*r2inv; if (ewald_order&64) { // long-range register double x2 = g2*rsq, a2 = 1.0/x2, t = r6inv*(1.0-factor_lj); x2 = a2*exp(-x2)*lj4[itype][jtype]; force_lj = factor_lj*(r6inv *= r6inv)*lj1[itype][jtype]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+a2)*x2*rsq+t*lj2[itype][jtype]; eng += factor_lj*r6inv*lj3[itype][jtype]- g6*((a2+1.0)*a2+0.5)*x2+t*lj4[itype][jtype]; } else { // cut force_lj = factor_lj*r6inv*(lj1[itype][jtype]*r6inv-lj2[itype][jtype]); eng += factor_lj*(r6inv*(r6inv*lj3[itype][jtype]- lj4[itype][jtype])-offset[itype][jtype]); } } else force_lj = 0.0; fforce = (force_coul+force_lj)*r2inv; return eng; } diff --git a/src/KSPACE/pair_lj_long_coul_long.h b/src/KSPACE/pair_lj_long_coul_long.h index 22704c79f..f11c81e28 100644 --- a/src/KSPACE/pair_lj_long_coul_long.h +++ b/src/KSPACE/pair_lj_long_coul_long.h @@ -1,114 +1,113 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/long/coul/long,PairLJLongCoulLong) #else #ifndef LMP_PAIR_LJ_LONG_COUL_LONG_H #define LMP_PAIR_LJ_LONG_COUL_LONG_H #include "pair.h" namespace LAMMPS_NS { class PairLJLongCoulLong : public Pair { public: double cut_coul; PairLJLongCoulLong(class LAMMPS *); virtual ~PairLJLongCoulLong(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); void init_style(); - void init_list(int, class NeighList *); double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); double single(int, int, int, int, double, double, double, double &); void *extract(const char *, int &); virtual void compute_inner(); virtual void compute_middle(); virtual void compute_outer(int, int); protected: double cut_lj_global; double **cut_lj, **cut_lj_read, **cut_ljsq; double cut_coulsq; double **epsilon_read, **epsilon, **sigma_read, **sigma; double **lj1, **lj2, **lj3, **lj4, **offset; double *cut_respa; double qdist; double g_ewald; double g_ewald_6; int ewald_order, ewald_off; void options(char **arg, int order); void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. W: Using largest cutoff for lj/long/coul/long Self-explanatory. E: Cutoffs missing in pair_style lj/long/coul/long Self-explanatory. E: Coulomb cut not supported in pair_style lj/long/coul/long Must use long-range Coulombic interactions. E: Only one cutoff allowed when requesting all long Self-explanatory. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Invoking coulombic in pair style lj/coul requires atom attribute q The atom style defined does not have this attribute. E: Pair style requires a KSpace style No kspace style is defined. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/KSPACE/pair_lj_long_tip4p_long.cpp b/src/KSPACE/pair_lj_long_tip4p_long.cpp index 1dc1ca1cb..1b0eb12e2 100644 --- a/src/KSPACE/pair_lj_long_tip4p_long.cpp +++ b/src/KSPACE/pair_lj_long_tip4p_long.cpp @@ -1,1641 +1,1641 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing authors: Amalie Frischknecht and Ahmed Ismail (SNL) Rolf Isele-Holder (Aachen University) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_long_tip4p_long.h" #include "angle.h" #include "atom.h" #include "bond.h" #include "comm.h" #include "domain.h" #include "force.h" #include "kspace.h" #include "update.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJLongTIP4PLong::PairLJLongTIP4PLong(LAMMPS *lmp) : PairLJLongCoulLong(lmp) { dispersionflag = tip4pflag = 1; single_enable = 0; respa_enable = 1; nmax = 0; hneigh = NULL; newsite = NULL; // TIP4P cannot compute virial as F dot r // due to find_M() finding bonded H atoms which are not near O atom no_virial_fdotr_compute = 1; } /* ---------------------------------------------------------------------- */ PairLJLongTIP4PLong::~PairLJLongTIP4PLong() { memory->destroy(hneigh); memory->destroy(newsite); } /* ---------------------------------------------------------------------- */ void PairLJLongTIP4PLong::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype,itable; int n,vlist[6]; int key; int iH1,iH2,jH1,jH2; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul; double fraction,table; double r,r2inv,forcecoul,forcelj,cforce; double factor_coul; double grij,expm2,prefactor,t,erfc; double fO[3],fH[3],fd[3],v[6]; double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; // reallocate hneigh & newsite if necessary // initialize hneigh[0] to -1 on steps when reneighboring occurred // initialize hneigh[2] to 0 every step int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; if (atom->nmax > nmax) { nmax = atom->nmax; memory->destroy(hneigh); memory->create(hneigh,nmax,3,"pair:hneigh"); memory->destroy(newsite); memory->create(newsite,nmax,3,"pair:newsite"); } if (neighbor->ago == 0) for (i = 0; i < nall; i++) hneigh[i][0] = -1; for (i = 0; i < nall; i++) hneigh[i][2] = 0; double **f = atom->f; double **x = atom->x; double *q = atom->q; tagint *tag = atom->tag; int *type = atom->type; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; double cut_coulsqplus = (cut_coul+2.0*qdist)*(cut_coul+2.0*qdist); int order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6); int ni; double *lj1i, *lj2i, *lj3i, *lj4i, *offseti; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; if (itype == typeO) { if (hneigh[i][0] < 0) { iH1 = atom->map(tag[i] + 1); iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set iH1,iH2 to closest image to O iH1 = domain->closest_image(i,iH1); iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); hneigh[i][0] = iH1; hneigh[i][1] = iH2; hneigh[i][2] = 1; } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; if (hneigh[i][2] == 0) { hneigh[i][2] = 1; compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); } } x1 = newsite[i]; } else x1 = x[i]; jlist = firstneigh[i]; jnum = numneigh[i]; offseti = offset[itype]; lj1i = lj1[itype]; lj2i = lj2[itype]; lj3i = lj3[itype]; lj4i = lj4[itype]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; ni = sbmask(j); factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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 < cut_ljsq[itype][jtype]) { // lj r2inv = 1.0/rsq; if (order6) { // long-range lj if (!ndisptablebits || rsq <= tabinnerdispsq) { register double rn = r2inv*r2inv*r2inv; register double x2 = g2*rsq, a2 = 1.0/x2; x2 = a2*exp(-x2)*lj4i[jtype]; if (ni == 0) { forcelj = (rn*=rn)*lj1i[jtype]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq; if (eflag) evdwl = rn*lj3i[jtype]-g6*((a2+1.0)*a2+0.5)*x2; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); forcelj = f*(rn *= rn)*lj1i[jtype]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*lj2i[jtype]; if (eflag) evdwl = f*rn*lj3i[jtype]-g6*((a2+1.0)*a2+0.5)*x2+t*lj4i[jtype]; } } else { // table real space register union_int_float_t disp_t; disp_t.f = rsq; register const int disp_k = (disp_t.i & ndispmask)>>ndispshiftbits; register double f_disp = (rsq-rdisptable[disp_k])*drdisptable[disp_k]; register double rn = r2inv*r2inv*r2inv; if (ni == 0) { forcelj = (rn*=rn)*lj1i[jtype]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[jtype]; if (eflag) evdwl = rn*lj3i[jtype]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[jtype]; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); forcelj = f*(rn *= rn)*lj1i[jtype]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[jtype]+t*lj2i[jtype]; if (eflag) evdwl = f*rn*lj3i[jtype]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[jtype]+t*lj4i[jtype]; } } } else { // cut lj register double rn = r2inv*r2inv*r2inv; if (ni == 0) { forcelj = rn*(rn*lj1i[jtype]-lj2i[jtype]); if (eflag) evdwl = rn*(rn*lj3i[jtype]-lj4i[jtype])-offseti[jtype]; } else { // special case register double f = special_lj[ni]; forcelj = f*rn*(rn*lj1i[jtype]-lj2i[jtype]); if (eflag) evdwl = f * (rn*(rn*lj3i[jtype]-lj4i[jtype])-offseti[jtype]); } } forcelj *= r2inv; f[i][0] += delx*forcelj; f[i][1] += dely*forcelj; f[i][2] += delz*forcelj; f[j][0] -= delx*forcelj; f[j][1] -= dely*forcelj; f[j][2] -= delz*forcelj; if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,forcelj,delx,dely,delz); } // adjust rsq and delxyz for off-site O charge(s) // ADDITIONAL REQEUST REQUIRED HERE!!!!! if (rsq < cut_coulsqplus) { if (itype == typeO || jtype == typeO) { if (jtype == typeO) { if (hneigh[j][0] < 0) { jH1 = atom->map(tag[j] + 1); jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set jH1,jH2 to closest image to O jH1 = domain->closest_image(j,jH1); jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); hneigh[j][0] = jH1; hneigh[j][1] = jH2; hneigh[j][2] = 1; } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; if (hneigh[j][2] == 0) { hneigh[j][2] = 1; compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); } } x2 = newsite[j]; } else x2 = x[j]; delx = x1[0] - x2[0]; dely = x1[1] - x2[1]; delz = x1[2] - x2[2]; rsq = delx*delx + dely*dely + delz*delz; } // test current rsq against cutoff and compute Coulombic force if (rsq < cut_coulsq && order1) { r2inv = 1.0 / rsq; if (!ncoultablebits || rsq <= tabinnersq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; prefactor = qqrd2e * qtmp*q[j]/r; forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) { forcecoul -= (1.0-factor_coul)*prefactor; } } else { union_int_float_t rsq_lookup; rsq_lookup.f = rsq; itable = rsq_lookup.i & ncoulmask; itable >>= ncoulshiftbits; fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable]; table = ftable[itable] + fraction*dftable[itable]; forcecoul = qtmp*q[j] * table; if (factor_coul < 1.0) { table = ctable[itable] + fraction*dctable[itable]; prefactor = qtmp*q[j] * table; forcecoul -= (1.0-factor_coul)*prefactor; } } cforce = forcecoul * r2inv; //if (evflag) ev_tally(i,j,nlocal,newton_pair, // evdwl,0.0,cforce,delx,dely,delz); // if i,j are not O atoms, force is applied directly // if i or j are O atoms, force is on fictitious atom & partitioned // force partitioning due to Feenstra, J Comp Chem, 20, 786 (1999) // f_f = fictitious force, fO = f_f (1 - 2 alpha), fH = alpha f_f // preserves total force and torque on water molecule // virial = sum(r x F) where each water's atoms are near xi and xj // vlist stores 2,4,6 atoms whose forces contribute to virial n = 0; key = 0; if (itype != typeO) { f[i][0] += delx * cforce; f[i][1] += dely * cforce; f[i][2] += delz * cforce; if (vflag) { v[0] = x[i][0] * delx * cforce; v[1] = x[i][1] * dely * cforce; v[2] = x[i][2] * delz * cforce; v[3] = x[i][0] * dely * cforce; v[4] = x[i][0] * delz * cforce; v[5] = x[i][1] * delz * cforce; } vlist[n++] = i; } else { key += 1; fd[0] = delx*cforce; fd[1] = dely*cforce; fd[2] = delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[i][0] += fO[0]; f[i][1] += fO[1]; f[i][2] += fO[2]; f[iH1][0] += fH[0]; f[iH1][1] += fH[1]; f[iH1][2] += fH[2]; f[iH2][0] += fH[0]; f[iH2][1] += fH[1]; f[iH2][2] += fH[2]; if (vflag) { xH1 = x[iH1]; xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; v[3] = x[i][0]*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1]; v[4] = x[i][0]*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2]; v[5] = x[i][1]*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2]; } vlist[n++] = i; vlist[n++] = iH1; vlist[n++] = iH2; } if (jtype != typeO) { f[j][0] -= delx * cforce; f[j][1] -= dely * cforce; f[j][2] -= delz * cforce; if (vflag) { v[0] -= x[j][0] * delx * cforce; v[1] -= x[j][1] * dely * cforce; v[2] -= x[j][2] * delz * cforce; v[3] -= x[j][0] * dely * cforce; v[4] -= x[j][0] * delz * cforce; v[5] -= x[j][1] * delz * cforce; } vlist[n++] = j; } else { key += 2; fd[0] = -delx*cforce; fd[1] = -dely*cforce; fd[2] = -delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[j][0] += fO[0]; f[j][1] += fO[1]; f[j][2] += fO[2]; f[jH1][0] += fH[0]; f[jH1][1] += fH[1]; f[jH1][2] += fH[2]; f[jH2][0] += fH[0]; f[jH2][1] += fH[1]; f[jH2][2] += fH[2]; if (vflag) { xH1 = x[jH1]; xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; v[3] += x[j][0]*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1]; v[4] += x[j][0]*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2]; v[5] += x[j][1]*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2]; } vlist[n++] = j; vlist[n++] = jH1; vlist[n++] = jH2; } if (eflag) { if (!ncoultablebits || rsq <= tabinnersq) ecoul = prefactor*erfc; else { table = etable[itable] + fraction*detable[itable]; ecoul = qtmp*q[j] * table; } if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (evflag) ev_tally_tip4p(key,vlist,v,ecoul,alpha); } } } } } /* --------------------------------------------------------------------- */ void PairLJLongTIP4PLong::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; int iH1,iH2,jH1,jH2; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz; double r2inv,forcecoul,forcelj,cforce; double fO[3],fH[3],fd[3]; double *x1,*x2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq, qri; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // reallocate hneigh & newsite if necessary // initialize hneigh[0] to -1 on steps when reneighboring occurred // initialize hneigh[2] to 0 every step int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; // atom->nmax > nmax will occur during setup if (atom->nmax > nmax) { nmax = atom->nmax; memory->destroy(hneigh); memory->create(hneigh,nmax,3,"pair:hneigh"); memory->destroy(newsite); memory->create(newsite,nmax,3,"pair:newsite"); } if (neighbor->ago == 0) for (i = 0; i < nall; i++) hneigh[i][0] = -1; for (i = 0; i < nall; i++) hneigh[i][2] = 0; double **f = atom->f; double **x = atom->x; double *q = atom->q; tagint *tag = atom->tag; int *type = atom->type; double *special_coul = force->special_coul; double *special_lj = force->special_lj; double qqrd2e = force->qqrd2e; double cut_coulsqplus = (cut_coul+2.0*qdist)*(cut_coul+2.0*qdist); int order1 = ewald_order&(1<<1); int ni; double *lj1i, *lj2i; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; if (itype == typeO && order1) { if (hneigh[i][0] < 0) { iH1 = atom->map(tag[i] + 1); iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set iH1,iH2 to closest image to O iH1 = domain->closest_image(i,iH1); iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); hneigh[i][0] = iH1; hneigh[i][1] = iH2; hneigh[i][2] = 1; } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; if (hneigh[i][2] == 0) { hneigh[i][2] = 1; compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); } } x1 = newsite[i]; } else x1 = x[i]; jlist = firstneigh[i]; jnum = numneigh[i]; lj1i = lj1[itype]; lj2i = lj2[itype]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; ni = sbmask(j); j &= NEIGHMASK; 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 < cut_ljsq[itype][jtype] && rsq < cut_out_off_sq ) { // lj r2inv = 1.0/rsq; register double rn = r2inv*r2inv*r2inv; if (ni == 0) forcelj = rn*(rn*lj1i[jtype]-lj2i[jtype]); else { // special case register double f = special_lj[ni]; forcelj = f*rn*(rn*lj1i[jtype]-lj2i[jtype]); } if (rsq > cut_out_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; forcelj *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } forcelj *= r2inv; f[i][0] += delx*forcelj; f[i][1] += dely*forcelj; f[i][2] += delz*forcelj; f[j][0] -= delx*forcelj; f[j][1] -= dely*forcelj; f[j][2] -= delz*forcelj; } // adjust rsq and delxyz for off-site O charge(s) // ADDITIONAL REQEUST REQUIRED HERE!!!!! if (rsq < cut_coulsqplus && order1) { if (itype == typeO || jtype == typeO) { if (jtype == typeO) { if (hneigh[j][0] < 0) { jH1 = atom->map(tag[j] + 1); jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set jH1,jH2 to closest image to O jH1 = domain->closest_image(j,jH1); jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); hneigh[j][0] = jH1; hneigh[j][1] = jH2; hneigh[j][2] = 1; } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; if (hneigh[j][2] == 0) { hneigh[j][2] = 1; compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); } } x2 = newsite[j]; } else x2 = x[j]; delx = x1[0] - x2[0]; dely = x1[1] - x2[1]; delz = x1[2] - x2[2]; rsq = delx*delx + dely*dely + delz*delz; } // test current rsq against cutoff and compute Coulombic force if (rsq < cut_coulsq && rsq < cut_out_off_sq) { r2inv = 1.0 / rsq; qri = qqrd2e*qtmp; if (ni == 0) forcecoul = qri*q[j]*sqrt(r2inv); else { forcecoul = qri*q[j]*sqrt(r2inv)*special_coul[ni]; } if (rsq > cut_out_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; forcecoul *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } cforce = forcecoul * r2inv; //if (evflag) ev_tally(i,j,nlocal,newton_pair, // evdwl,0.0,cforce,delx,dely,delz); // if i,j are not O atoms, force is applied directly // if i or j are O atoms, force is on fictitious atom & partitioned // force partitioning due to Feenstra, J Comp Chem, 20, 786 (1999) // f_f = fictitious force, fO = f_f (1 - 2 alpha), fH = alpha f_f // preserves total force and torque on water molecule // virial = sum(r x F) where each water's atoms are near xi and xj // vlist stores 2,4,6 atoms whose forces contribute to virial if (itype != typeO) { f[i][0] += delx * cforce; f[i][1] += dely * cforce; f[i][2] += delz * cforce; } else { fd[0] = delx*cforce; fd[1] = dely*cforce; fd[2] = delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[i][0] += fO[0]; f[i][1] += fO[1]; f[i][2] += fO[2]; f[iH1][0] += fH[0]; f[iH1][1] += fH[1]; f[iH1][2] += fH[2]; f[iH2][0] += fH[0]; f[iH2][1] += fH[1]; f[iH2][2] += fH[2]; } if (jtype != typeO) { f[j][0] -= delx * cforce; f[j][1] -= dely * cforce; f[j][2] -= delz * cforce; } else { fd[0] = -delx*cforce; fd[1] = -dely*cforce; fd[2] = -delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[j][0] += fO[0]; f[j][1] += fO[1]; f[j][2] += fO[2]; f[jH1][0] += fH[0]; f[jH1][1] += fH[1]; f[jH1][2] += fH[2]; f[jH2][0] += fH[0]; f[jH2][1] += fH[1]; f[jH2][2] += fH[2]; } } } } } } /* --------------------------------------------------------------------- */ void PairLJLongTIP4PLong::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; int iH1,iH2,jH1,jH2; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz; double r2inv,forcecoul,forcelj,cforce; double fO[3],fH[3],fd[3]; double *x1,*x2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq,qri; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // reallocate hneigh & newsite if necessary // initialize hneigh[0] to -1 on steps when reneighboring occurred // initialize hneigh[2] to 0 every step double **f = atom->f; double **x = atom->x; double *q = atom->q; tagint *tag = atom->tag; int *type = atom->type; double *special_coul = force->special_coul; double *special_lj = force->special_lj; double qqrd2e = force->qqrd2e; double cut_coulsqplus = (cut_coul+2.0*qdist)*(cut_coul+2.0*qdist); int order1 = ewald_order&(1<<1); int ni; double *lj1i, *lj2i; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; if (itype == typeO && order1) { if (hneigh[i][0] < 0) { iH1 = atom->map(tag[i] + 1); iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set iH1,iH2 to closest image to O iH1 = domain->closest_image(i,iH1); iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); hneigh[i][0] = iH1; hneigh[i][1] = iH2; hneigh[i][2] = 1; } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; if (hneigh[i][2] == 0) { hneigh[i][2] = 1; compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); } } x1 = newsite[i]; } else x1 = x[i]; jlist = firstneigh[i]; jnum = numneigh[i]; lj1i = lj1[itype]; lj2i = lj2[itype]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; ni = sbmask(j); j &= NEIGHMASK; 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 < cut_ljsq[itype][jtype] && rsq >= cut_in_off_sq && rsq <= cut_out_off_sq ) { // lj r2inv = 1.0/rsq; register double rn = r2inv*r2inv*r2inv; if (ni == 0) forcelj = rn*(rn*lj1i[jtype]-lj2i[jtype]); else { // special case register double f = special_lj[ni]; forcelj = f*rn*(rn*lj1i[jtype]-lj2i[jtype]); } if (rsq < cut_in_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; forcelj *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } forcelj *= r2inv; f[i][0] += delx*forcelj; f[i][1] += dely*forcelj; f[i][2] += delz*forcelj; f[j][0] -= delx*forcelj; f[j][1] -= dely*forcelj; f[j][2] -= delz*forcelj; } // adjust rsq and delxyz for off-site O charge(s) // ADDITIONAL REQEUST REQUIRED HERE!!!!! if (rsq < cut_coulsqplus && order1) { if (itype == typeO || jtype == typeO) { if (jtype == typeO) { if (hneigh[j][0] < 0) { jH1 = atom->map(tag[j] + 1); jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set jH1,jH2 to closest image to O jH1 = domain->closest_image(j,jH1); jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); hneigh[j][0] = jH1; hneigh[j][1] = jH2; hneigh[j][2] = 1; } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; if (hneigh[j][2] == 0) { hneigh[j][2] = 1; compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); } } x2 = newsite[j]; } else x2 = x[j]; delx = x1[0] - x2[0]; dely = x1[1] - x2[1]; delz = x1[2] - x2[2]; rsq = delx*delx + dely*dely + delz*delz; } // test current rsq against cutoff and compute Coulombic force if (rsq < cut_coulsq && rsq >= cut_in_off_sq && rsq <= cut_out_off_sq) { r2inv = 1.0 / rsq; qri = qqrd2e*qtmp; if (ni == 0) forcecoul = qri*q[j]*sqrt(r2inv); else { forcecoul = qri*q[j]*sqrt(r2inv)*special_coul[ni]; } if (rsq < cut_in_on_sq) { // switching register double rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcecoul *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; forcecoul *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } cforce = forcecoul * r2inv; //if (evflag) ev_tally(i,j,nlocal,newton_pair, // evdwl,0.0,cforce,delx,dely,delz); // if i,j are not O atoms, force is applied directly // if i or j are O atoms, force is on fictitious atom & partitioned // force partitioning due to Feenstra, J Comp Chem, 20, 786 (1999) // f_f = fictitious force, fO = f_f (1 - 2 alpha), fH = alpha f_f // preserves total force and torque on water molecule // virial = sum(r x F) where each water's atoms are near xi and xj // vlist stores 2,4,6 atoms whose forces contribute to virial if (itype != typeO) { f[i][0] += delx * cforce; f[i][1] += dely * cforce; f[i][2] += delz * cforce; } else { fd[0] = delx*cforce; fd[1] = dely*cforce; fd[2] = delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[i][0] += fO[0]; f[i][1] += fO[1]; f[i][2] += fO[2]; f[iH1][0] += fH[0]; f[iH1][1] += fH[1]; f[iH1][2] += fH[2]; f[iH2][0] += fH[0]; f[iH2][1] += fH[1]; f[iH2][2] += fH[2]; } if (jtype != typeO) { f[j][0] -= delx * cforce; f[j][1] -= dely * cforce; f[j][2] -= delz * cforce; } else { fd[0] = -delx*cforce; fd[1] = -dely*cforce; fd[2] = -delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[j][0] += fO[0]; f[j][1] += fO[1]; f[j][2] += fO[2]; f[jH1][0] += fH[0]; f[jH1][1] += fH[1]; f[jH1][2] += fH[2]; f[jH2][0] += fH[0]; f[jH2][1] += fH[1]; f[jH2][2] += fH[2]; } } } } } } /* --------------------------------------------------------------------- */ void PairLJLongTIP4PLong::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; int n,vlist[6]; int key; int iH1,iH2,jH1,jH2; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul; double r2inv,forcecoul,forcelj,cforce, respa_coul, respa_lj, frespa,fvirial; double fO[3],fH[3],fd[3],v[6]; double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq,qri; int respa_flag; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; // reallocate hneigh & newsite if necessary // initialize hneigh[0] to -1 on steps when reneighboring occurred // initialize hneigh[2] to 0 every step int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; if (atom->nmax > nmax) { nmax = atom->nmax; memory->destroy(hneigh); memory->create(hneigh,nmax,3,"pair:hneigh"); memory->destroy(newsite); memory->create(newsite,nmax,3,"pair:newsite"); } if (neighbor->ago == 0) { for (i = 0; i < nall; i++) hneigh[i][0] = -1; for (i = 0; i < nall; i++) hneigh[i][2] = 0; } double **f = atom->f; double **x = atom->x; double *q = atom->q; tagint *tag = atom->tag; int *type = atom->type; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; double cut_coulsqplus = (cut_coul+2.0*qdist)*(cut_coul+2.0*qdist); int order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6); int ni; double *lj1i, *lj2i, *lj3i, *lj4i, *offseti; double g2 = g_ewald_6*g_ewald_6, g6 = g2*g2*g2, g8 = g6*g2; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; qri = qtmp*qqrd2e; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; if (itype == typeO) { if (hneigh[i][0] < 0) { iH1 = atom->map(tag[i] + 1); iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set iH1,iH2 to closest image to O iH1 = domain->closest_image(i,iH1); iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); hneigh[i][0] = iH1; hneigh[i][1] = iH2; hneigh[i][2] = 1; } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; if (hneigh[i][2] == 0) { hneigh[i][2] = 1; compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); } } x1 = newsite[i]; } else x1 = x[i]; jlist = firstneigh[i]; jnum = numneigh[i]; offseti = offset[itype]; lj1i = lj1[itype]; lj2i = lj2[itype]; lj3i = lj3[itype]; lj4i = lj4[itype]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; ni = sbmask(j); j &= NEIGHMASK; 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]; respa_coul = 0; respa_lj = 0; if (rsq < cut_ljsq[itype][jtype]) { // lj frespa = 1.0; // check whether and how to compute respa corrections respa_flag = rsq < cut_in_on_sq ? 1 : 0; if (respa_flag && (rsq > cut_in_off_sq)) { register double rsw = (sqrt(rsq)-cut_in_off)/cut_in_diff; frespa = 1-rsw*rsw*(3.0-2.0*rsw); } r2inv = 1.0/rsq; register double rn = r2inv*r2inv*r2inv; if (respa_flag) respa_lj = ni == 0 ? // correct for respa frespa*rn*(rn*lj1i[jtype]-lj2i[jtype]) : frespa*rn*(rn*lj1i[jtype]-lj2i[jtype])*special_lj[ni]; if (order6) { // long-range form if (!ndisptablebits || rsq <= tabinnerdispsq) { register double x2 = g2*rsq, a2 = 1.0/x2; x2 = a2*exp(-x2)*lj4i[jtype]; if (ni == 0) { forcelj = (rn*=rn)*lj1i[jtype]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq-respa_lj; if (eflag) evdwl = rn*lj3i[jtype]-g6*((a2+1.0)*a2+0.5)*x2; } else { // correct for special register double f = special_lj[ni], t = rn*(1.0-f); forcelj = f*(rn *= rn)*lj1i[jtype]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*lj2i[jtype]-respa_lj; if (eflag) evdwl = f*rn*lj3i[jtype]-g6*((a2+1.0)*a2+0.5)*x2+t*lj4i[jtype]; } } else { // table real space register union_int_float_t disp_t; disp_t.f = rsq; register const int disp_k = (disp_t.i & ndispmask)>>ndispshiftbits; register double f_disp = (rsq-rdisptable[disp_k])*drdisptable[disp_k]; if (ni == 0) { forcelj = (rn*=rn)*lj1i[jtype]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[jtype]-respa_lj; if (eflag) evdwl = rn*lj3i[jtype]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[jtype]; } else { // special case register double f = special_lj[ni], t = rn*(1.0-f); forcelj = f*(rn *= rn)*lj1i[jtype]-(fdisptable[disp_k]+f_disp*dfdisptable[disp_k])*lj4i[jtype]+t*lj2i[jtype]-respa_lj; if (eflag) evdwl = f*rn*lj3i[jtype]-(edisptable[disp_k]+f_disp*dedisptable[disp_k])*lj4i[jtype]+t*lj4i[jtype]; } } } else { // cut form if (ni == 0) { forcelj = rn*(rn*lj1i[jtype]-lj2i[jtype])-respa_lj; if (eflag) evdwl = rn*(rn*lj3i[jtype]-lj4i[jtype])-offseti[jtype]; } else { // correct for special register double f = special_lj[ni]; forcelj = f*rn*(rn*lj1i[jtype]-lj2i[jtype])-respa_lj; if (eflag) evdwl = f*(rn*(rn*lj3i[jtype]-lj4i[jtype])-offseti[jtype]); } } forcelj *= r2inv; f[i][0] += delx*forcelj; f[i][1] += dely*forcelj; f[i][2] += delz*forcelj; f[j][0] -= delx*forcelj; f[j][1] -= dely*forcelj; f[j][2] -= delz*forcelj; if (evflag) { fvirial = forcelj + respa_lj*r2inv; ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fvirial,delx,dely,delz); } } // adjust rsq and delxyz for off-site O charge(s) // ADDITIONAL REQEUST REQUIRED HERE!!!!! if (rsq < cut_coulsqplus) { if (itype == typeO || jtype == typeO) { if (jtype == typeO) { if (hneigh[j][0] < 0) { jH1 = atom->map(tag[j] + 1); jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); // set jH1,jH2 to closest image to O jH1 = domain->closest_image(j,jH1); jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); hneigh[j][0] = jH1; hneigh[j][1] = jH2; hneigh[j][2] = 1; } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; if (hneigh[j][2] == 0) { hneigh[j][2] = 1; compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); } } x2 = newsite[j]; } else x2 = x[j]; delx = x1[0] - x2[0]; dely = x1[1] - x2[1]; delz = x1[2] - x2[2]; rsq = delx*delx + dely*dely + delz*delz; } // test current rsq against cutoff and compute Coulombic force if ((rsq < cut_coulsq) && order1) { frespa = 1.0; // check whether and how to compute respa corrections respa_flag = rsq < cut_in_on_sq ? 1 : 0; if (respa_flag && (rsq > cut_in_off_sq)) { register double rsw = (sqrt(rsq)-cut_in_off)/cut_in_diff; frespa = 1-rsw*rsw*(3.0-2.0*rsw); } r2inv = 1.0 / rsq; if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double r = sqrt(rsq), s = qri*q[j]; if (respa_flag) // correct for respa respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni]; register double x = g_ewald*r, t = 1.0/(1.0+EWALD_P*x); if (ni == 0) { s *= g_ewald*exp(-x*x); forcecoul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-respa_coul; if (eflag) ecoul = t; } else { // correct for special r = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x); forcecoul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r-respa_coul; if (eflag) ecoul = t-r; } } // table real space else { if (respa_flag) { register double r = sqrt(rsq), s = qri*q[j]; respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni]; } register union_int_float_t t; t.f = rsq; register const int k = (t.i & ncoulmask) >> ncoulshiftbits; register double f = (t.f-rtable[k])*drtable[k], qiqj = qtmp*q[j]; if (ni == 0) { forcecoul = qiqj*(ftable[k]+f*dftable[k]); if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]); } else { // correct for special t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]); forcecoul = qiqj*(ftable[k]+f*dftable[k]-t.f); if (eflag) { t.f = (1.0-special_coul[ni])*(ptable[k]+f*dptable[k]); ecoul = qiqj*(etable[k]+f*detable[k]-t.f); } } } cforce = forcecoul * r2inv; fvirial = (forcecoul + respa_coul) * r2inv; // if i,j are not O atoms, force is applied directly // if i or j are O atoms, force is on fictitious atom & partitioned // force partitioning due to Feenstra, J Comp Chem, 20, 786 (1999) // f_f = fictitious force, fO = f_f (1 - 2 alpha), fH = alpha f_f // preserves total force and torque on water molecule // virial = sum(r x F) where each water's atoms are near xi and xj // vlist stores 2,4,6 atoms whose forces contribute to virial n = 0; key = 0; if (itype != typeO) { f[i][0] += delx * cforce; f[i][1] += dely * cforce; f[i][2] += delz * cforce; if (vflag) { v[0] = x[i][0] * delx * fvirial; v[1] = x[i][1] * dely * fvirial; v[2] = x[i][2] * delz * fvirial; v[3] = x[i][0] * dely * fvirial; v[4] = x[i][0] * delz * fvirial; v[5] = x[i][1] * delz * fvirial; } vlist[n++] = i; } else { key += 1; fd[0] = delx*cforce; fd[1] = dely*cforce; fd[2] = delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[i][0] += fO[0]; f[i][1] += fO[1]; f[i][2] += fO[2]; f[iH1][0] += fH[0]; f[iH1][1] += fH[1]; f[iH1][2] += fH[2]; f[iH2][0] += fH[0]; f[iH2][1] += fH[1]; f[iH2][2] += fH[2]; if (vflag) { fd[0] = delx*fvirial; fd[1] = dely*fvirial; fd[2] = delz*fvirial; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; xH1 = x[iH1]; xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; v[3] = x[i][0]*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1]; v[4] = x[i][0]*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2]; v[5] = x[i][1]*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2]; } vlist[n++] = i; vlist[n++] = iH1; vlist[n++] = iH2; } if (jtype != typeO) { f[j][0] -= delx * cforce; f[j][1] -= dely * cforce; f[j][2] -= delz * cforce; if (vflag) { v[0] -= x[j][0] * delx * fvirial; v[1] -= x[j][1] * dely * fvirial; v[2] -= x[j][2] * delz * fvirial; v[3] -= x[j][0] * dely * fvirial; v[4] -= x[j][0] * delz * fvirial; v[5] -= x[j][1] * delz * fvirial; } vlist[n++] = j; } else { key += 2; fd[0] = -delx*cforce; fd[1] = -dely*cforce; fd[2] = -delz*cforce; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; f[j][0] += fO[0]; f[j][1] += fO[1]; f[j][2] += fO[2]; f[jH1][0] += fH[0]; f[jH1][1] += fH[1]; f[jH1][2] += fH[2]; f[jH2][0] += fH[0]; f[jH2][1] += fH[1]; f[jH2][2] += fH[2]; if (vflag) { fd[0] = -delx*fvirial; fd[1] = -dely*fvirial; fd[2] = -delz*fvirial; fO[0] = fd[0]*(1 - alpha); fO[1] = fd[1]*(1 - alpha); fO[2] = fd[2]*(1 - alpha); fH[0] = 0.5 * alpha * fd[0]; fH[1] = 0.5 * alpha * fd[1]; fH[2] = 0.5 * alpha * fd[2]; xH1 = x[jH1]; xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; v[3] += x[j][0]*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1]; v[4] += x[j][0]*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2]; v[5] += x[j][1]*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2]; } vlist[n++] = j; vlist[n++] = jH1; vlist[n++] = jH2; } if (evflag) ev_tally_tip4p(key,vlist,v,ecoul,alpha); } } } } } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJLongTIP4PLong::settings(int narg, char **arg) { if (narg < 8 || narg > 9) error->all(FLERR,"Illegal pair_style command"); ewald_off = 0; ewald_order = 0; options(arg, 6); options(++arg, 1); if (!comm->me && ewald_order&(1<<6)) error->warning(FLERR,"Mixing forced for lj coefficients"); if (!comm->me && ewald_order==((1<<1)|(1<<6))) error->warning(FLERR, "Using largest cutoff for pair_style lj/long/tip4p/long"); if (!((ewald_order^ewald_off)&(1<<1))) error->all(FLERR, "Coulomb cut not supported in pair_style lj/long/tip4p/long"); typeO = force->inumeric(FLERR,arg[1]); typeH = force->inumeric(FLERR,arg[2]); typeB = force->inumeric(FLERR,arg[3]); typeA = force->inumeric(FLERR,arg[4]); qdist = force->numeric(FLERR,arg[5]); cut_lj_global = force->numeric(FLERR,arg[6]); if (narg == 8) cut_coul = cut_lj_global; else cut_coul = force->numeric(FLERR,arg[7]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut_lj[i][j] = cut_lj_global; } } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJLongTIP4PLong::init_style() { if (atom->tag_enable == 0) error->all(FLERR,"Pair style lj/long/tip4p/long requires atom IDs"); if (!force->newton_pair) error->all(FLERR,"Pair style lj/long/tip4p/long requires newton pair on"); if (!atom->q_flag) error->all(FLERR,"Pair style lj/long/tip4p/long requires atom attribute q"); if (force->bond == NULL) error->all(FLERR,"Must use a bond style with TIP4P potential"); if (force->angle == NULL) error->all(FLERR,"Must use an angle style with TIP4P potential"); PairLJLongCoulLong::init_style(); // set alpha parameter double theta = force->angle->equilibrium_angle(typeA); double blen = force->bond->equilibrium_distance(typeB); alpha = qdist / (cos(0.5*theta) * blen); } /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJLongTIP4PLong::init_one(int i, int j) { double cut = PairLJLongCoulLong::init_one(i,j); // check that LJ epsilon = 0.0 for water H // set LJ cutoff to 0.0 for any interaction involving water H // so LJ term isn't calculated in compute() if ((i == typeH && epsilon[i][i] != 0.0)) error->all(FLERR,"Water H epsilon must be 0.0 for " "pair style lj/long/tip4p/long"); if (i == typeH || j == typeH) cut_ljsq[j][i] = cut_ljsq[i][j] = 0.0; return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJLongTIP4PLong::write_restart_settings(FILE *fp) { fwrite(&typeO,sizeof(int),1,fp); fwrite(&typeH,sizeof(int),1,fp); fwrite(&typeB,sizeof(int),1,fp); fwrite(&typeA,sizeof(int),1,fp); fwrite(&qdist,sizeof(double),1,fp); fwrite(&cut_lj_global,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&ncoultablebits,sizeof(int),1,fp); fwrite(&tabinner,sizeof(double),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJLongTIP4PLong::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&typeO,sizeof(int),1,fp); fread(&typeH,sizeof(int),1,fp); fread(&typeB,sizeof(int),1,fp); fread(&typeA,sizeof(int),1,fp); fread(&qdist,sizeof(double),1,fp); fread(&cut_lj_global,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&ncoultablebits,sizeof(int),1,fp); fread(&tabinner,sizeof(double),1,fp); } MPI_Bcast(&typeO,1,MPI_INT,0,world); MPI_Bcast(&typeH,1,MPI_INT,0,world); MPI_Bcast(&typeB,1,MPI_INT,0,world); MPI_Bcast(&typeA,1,MPI_INT,0,world); MPI_Bcast(&qdist,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&ncoultablebits,1,MPI_INT,0,world); MPI_Bcast(&tabinner,1,MPI_DOUBLE,0,world); } /* ---------------------------------------------------------------------- compute position xM of fictitious charge site for O atom and 2 H atoms return it as xM ------------------------------------------------------------------------- */ void PairLJLongTIP4PLong::compute_newsite(double *xO, double *xH1, double *xH2, double *xM) { double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); xM[2] = xO[2] + alpha * 0.5 * (delz1 + delz2); } /* ---------------------------------------------------------------------- */ void *PairLJLongTIP4PLong::extract(const char *str, int &dim) { dim = 0; if (strcmp(str,"qdist") == 0) return (void *) &qdist; if (strcmp(str,"typeO") == 0) return (void *) &typeO; if (strcmp(str,"typeH") == 0) return (void *) &typeH; if (strcmp(str,"typeA") == 0) return (void *) &typeA; if (strcmp(str,"typeB") == 0) return (void *) &typeB; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; const char *ids[] = { "B", "sigma", "epsilon", "ewald_order", "ewald_cut", "cut_coul", "ewald_mix", "cut_LJ", NULL}; void *ptrs[] = { lj4, sigma, epsilon, &ewald_order, &cut_coul, &cut_coul, &mix_flag, &cut_lj_global, NULL}; int i; i=0; while (ids[i] != NULL) { if (i <=2) dim = 2; else dim = 0; if (strcmp(ids[i],str) == 0) return ptrs[i]; ++i; } return NULL; } /* ---------------------------------------------------------------------- memory usage of hneigh ------------------------------------------------------------------------- */ double PairLJLongTIP4PLong::memory_usage() { double bytes = maxeatom * sizeof(double); bytes += maxvatom*6 * sizeof(double); bytes += 2 * nmax * sizeof(double); return bytes; } diff --git a/src/USER-FEP/pair_lj_charmm_coul_long_soft.cpp b/src/USER-FEP/pair_lj_charmm_coul_long_soft.cpp index d8bfd698b..06285a58d 100644 --- a/src/USER-FEP/pair_lj_charmm_coul_long_soft.cpp +++ b/src/USER-FEP/pair_lj_charmm_coul_long_soft.cpp @@ -1,1028 +1,1015 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) Soft-core version: Agilio Padua (Univ Blaise Pascal & CNRS) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_charmm_coul_long_soft.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJCharmmCoulLongSoft::PairLJCharmmCoulLongSoft(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; ewaldflag = pppmflag = 1; implicit = 0; mix_flag = ARITHMETIC; writedata = 1; } /* ---------------------------------------------------------------------- */ PairLJCharmmCoulLongSoft::~PairLJCharmmCoulLongSoft() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(lambda); memory->destroy(eps14); memory->destroy(sigma14); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(lj14_1); memory->destroy(lj14_2); memory->destroy(lj14_3); memory->destroy(lj14_4); } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double r,rsq,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double philj,switch1,switch2; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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 < cut_bothsq) { if (rsq < cut_coulsq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; denc = sqrt(lj4[itype][jtype] + rsq); prefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else forcecoul = 0.0; if (rsq < cut_ljsq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; switch2 = 12.0 * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) / denom_lj; philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; fpair = forcecoul + factor_lj*forcelj; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { prefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / denc; ecoul = prefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (rsq < cut_ljsq) { evdwl = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; evdwl *= switch1; } evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,forcecoul,forcelj,factor_coul,factor_lj; double rsw; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { jtype = type[j]; denc = sqrt(lj4[itype][jtype] + rsq); forcecoul = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); fpair = forcecoul + factor_lj*forcelj; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,forcecoul,forcelj,factor_coul,factor_lj; double philj,switch1,switch2; double rsw; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { jtype = type[j]; denc = sqrt(lj4[itype][jtype] + rsq); forcecoul = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; switch2 = 12.0 * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) / denom_lj; philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); forcelj = forcelj*switch1 + philj*switch2; } fpair = forcecoul + factor_lj*forcelj; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double r,rsq,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,fprefactor,eprefactor,t,erfc; double philj,switch1,switch2; double rsw; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_bothsq) { jtype = type[j]; if (rsq < cut_coulsq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; denc = sqrt(lj4[itype][jtype] + rsq); fprefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); forcecoul = fprefactor * (erfc + EWALD_F*grij*expm2 - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += fprefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*fprefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += fprefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*fprefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq && rsq > cut_in_off_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; switch2 = 12.0 * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) / denom_lj; philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); forcelj = forcelj*switch1 + philj*switch2; } if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = forcecoul + forcelj; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { eprefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / denc; ecoul = eprefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*eprefactor; } else ecoul = 0.0; if (rsq < cut_ljsq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; evdwl = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; evdwl *= switch1; } evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { forcecoul = fprefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*fprefactor; } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; switch2 = 12.0 * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) / denom_lj; philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); forcelj = forcelj*switch1 + philj*switch2; } } else if (rsq <= cut_in_on_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; switch2 = 12.0 * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) / denom_lj; philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); forcelj = forcelj*switch1 + philj*switch2; } } fpair = forcecoul + factor_lj*forcelj; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lambda,n+1,n+1,"pair:lambda"); memory->create(eps14,n+1,n+1,"pair:eps14"); memory->create(sigma14,n+1,n+1,"pair:sigma14"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(lj14_1,n+1,n+1,"pair:lj14_1"); memory->create(lj14_2,n+1,n+1,"pair:lj14_2"); memory->create(lj14_3,n+1,n+1,"pair:lj14_3"); memory->create(lj14_4,n+1,n+1,"pair:lj14_4"); } /* ---------------------------------------------------------------------- global settings unlike other pair styles, there are no individual pair settings that these override ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::settings(int narg, char **arg) { if (narg != 5 && narg != 6) error->all(FLERR,"Illegal pair_style command"); nlambda = force->numeric(FLERR,arg[0]); alphalj = force->numeric(FLERR,arg[1]); alphac = force->numeric(FLERR,arg[2]); cut_lj_inner = force->numeric(FLERR,arg[3]); cut_lj = force->numeric(FLERR,arg[4]); if (narg == 5) cut_coul = cut_lj; else cut_coul = force->numeric(FLERR,arg[5]); } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::coeff(int narg, char **arg) { if (narg != 5 && narg != 7) error->all(FLERR,"Illegal pair_coeff command"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double lambda_one = force->numeric(FLERR,arg[4]); double eps14_one = epsilon_one; double sigma14_one = sigma_one; if (narg == 7) { eps14_one = force->numeric(FLERR,arg[5]); sigma14_one = force->numeric(FLERR,arg[6]); } int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; lambda[i][j] = lambda_one; eps14[i][j] = eps14_one; sigma14[i][j] = sigma14_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::init_style() { if (!atom->q_flag) error->all(FLERR, "Pair style lj/charmm/coul/long/soft requires atom attribute q"); // request regular or rRESPA neighbor lists int irequest; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; if (respa == 0) irequest = neighbor->request(this,instance_me); else if (respa == 1) { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } else { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 2; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respamiddle = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } } else irequest = neighbor->request(this,instance_me); // require cut_lj_inner < cut_lj if (cut_lj_inner >= cut_lj) error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff"); cut_lj_innersq = cut_lj_inner * cut_lj_inner; cut_ljsq = cut_lj * cut_lj; cut_coulsq = cut_coul * cut_coul; cut_bothsq = MAX(cut_ljsq,cut_coulsq); denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq); // set & error check interior rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) { cut_respa = ((Respa *) update->integrate)->cutoff; if (MIN(cut_lj,cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); if (cut_lj_inner < cut_respa[1]) error->all(FLERR,"Pair inner cutoff < Respa interior cutoff"); } else cut_respa = NULL; // insure use of KSpace long-range solver, set g_ewald if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); g_ewald = force->kspace->g_ewald; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJCharmmCoulLongSoft::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCharmmCoulLongSoft::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); if (lambda[i][i] != lambda[j][j]) error->all(FLERR,"Pair lj/charmm/coul/long/soft different lambda values in mix"); lambda[i][j] = lambda[i][i]; eps14[i][j] = mix_energy(eps14[i][i],eps14[j][j], sigma14[i][i],sigma14[j][j]); sigma14[i][j] = mix_distance(sigma14[i][i],sigma14[j][j]); } double cut = MAX(cut_lj,cut_coul); lj1[i][j] = pow(lambda[i][j], nlambda); lj2[i][j] = pow(sigma[i][j], 6.0); lj3[i][j] = alphalj * (1.0 - lambda[i][j])*(1.0 - lambda[i][j]); lj4[i][j] = alphac * (1.0 - lambda[i][j])*(1.0 - lambda[i][j]); // 1-4 interactions unaffected (they're part of the dihedral term) lj14_1[i][j] = 48.0 * eps14[i][j] * pow(sigma14[i][j],12.0); lj14_2[i][j] = 24.0 * eps14[i][j] * pow(sigma14[i][j],6.0); lj14_3[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],12.0); lj14_4[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],6.0); epsilon[j][i] = epsilon[i][j]; sigma[j][i] = sigma[i][j]; lambda[j][i] = lambda[i][j]; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; lj14_1[j][i] = lj14_1[i][j]; lj14_2[j][i] = lj14_2[i][j]; lj14_3[j][i] = lj14_3[i][j]; lj14_4[j][i] = lj14_4[i][j]; return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&lambda[i][j],sizeof(double),1,fp); fwrite(&eps14[i][j],sizeof(double),1,fp); fwrite(&sigma14[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&lambda[i][j],sizeof(double),1,fp); fread(&eps14[i][j],sizeof(double),1,fp); fread(&sigma14[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&lambda[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&eps14[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma14[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::write_restart_settings(FILE *fp) { fwrite(&nlambda,sizeof(double),1,fp); fwrite(&alphalj,sizeof(double),1,fp); fwrite(&alphac,sizeof(double),1,fp); fwrite(&cut_lj_inner,sizeof(double),1,fp); fwrite(&cut_lj,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&nlambda,sizeof(double),1,fp); fread(&alphalj,sizeof(double),1,fp); fread(&alphac,sizeof(double),1,fp); fread(&cut_lj_inner,sizeof(double),1,fp); fread(&cut_lj,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); } MPI_Bcast(&nlambda,1,MPI_DOUBLE,0,world); MPI_Bcast(&alphalj,1,MPI_DOUBLE,0,world); MPI_Bcast(&alphac,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g %g %g %g\n",i,epsilon[i][i],sigma[i][i], lambda[i][i],eps14[i][i],sigma14[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCharmmCoulLongSoft::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g %g %g\n",i,j,epsilon[i][j],sigma[i][j], lambda[i][j],eps14[i][j],sigma14[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCharmmCoulLongSoft::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r,grij,expm2,t,erfc,prefactor; double switch1,switch2,forcecoul,forcelj,phicoul,philj; double denc, denlj, r4sig6; if (rsq < cut_coulsq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; denc = sqrt(lj4[itype][jtype] + rsq); prefactor = force->qqrd2e * lj1[itype][jtype] * atom->q[i]*atom->q[j] / (denc*denc*denc); forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else forcecoul = 0.0; if (rsq < cut_ljsq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; switch2 = 12.0 * (cut_ljsq-rsq) * (rsq-cut_lj_innersq) / denom_lj; philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; fforce = forcecoul + factor_lj*forcelj; double eng = 0.0; if (rsq < cut_coulsq) { prefactor = force->qqrd2e * lj1[itype][jtype] * atom->q[i]*atom->q[j] / denc; phicoul = prefactor*erfc; if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq) { philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj); if (rsq > cut_lj_innersq) { switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; philj *= switch1; } eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCharmmCoulLongSoft::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"lj14_1") == 0) return (void *) lj14_1; if (strcmp(str,"lj14_2") == 0) return (void *) lj14_2; if (strcmp(str,"lj14_3") == 0) return (void *) lj14_3; if (strcmp(str,"lj14_4") == 0) return (void *) lj14_4; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; if (strcmp(str,"lambda") == 0) return (void *) lambda; dim = 0; if (strcmp(str,"implicit") == 0) return (void *) &implicit; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; return NULL; } diff --git a/src/USER-FEP/pair_lj_charmm_coul_long_soft.h b/src/USER-FEP/pair_lj_charmm_coul_long_soft.h index 7e52ec54b..252c9f66f 100644 --- a/src/USER-FEP/pair_lj_charmm_coul_long_soft.h +++ b/src/USER-FEP/pair_lj_charmm_coul_long_soft.h @@ -1,107 +1,106 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/charmm/coul/long/soft,PairLJCharmmCoulLongSoft) #else #ifndef LMP_PAIR_LJ_CHARMM_COUL_LONG_SOFT_H #define LMP_PAIR_LJ_CHARMM_COUL_LONG_SOFT_H #include "pair.h" namespace LAMMPS_NS { class PairLJCharmmCoulLongSoft : public Pair { public: PairLJCharmmCoulLongSoft(class LAMMPS *); virtual ~PairLJCharmmCoulLongSoft(); virtual void compute(int, int); void settings(int, char **); void coeff(int, char **); void init_style(); - void init_list(int, class NeighList *); double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); virtual double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); virtual void compute_outer(int, int); virtual void *extract(const char *, int &); protected: int implicit; double cut_lj_inner,cut_lj; double cut_lj_innersq,cut_ljsq; double cut_coul,cut_coulsq; double cut_bothsq; double denom_lj; double **epsilon,**sigma,**eps14,**sigma14,**lambda; double nlambda, alphalj, alphac; double **lj1,**lj2,**lj3,**lj4,**offset; double **lj14_1,**lj14_2,**lj14_3,**lj14_4; double *cut_respa; double g_ewald; void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair style lj/charmm/coul/long/soft requires atom attribute q The atom style defined does not have these attributes. E: Pair inner cutoff >= Pair outer cutoff The specified cutoffs for the pair style are inconsistent. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair inner cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair style requires a KSpace style No kspace style is defined. */ diff --git a/src/USER-FEP/pair_lj_cut_coul_long_soft.cpp b/src/USER-FEP/pair_lj_cut_coul_long_soft.cpp index f7c4084fe..f1503a694 100644 --- a/src/USER-FEP/pair_lj_cut_coul_long_soft.cpp +++ b/src/USER-FEP/pair_lj_cut_coul_long_soft.cpp @@ -1,961 +1,961 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) Soft-core version: Agilio Padua (Univ Blaise Pascal & CNRS) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_cut_coul_long_soft.h" #include "atom.h" #include "comm.h" #include "force.h" #include "kspace.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; #define EWALD_F 1.12837917 #define EWALD_P 0.3275911 #define A1 0.254829592 #define A2 -0.284496736 #define A3 1.421413741 #define A4 -1.453152027 #define A5 1.061405429 /* ---------------------------------------------------------------------- */ PairLJCutCoulLongSoft::PairLJCutCoulLongSoft(LAMMPS *lmp) : Pair(lmp) { ewaldflag = pppmflag = 1; respa_enable = 1; writedata = 1; qdist = 0.0; } /* ---------------------------------------------------------------------- */ PairLJCutCoulLongSoft::~PairLJCutCoulLongSoft() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut_lj); memory->destroy(cut_ljsq); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(lambda); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(offset); } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::compute(int eflag, int vflag) { int i,ii,j,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double r,rsq,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { if (rsq < cut_coulsq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; denc = sqrt(lj4[itype][jtype] + rsq); prefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } else forcelj = 0.0; fpair = forcecoul + factor_lj*forcelj; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { prefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / denc; ecoul = prefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor; } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { evdwl = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,forcecoul,forcelj,factor_coul,factor_lj; double rsw; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { jtype = type[j]; denc = sqrt(lj4[itype][jtype] + rsq); forcecoul = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; if (rsq < cut_ljsq[itype][jtype]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } else forcelj = 0.0; fpair = forcecoul + factor_lj*forcelj; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,forcecoul,forcelj,factor_coul,factor_lj; double rsw; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { jtype = type[j]; denc = sqrt(lj4[itype][jtype] + rsq); forcecoul = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul; if (rsq < cut_ljsq[itype][jtype]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } else forcelj = 0.0; fpair = forcecoul + factor_lj*forcelj; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair; double r,rsq,forcecoul,forcelj,factor_coul,factor_lj; double grij,expm2,fprefactor,eprefactor,t,erfc; double rsw; double denc, denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; double *q = atom->q; int *type = atom->type; int nlocal = atom->nlocal; double *special_coul = force->special_coul; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; double qqrd2e = force->qqrd2e; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; qtmp = q[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; factor_coul = special_coul[sbmask(j)]; j &= NEIGHMASK; 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]) { if (rsq < cut_coulsq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; denc = sqrt(lj4[itype][jtype] + rsq); fprefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / (denc*denc*denc); forcecoul = fprefactor * (erfc + EWALD_F*grij*expm2 - 1.0); if (rsq > cut_in_off_sq) { if (rsq < cut_in_on_sq) { rsw = (r - cut_in_off)/cut_in_diff; forcecoul += fprefactor*rsw*rsw*(3.0 - 2.0*rsw); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*fprefactor*rsw*rsw*(3.0 - 2.0*rsw); } else { forcecoul += fprefactor; if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*fprefactor; } } } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype] && rsq > cut_in_off_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; forcelj *= rsw*rsw*(3.0 - 2.0*rsw); } } else forcelj = 0.0; fpair = forcecoul + forcelj; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { if (rsq < cut_coulsq) { eprefactor = qqrd2e * lj1[itype][jtype] * qtmp*q[j] / denc; ecoul = eprefactor*erfc; if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*eprefactor; } else ecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; evdwl = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj) - offset[itype][jtype]; evdwl *= factor_lj; } else evdwl = 0.0; } if (vflag) { if (rsq < cut_coulsq) { forcecoul = fprefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*fprefactor; } else forcecoul = 0.0; if (rsq <= cut_in_off_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } else if (rsq < cut_in_on_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } fpair = forcecoul + factor_lj*forcelj; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,ecoul,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut_lj,n+1,n+1,"pair:cut_lj"); memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lambda,n+1,n+1,"pair:lambda"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::settings(int narg, char **arg) { if (narg < 4 || narg > 5) error->all(FLERR,"Illegal pair_style command"); nlambda = force->numeric(FLERR,arg[0]); alphalj = force->numeric(FLERR,arg[1]); alphac = force->numeric(FLERR,arg[2]); cut_lj_global = force->numeric(FLERR,arg[3]); if (narg == 4) cut_coul = cut_lj_global; else cut_coul = force->numeric(FLERR,arg[4]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut_lj[i][j] = cut_lj_global; } } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::coeff(int narg, char **arg) { if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double lambda_one = force->numeric(FLERR,arg[4]); if (sigma_one <= 0.0) error->all(FLERR,"Incorrect args for pair coefficients"); double cut_lj_one = cut_lj_global; if (narg == 6) cut_lj_one = force->numeric(FLERR,arg[5]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; lambda[i][j] = lambda_one; cut_lj[i][j] = cut_lj_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::init_style() { if (!atom->q_flag) error->all(FLERR,"Pair style lj/cut/coul/long/soft requires atom attribute q"); // request regular or rRESPA neighbor lists int irequest; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; if (respa == 0) irequest = neighbor->request(this,instance_me); else if (respa == 1) { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } else { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 2; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respamiddle = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } } else irequest = neighbor->request(this,instance_me); cut_coulsq = cut_coul * cut_coul; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; // insure use of KSpace long-range solver, set g_ewald if (force->kspace == NULL) error->all(FLERR,"Pair style requires a KSpace style"); g_ewald = force->kspace->g_ewald; } /* ---------------------------------------------------------------------- neighbor callback to inform pair style of neighbor list to use regular or rRESPA ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::init_list(int id, NeighList *ptr) { if (id == 0) list = ptr; else if (id == 1) listinner = ptr; else if (id == 2) listmiddle = ptr; else if (id == 3) listouter = ptr; } /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCutCoulLongSoft::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); if (lambda[i][i] != lambda[j][j]) error->all(FLERR,"Pair lj/cut/coul/long/soft different lambda values in mix"); lambda[i][j] = lambda[i][i]; cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]); } // include TIP4P qdist in full cutoff, qdist = 0.0 if not TIP4P double cut = MAX(cut_lj[i][j],cut_coul+2.0*qdist); cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j]; lj1[i][j] = pow(lambda[i][j], nlambda); lj2[i][j] = pow(sigma[i][j], 6.0); lj3[i][j] = alphalj * (1.0 - lambda[i][j])*(1.0 - lambda[i][j]); lj4[i][j] = alphac * (1.0 - lambda[i][j])*(1.0 - lambda[i][j]); if (offset_flag && (cut_lj[i][j] > 0.0)) { double denlj = lj3[i][j] + pow(cut_lj[i][j] / sigma[i][j], 6.0); offset[i][j] = lj1[i][j] * 4.0 * epsilon[i][j] * (1.0/(denlj*denlj) - 1.0/denlj); } else offset[i][j] = 0.0; epsilon[j][i] = epsilon[i][j]; sigma[j][i] = sigma[i][j]; lambda[j][i] = lambda[i][j]; cut_ljsq[j][i] = cut_ljsq[i][j]; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; offset[j][i] = offset[i][j]; // check interior rRESPA cutoff if (cut_respa && MIN(cut_lj[i][j],cut_coul) < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); // compute I,J contribution to long-range tail correction // count total # of atoms of type I and J via Allreduce if (tail_flag) { int *type = atom->type; int nlocal = atom->nlocal; double count[2],all[2]; count[0] = count[1] = 0.0; for (int k = 0; k < nlocal; k++) { if (type[k] == i) count[0] += 1.0; if (type[k] == j) count[1] += 1.0; } MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world); double sig2 = sigma[i][j]*sigma[i][j]; double sig6 = sig2*sig2*sig2; double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j]; double rc6 = rc3*rc3; double rc9 = rc3*rc6; etail_ij = 8.0*MY_PI*all[0]*all[1]* lj1[i][j] * epsilon[i][j] * sig6 * (sig6 - 3.0*rc6) / (9.0*rc9); ptail_ij = 16.0*MY_PI*all[0]*all[1]* lj1[i][j] * epsilon[i][j] * sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9); } return cut; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&lambda[i][j],sizeof(double),1,fp); fwrite(&cut_lj[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&lambda[i][j],sizeof(double),1,fp); fread(&cut_lj[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&lambda[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::write_restart_settings(FILE *fp) { fwrite(&nlambda,sizeof(double),1,fp); fwrite(&alphalj,sizeof(double),1,fp); fwrite(&alphac,sizeof(double),1,fp); fwrite(&cut_lj_global,sizeof(double),1,fp); fwrite(&cut_coul,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&tail_flag,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::read_restart_settings(FILE *fp) { if (comm->me == 0) { fread(&nlambda,sizeof(double),1,fp); fread(&alphalj,sizeof(double),1,fp); fread(&alphac,sizeof(double),1,fp); fread(&cut_lj_global,sizeof(double),1,fp); fread(&cut_coul,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&tail_flag,sizeof(int),1,fp); } MPI_Bcast(&nlambda,1,MPI_DOUBLE,0,world); MPI_Bcast(&alphalj,1,MPI_DOUBLE,0,world); MPI_Bcast(&alphac,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&tail_flag,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g %g\n",i,epsilon[i][i],sigma[i][i],lambda[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCutCoulLongSoft::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g %g\n",i,j,epsilon[i][j],sigma[i][j], lambda[i][j],cut_lj[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCutCoulLongSoft::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r,grij,expm2,t,erfc,prefactor; double forcecoul,forcelj,phicoul,philj; double denc, denlj, r4sig6; if (rsq < cut_coulsq) { r = sqrt(rsq); grij = g_ewald * r; expm2 = exp(-grij*grij); t = 1.0 / (1.0 + EWALD_P*grij); erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2; denc = sqrt(lj4[itype][jtype] + rsq); prefactor = force->qqrd2e * lj1[itype][jtype] * atom->q[i]*atom->q[j] / (denc*denc*denc); forcecoul = prefactor * (erfc + EWALD_F*grij*expm2); if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor; } else forcecoul = 0.0; if (rsq < cut_ljsq[itype][jtype]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } else forcelj = 0.0; fforce = forcecoul + factor_lj*forcelj; double eng = 0.0; if (rsq < cut_coulsq) { prefactor = force->qqrd2e * lj1[itype][jtype] * atom->q[i]*atom->q[j] / denc; phicoul = prefactor*erfc; if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; eng += phicoul; } if (rsq < cut_ljsq[itype][jtype]) { philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj) - offset[itype][jtype]; eng += factor_lj*philj; } return eng; } /* ---------------------------------------------------------------------- */ void *PairLJCutCoulLongSoft::extract(const char *str, int &dim) { dim = 0; if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul; dim = 2; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; if (strcmp(str,"lambda") == 0) return (void *) lambda; return NULL; } diff --git a/src/USER-FEP/pair_lj_cut_coul_long_soft.h b/src/USER-FEP/pair_lj_cut_coul_long_soft.h index a03be3814..d49d1c864 100644 --- a/src/USER-FEP/pair_lj_cut_coul_long_soft.h +++ b/src/USER-FEP/pair_lj_cut_coul_long_soft.h @@ -1,94 +1,93 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/cut/coul/long/soft,PairLJCutCoulLongSoft) #else #ifndef LMP_PAIR_LJ_CUT_COUL_LONG_SOFT_H #define LMP_PAIR_LJ_CUT_COUL_LONG_SOFT_H #include "pair.h" namespace LAMMPS_NS { class PairLJCutCoulLongSoft : public Pair { public: PairLJCutCoulLongSoft(class LAMMPS *); virtual ~PairLJCutCoulLongSoft(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); virtual void init_style(); - void init_list(int, class NeighList *); virtual double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); virtual void write_restart_settings(FILE *); virtual void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); virtual double single(int, int, int, int, double, double, double, double &); virtual void *extract(const char *, int &); void compute_inner(); void compute_middle(); virtual void compute_outer(int, int); protected: double cut_lj_global; double **cut_lj,**cut_ljsq; double cut_coul,cut_coulsq; double **epsilon,**sigma, **lambda; double nlambda, alphalj, alphac; double **lj1,**lj2,**lj3,**lj4,**offset; double *cut_respa; double qdist; // TIP4P distance O to negative charge (compatibility of cutoffs) double g_ewald; void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair style lj/cut/coul/long requires atom attribute q The atom style defined does not have this attribute. E: Pair style requires a KSpace style No kspace style is defined. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/USER-FEP/pair_lj_cut_soft.cpp b/src/USER-FEP/pair_lj_cut_soft.cpp index 8b6280a61..9ae108fa3 100644 --- a/src/USER-FEP/pair_lj_cut_soft.cpp +++ b/src/USER-FEP/pair_lj_cut_soft.cpp @@ -1,783 +1,770 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) Soft-core version: Agilio Padua (Univ Blaise Pascal & CNRS) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_cut_soft.h" #include "atom.h" #include "comm.h" #include "force.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; /* ---------------------------------------------------------------------- */ PairLJCutSoft::PairLJCutSoft(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; writedata = 1; allocated = 0; } /* ---------------------------------------------------------------------- */ PairLJCutSoft::~PairLJCutSoft() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(lambda); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(offset); allocated=0; } } /* ---------------------------------------------------------------------- */ void PairLJCutSoft::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,forcelj,factor_lj; double denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; 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]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); fpair = factor_lj*forcelj; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { evdwl = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj) - offset[itype][jtype]; evdwl *= factor_lj; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCutSoft::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,forcelj,factor_lj,rsw; double denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { jtype = type[j]; r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); fpair = factor_lj*forcelj; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 - rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutSoft::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,forcelj,factor_lj,rsw; double denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { jtype = type[j]; r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); fpair = factor_lj*forcelj; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCutSoft::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,forcelj,factor_lj,rsw; double denlj, r4sig6; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; 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]) { if (rsq > cut_in_off_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); fpair = factor_lj*forcelj; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } if (eflag) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; evdwl = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj) - offset[itype][jtype]; evdwl *= factor_lj; } if (vflag) { if (rsq <= cut_in_off_sq) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); fpair = factor_lj*forcelj; } else if (rsq < cut_in_on_sq) fpair = factor_lj*forcelj; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCutSoft::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut,n+1,n+1,"pair:cut"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lambda,n+1,n+1,"pair:lambda"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJCutSoft::settings(int narg, char **arg) { if (narg != 3) error->all(FLERR,"Illegal pair_style command"); nlambda = force->numeric(FLERR,arg[0]); alphalj = force->numeric(FLERR,arg[1]); cut_global = force->numeric(FLERR,arg[2]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut[i][j] = cut_global; } } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCutSoft::coeff(int narg, char **arg) { if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double lambda_one = force->numeric(FLERR,arg[4]); if (sigma_one <= 0.0) error->all(FLERR,"Incorrect args for pair coefficients"); double cut_one = cut_global; if (narg == 6) cut_one = force->numeric(FLERR,arg[5]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; lambda[i][j] = lambda_one; cut[i][j] = cut_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCutSoft::init_style() { // request regular or rRESPA neighbor lists int irequest; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; if (respa == 0) irequest = neighbor->request(this,instance_me); else if (respa == 1) { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } else { irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 1; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respainner = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 2; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respamiddle = 1; irequest = neighbor->request(this,instance_me); neighbor->requests[irequest]->id = 3; neighbor->requests[irequest]->half = 0; neighbor->requests[irequest]->respaouter = 1; } } else irequest = neighbor->request(this,instance_me); // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJCutSoft::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCutSoft::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); cut[i][j] = mix_distance(cut[i][i],cut[j][j]); } lj1[i][j] = pow(lambda[i][j], nlambda); lj2[i][j] = pow(sigma[i][j], 6.0); lj3[i][j] = alphalj * (1.0 - lambda[i][j])*(1.0 - lambda[i][j]); if (offset_flag && (cut[i][j] > 0.0)) { double denlj = lj3[i][j] + pow(cut[i][j] / sigma[i][j], 6.0); offset[i][j] = lj1[i][j] * 4.0 * epsilon[i][j] * (1.0/(denlj*denlj) - 1.0/denlj); } else offset[i][j] = 0.0; epsilon[j][i] = epsilon[i][j]; sigma[j][i] = sigma[i][j]; lambda[j][i] = lambda[i][j]; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; offset[j][i] = offset[i][j]; // check interior rRESPA cutoff if (cut_respa && cut[i][j] < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); // compute I,J contribution to long-range tail correction // count total # of atoms of type I and J via Allreduce if (tail_flag) { int *type = atom->type; int nlocal = atom->nlocal; double count[2],all[2]; count[0] = count[1] = 0.0; for (int k = 0; k < nlocal; k++) { if (type[k] == i) count[0] += 1.0; if (type[k] == j) count[1] += 1.0; } MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world); double sig2 = sigma[i][j]*sigma[i][j]; double sig6 = sig2*sig2*sig2; double rc3 = cut[i][j]*cut[i][j]*cut[i][j]; double rc6 = rc3*rc3; double rc9 = rc3*rc6; etail_ij = 8.0*MY_PI*all[0]*all[1]* lj1[i][j] * epsilon[i][j] * sig6 * (sig6 - 3.0*rc6) / (9.0*rc9); ptail_ij = 16.0*MY_PI*all[0]*all[1]* lj1[i][j] * epsilon[i][j] * sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9); } return cut[i][j]; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCutSoft::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&lambda[i][j],sizeof(double),1,fp); fwrite(&cut[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCutSoft::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&lambda[i][j],sizeof(double),1,fp); fread(&cut[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&lambda[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCutSoft::write_restart_settings(FILE *fp) { fwrite(&nlambda,sizeof(double),1,fp); fwrite(&alphalj,sizeof(double),1,fp); fwrite(&cut_global,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&tail_flag,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCutSoft::read_restart_settings(FILE *fp) { int me = comm->me; if (me == 0) { fread(&nlambda,sizeof(double),1,fp); fread(&alphalj,sizeof(double),1,fp); fread(&cut_global,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&tail_flag,sizeof(int),1,fp); } MPI_Bcast(&nlambda,1,MPI_DOUBLE,0,world); MPI_Bcast(&alphalj,1,MPI_DOUBLE,0,world); MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&tail_flag,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCutSoft::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g %g\n",i,epsilon[i][i],sigma[i][i],lambda[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCutSoft::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g %g\n",i,j,epsilon[i][j],sigma[i][j], lambda[i][j],cut[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCutSoft::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double forcelj,philj; double r4sig6, denlj; if (rsq < cutsq[itype][jtype]) { r4sig6 = rsq*rsq / lj2[itype][jtype]; denlj = lj3[itype][jtype] + rsq*r4sig6; forcelj = lj1[itype][jtype] * epsilon[itype][jtype] * (48.0*r4sig6/(denlj*denlj*denlj) - 24.0*r4sig6/(denlj*denlj)); } else forcelj = 0.0; fforce = factor_lj*forcelj; if (rsq < cutsq[itype][jtype]) { philj = lj1[itype][jtype] * 4.0 * epsilon[itype][jtype] * (1.0/(denlj*denlj) - 1.0/denlj) - offset[itype][jtype]; } else philj = 0.0; return factor_lj*philj; } /* ---------------------------------------------------------------------- */ void *PairLJCutSoft::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; if (strcmp(str,"lambda") == 0) return (void *) lambda; return NULL; } diff --git a/src/USER-FEP/pair_lj_cut_soft.h b/src/USER-FEP/pair_lj_cut_soft.h index 50ce685e5..46202d78a 100644 --- a/src/USER-FEP/pair_lj_cut_soft.h +++ b/src/USER-FEP/pair_lj_cut_soft.h @@ -1,87 +1,86 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/cut/soft,PairLJCutSoft) #else #ifndef LMP_PAIR_LJ_CUT_SOFT_H #define LMP_PAIR_LJ_CUT_SOFT_H #include "pair.h" namespace LAMMPS_NS { class PairLJCutSoft : public Pair { public: PairLJCutSoft(class LAMMPS *); virtual ~PairLJCutSoft(); virtual void compute(int, int); virtual void settings(int, char **); void coeff(int, char **); virtual void init_style(); - void init_list(int, class NeighList *); virtual double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); virtual void write_restart_settings(FILE *); virtual void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); virtual double single(int, int, int, int, double, double, double, double &); void *extract(const char *, int &); void compute_inner(); void compute_middle(); void compute_outer(int, int); protected: double cut_global; double **cut; double **epsilon,**sigma, **lambda; double nlambda, alphalj; double **lj1,**lj2,**lj3,**offset; double *cut_respa; void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. E: Pair lj/cut/soft different lambda values in mix The value of lambda has to be the same for I J pairs. */ diff --git a/src/min.cpp b/src/min.cpp index af23629ca..653cac71e 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -1,828 +1,833 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Aidan Thompson (SNL) improved CG and backtrack ls, added quadratic ls Sources: Numerical Recipes frprmn routine "Conjugate Gradient Method Without the Agonizing Pain" by JR Shewchuk, http://www-2.cs.cmu.edu/~jrs/jrspapers.html#cg ------------------------------------------------------------------------- */ #include #include #include #include "min.h" #include "atom.h" #include "atom_vec.h" #include "domain.h" #include "comm.h" #include "update.h" #include "modify.h" #include "fix_minimize.h" #include "compute.h" #include "neighbor.h" #include "force.h" #include "pair.h" #include "bond.h" #include "angle.h" #include "dihedral.h" #include "improper.h" #include "kspace.h" #include "output.h" #include "thermo.h" #include "timer.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ Min::Min(LAMMPS *lmp) : Pointers(lmp) { dmax = 0.1; searchflag = 0; linestyle = 1; elist_global = elist_atom = NULL; vlist_global = vlist_atom = NULL; nextra_global = 0; fextra = NULL; nextra_atom = 0; xextra_atom = fextra_atom = NULL; extra_peratom = extra_nlen = NULL; extra_max = NULL; requestor = NULL; external_force_clear = 0; } /* ---------------------------------------------------------------------- */ Min::~Min() { delete [] elist_global; delete [] elist_atom; delete [] vlist_global; delete [] vlist_atom; delete [] fextra; memory->sfree(xextra_atom); memory->sfree(fextra_atom); memory->destroy(extra_peratom); memory->destroy(extra_nlen); memory->destroy(extra_max); memory->sfree(requestor); } /* ---------------------------------------------------------------------- */ void Min::init() { // create fix needed for storing atom-based quantities // will delete it at end of run char **fixarg = new char*[3]; fixarg[0] = (char *) "MINIMIZE"; fixarg[1] = (char *) "all"; fixarg[2] = (char *) "MINIMIZE"; modify->add_fix(3,fixarg); delete [] fixarg; fix_minimize = (FixMinimize *) modify->fix[modify->nfix-1]; // clear out extra global and per-atom dof // will receive requests for new per-atom dof during pair init() // can then add vectors to fix_minimize in setup() nextra_global = 0; delete [] fextra; fextra = NULL; nextra_atom = 0; memory->sfree(xextra_atom); memory->sfree(fextra_atom); memory->destroy(extra_peratom); memory->destroy(extra_nlen); memory->destroy(extra_max); memory->sfree(requestor); xextra_atom = fextra_atom = NULL; extra_peratom = extra_nlen = NULL; extra_max = NULL; requestor = NULL; // virial_style: // 1 if computed explicitly by pair->compute via sum over pair interactions // 2 if computed implicitly by pair->virial_compute via sum over ghost atoms if (force->newton_pair) virial_style = 2; else virial_style = 1; // setup lists of computes for global and per-atom PE and pressure ev_setup(); // detect if fix omp is present for clearing force arrays int ifix = modify->find_fix("package_omp"); if (ifix >= 0) external_force_clear = 1; // set flags for arrays to clear in force_clear() torqueflag = extraflag = 0; if (atom->torque_flag) torqueflag = 1; if (atom->avec->forceclearflag) extraflag = 1; // allow pair and Kspace compute() to be turned off via modify flags if (force->pair && force->pair->compute_flag) pair_compute_flag = 1; else pair_compute_flag = 0; if (force->kspace && force->kspace->compute_flag) kspace_compute_flag = 1; else kspace_compute_flag = 0; // orthogonal vs triclinic simulation box triclinic = domain->triclinic; // reset reneighboring criteria if necessary neigh_every = neighbor->every; neigh_delay = neighbor->delay; neigh_dist_check = neighbor->dist_check; if (neigh_every != 1 || neigh_delay != 0 || neigh_dist_check != 1) { if (comm->me == 0) error->warning(FLERR, "Using 'neigh_modify every 1 delay 0 check" " yes' setting during minimization"); } neighbor->every = 1; neighbor->delay = 0; neighbor->dist_check = 1; niter = neval = 0; } /* ---------------------------------------------------------------------- setup before run ------------------------------------------------------------------------- */ void Min::setup(int flag) { if (comm->me == 0 && screen) { fprintf(screen,"Setting up %s style minimization ...\n", update->minimize_style); if (flag) { fprintf(screen," Unit style : %s\n", update->unit_style); fprintf(screen," Current step : " BIGINT_FORMAT "\n", update->ntimestep); timer->print_timeout(screen); } } update->setupflag = 1; // setup extra global dof due to fixes // cannot be done in init() b/c update init() is before modify init() nextra_global = modify->min_dof(); if (nextra_global) { fextra = new double[nextra_global]; if (comm->me == 0 && screen) fprintf(screen,"WARNING: Energy due to %d extra global DOFs will" " be included in minimizer energies\n",nextra_global); } // compute for potential energy int id = modify->find_compute("thermo_pe"); if (id < 0) error->all(FLERR,"Minimization could not find thermo_pe compute"); pe_compute = modify->compute[id]; // style-specific setup does two tasks // setup extra global dof vectors // setup extra per-atom dof vectors due to requests from Pair classes // cannot be done in init() b/c update init() is before modify/pair init() setup_style(); // ndoftotal = total dof for entire minimization problem // dof for atoms, extra per-atom, extra global bigint ndofme = 3 * static_cast(atom->nlocal); for (int m = 0; m < nextra_atom; m++) ndofme += extra_peratom[m]*atom->nlocal; MPI_Allreduce(&ndofme,&ndoftotal,1,MPI_LMP_BIGINT,MPI_SUM,world); ndoftotal += nextra_global; // setup domain, communication and neighboring // acquire ghosts // build neighbor lists atom->setup(); modify->setup_pre_exchange(); if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); comm->exchange(); if (atom->sortfreq > 0) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); domain->image_check(); domain->box_too_small_check(); modify->setup_pre_neighbor(); neighbor->build(); + modify->setup_post_neighbor(); neighbor->ncalls = 0; // remove these restriction eventually if (searchflag == 0) { if (nextra_global) error->all(FLERR, "Cannot use a damped dynamics min style with fix box/relax"); if (nextra_atom) error->all(FLERR, "Cannot use a damped dynamics min style with per-atom DOF"); } if (strcmp(update->minimize_style,"hftn") == 0) { if (nextra_global) error->all(FLERR, "Cannot use hftn min style with fix box/relax"); if (nextra_atom) error->all(FLERR, "Cannot use hftn min style with per-atom DOF"); } // atoms may have migrated in comm->exchange() reset_vectors(); // compute all forces force->setup(); ev_set(update->ntimestep); force_clear(); modify->setup_pre_force(vflag); if (pair_compute_flag) force->pair->compute(eflag,vflag); else if (force->pair) force->pair->compute_dummy(eflag,vflag); if (atom->molecular) { if (force->bond) force->bond->compute(eflag,vflag); if (force->angle) force->angle->compute(eflag,vflag); if (force->dihedral) force->dihedral->compute(eflag,vflag); if (force->improper) force->improper->compute(eflag,vflag); } if (force->kspace) { force->kspace->setup(); if (kspace_compute_flag) force->kspace->compute(eflag,vflag); else force->kspace->compute_dummy(eflag,vflag); } modify->setup_pre_reverse(eflag,vflag); if (force->newton) comm->reverse_comm(); // update per-atom minimization variables stored by pair styles if (nextra_atom) for (int m = 0; m < nextra_atom; m++) requestor[m]->min_xf_get(m); modify->setup(vflag); output->setup(flag); update->setupflag = 0; // stats for initial thermo output ecurrent = pe_compute->compute_scalar(); if (nextra_global) ecurrent += modify->min_energy(fextra); if (output->thermo->normflag) ecurrent /= atom->natoms; einitial = ecurrent; fnorm2_init = sqrt(fnorm_sqr()); fnorminf_init = fnorm_inf(); } /* ---------------------------------------------------------------------- setup without output or one-time post-init setup flag = 0 = just force calculation flag = 1 = reneighbor and force calculation ------------------------------------------------------------------------- */ void Min::setup_minimal(int flag) { update->setupflag = 1; // setup domain, communication and neighboring // acquire ghosts // build neighbor lists if (flag) { modify->setup_pre_exchange(); if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); comm->exchange(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); domain->image_check(); domain->box_too_small_check(); modify->setup_pre_neighbor(); neighbor->build(); + modify->setup_post_neighbor(); neighbor->ncalls = 0; } // atoms may have migrated in comm->exchange() reset_vectors(); // compute all forces ev_set(update->ntimestep); force_clear(); modify->setup_pre_force(vflag); if (pair_compute_flag) force->pair->compute(eflag,vflag); else if (force->pair) force->pair->compute_dummy(eflag,vflag); if (atom->molecular) { if (force->bond) force->bond->compute(eflag,vflag); if (force->angle) force->angle->compute(eflag,vflag); if (force->dihedral) force->dihedral->compute(eflag,vflag); if (force->improper) force->improper->compute(eflag,vflag); } if (force->kspace) { force->kspace->setup(); if (kspace_compute_flag) force->kspace->compute(eflag,vflag); else force->kspace->compute_dummy(eflag,vflag); } modify->setup_pre_reverse(eflag,vflag); if (force->newton) comm->reverse_comm(); // update per-atom minimization variables stored by pair styles if (nextra_atom) for (int m = 0; m < nextra_atom; m++) requestor[m]->min_xf_get(m); modify->setup(vflag); update->setupflag = 0; // stats for Finish to print ecurrent = pe_compute->compute_scalar(); if (nextra_global) ecurrent += modify->min_energy(fextra); if (output->thermo->normflag) ecurrent /= atom->natoms; einitial = ecurrent; fnorm2_init = sqrt(fnorm_sqr()); fnorminf_init = fnorm_inf(); } /* ---------------------------------------------------------------------- perform minimization, calling iterate() for N steps ------------------------------------------------------------------------- */ void Min::run(int n) { // minimizer iterations stop_condition = iterate(n); stopstr = stopstrings(stop_condition); // if early exit from iterate loop: // set update->nsteps to niter for Finish stats to print // set output->next values to this timestep // call energy_force() to insure vflag is set when forces computed // output->write does final output for thermo, dump, restart files // add ntimestep to all computes that store invocation times // since are hardwiring call to thermo/dumps and computes may not be ready if (stop_condition != MAXITER) { update->nsteps = niter; if (update->restrict_output == 0) { for (int idump = 0; idump < output->ndump; idump++) output->next_dump[idump] = update->ntimestep; output->next_dump_any = update->ntimestep; if (output->restart_flag) { output->next_restart = update->ntimestep; if (output->restart_every_single) output->next_restart_single = update->ntimestep; if (output->restart_every_double) output->next_restart_double = update->ntimestep; } } output->next_thermo = update->ntimestep; modify->addstep_compute_all(update->ntimestep); ecurrent = energy_force(0); output->write(update->ntimestep); } } /* ---------------------------------------------------------------------- */ void Min::cleanup() { modify->post_run(); // stats for Finish to print efinal = ecurrent; fnorm2_final = sqrt(fnorm_sqr()); fnorminf_final = fnorm_inf(); // reset reneighboring criteria neighbor->every = neigh_every; neighbor->delay = neigh_delay; neighbor->dist_check = neigh_dist_check; // delete fix at end of run, so its atom arrays won't persist modify->delete_fix("MINIMIZE"); domain->box_too_small_check(); } /* ---------------------------------------------------------------------- evaluate potential energy and forces may migrate atoms due to reneighboring return new energy, which should include nextra_global dof return negative gradient stored in atom->f return negative gradient for nextra_global dof in fextra ------------------------------------------------------------------------- */ double Min::energy_force(int resetflag) { // check for reneighboring // always communicate since minimizer moved atoms int nflag = neighbor->decide(); if (nflag == 0) { timer->stamp(); comm->forward_comm(); timer->stamp(Timer::COMM); } else { if (modify->n_min_pre_exchange) { timer->stamp(); modify->min_pre_exchange(); timer->stamp(Timer::MODIFY); } if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); if (domain->box_change) { domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); } timer->stamp(); comm->exchange(); if (atom->sortfreq > 0 && update->ntimestep >= atom->nextsort) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); timer->stamp(Timer::COMM); if (modify->n_min_pre_neighbor) { - timer->stamp(); modify->min_pre_neighbor(); timer->stamp(Timer::MODIFY); } neighbor->build(); timer->stamp(Timer::NEIGH); + if (modify->n_min_post_neighbor) { + modify->min_post_neighbor(); + timer->stamp(Timer::MODIFY); + } } ev_set(update->ntimestep); force_clear(); timer->stamp(); if (modify->n_min_pre_force) { modify->min_pre_force(vflag); timer->stamp(Timer::MODIFY); } if (pair_compute_flag) { force->pair->compute(eflag,vflag); timer->stamp(Timer::PAIR); } if (atom->molecular) { if (force->bond) force->bond->compute(eflag,vflag); if (force->angle) force->angle->compute(eflag,vflag); if (force->dihedral) force->dihedral->compute(eflag,vflag); if (force->improper) force->improper->compute(eflag,vflag); timer->stamp(Timer::BOND); } if (kspace_compute_flag) { force->kspace->compute(eflag,vflag); timer->stamp(Timer::KSPACE); } if (modify->n_min_pre_reverse) { modify->min_pre_reverse(eflag,vflag); timer->stamp(Timer::MODIFY); } if (force->newton) { comm->reverse_comm(); timer->stamp(Timer::COMM); } // update per-atom minimization variables stored by pair styles if (nextra_atom) for (int m = 0; m < nextra_atom; m++) requestor[m]->min_xf_get(m); // fixes that affect minimization if (modify->n_min_post_force) { timer->stamp(); modify->min_post_force(vflag); timer->stamp(Timer::MODIFY); } // compute potential energy of system // normalize if thermo PE does double energy = pe_compute->compute_scalar(); if (nextra_global) energy += modify->min_energy(fextra); if (output->thermo->normflag) energy /= atom->natoms; // if reneighbored, atoms migrated // if resetflag = 1, update x0 of atoms crossing PBC // reset vectors used by lo-level minimizer if (nflag) { if (resetflag) fix_minimize->reset_coords(); reset_vectors(); } return energy; } /* ---------------------------------------------------------------------- clear force on own & ghost atoms clear other arrays as needed ------------------------------------------------------------------------- */ void Min::force_clear() { if (external_force_clear) return; // clear global force array // if either newton flag is set, also include ghosts size_t nbytes = sizeof(double) * atom->nlocal; if (force->newton) nbytes += sizeof(double) * atom->nghost; if (nbytes) { memset(&atom->f[0][0],0,3*nbytes); if (torqueflag) memset(&atom->torque[0][0],0,3*nbytes); if (extraflag) atom->avec->force_clear(0,nbytes); } } /* ---------------------------------------------------------------------- pair style makes request to add a per-atom variables to minimization requestor stores callback to pair class to invoke during min to get current variable and forces on it and to update the variable return flag that pair can use if it registers multiple variables ------------------------------------------------------------------------- */ int Min::request(Pair *pair, int peratom, double maxvalue) { int n = nextra_atom + 1; xextra_atom = (double **) memory->srealloc(xextra_atom,n*sizeof(double *), "min:xextra_atom"); fextra_atom = (double **) memory->srealloc(fextra_atom,n*sizeof(double *), "min:fextra_atom"); memory->grow(extra_peratom,n,"min:extra_peratom"); memory->grow(extra_nlen,n,"min:extra_nlen"); memory->grow(extra_max,n,"min:extra_max"); requestor = (Pair **) memory->srealloc(requestor,n*sizeof(Pair *), "min:requestor"); requestor[nextra_atom] = pair; extra_peratom[nextra_atom] = peratom; extra_max[nextra_atom] = maxvalue; nextra_atom++; return nextra_atom-1; } /* ---------------------------------------------------------------------- */ void Min::modify_params(int narg, char **arg) { if (narg == 0) error->all(FLERR,"Illegal min_modify command"); int iarg = 0; while (iarg < narg) { if (strcmp(arg[iarg],"dmax") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command"); dmax = force->numeric(FLERR,arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"line") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command"); if (strcmp(arg[iarg+1],"backtrack") == 0) linestyle = 0; else if (strcmp(arg[iarg+1],"quadratic") == 0) linestyle = 1; else if (strcmp(arg[iarg+1],"forcezero") == 0) linestyle = 2; else error->all(FLERR,"Illegal min_modify command"); iarg += 2; } else error->all(FLERR,"Illegal min_modify command"); } } /* ---------------------------------------------------------------------- setup lists of computes for global and per-atom PE and pressure ------------------------------------------------------------------------- */ void Min::ev_setup() { delete [] elist_global; delete [] elist_atom; delete [] vlist_global; delete [] vlist_atom; elist_global = elist_atom = NULL; vlist_global = vlist_atom = NULL; nelist_global = nelist_atom = 0; nvlist_global = nvlist_atom = 0; for (int i = 0; i < modify->ncompute; i++) { if (modify->compute[i]->peflag) nelist_global++; if (modify->compute[i]->peatomflag) nelist_atom++; if (modify->compute[i]->pressflag) nvlist_global++; if (modify->compute[i]->pressatomflag) nvlist_atom++; } if (nelist_global) elist_global = new Compute*[nelist_global]; if (nelist_atom) elist_atom = new Compute*[nelist_atom]; if (nvlist_global) vlist_global = new Compute*[nvlist_global]; if (nvlist_atom) vlist_atom = new Compute*[nvlist_atom]; nelist_global = nelist_atom = 0; nvlist_global = nvlist_atom = 0; for (int i = 0; i < modify->ncompute; i++) { if (modify->compute[i]->peflag) elist_global[nelist_global++] = modify->compute[i]; if (modify->compute[i]->peatomflag) elist_atom[nelist_atom++] = modify->compute[i]; if (modify->compute[i]->pressflag) vlist_global[nvlist_global++] = modify->compute[i]; if (modify->compute[i]->pressatomflag) vlist_atom[nvlist_atom++] = modify->compute[i]; } } /* ---------------------------------------------------------------------- set eflag,vflag for current iteration invoke matchstep() on all timestep-dependent computes to clear their arrays eflag/vflag based on computes that need info on this ntimestep always set eflag_global = 1, since need energy every iteration eflag = 0 = no energy computation eflag = 1 = global energy only eflag = 2 = per-atom energy only eflag = 3 = both global and per-atom energy vflag = 0 = no virial computation (pressure) vflag = 1 = global virial with pair portion via sum of pairwise interactions vflag = 2 = global virial with pair portion via F dot r including ghosts vflag = 4 = per-atom virial only vflag = 5 or 6 = both global and per-atom virial ------------------------------------------------------------------------- */ void Min::ev_set(bigint ntimestep) { int i,flag; int eflag_global = 1; for (i = 0; i < nelist_global; i++) elist_global[i]->matchstep(ntimestep); flag = 0; int eflag_atom = 0; for (i = 0; i < nelist_atom; i++) if (elist_atom[i]->matchstep(ntimestep)) flag = 1; if (flag) eflag_atom = 2; if (eflag_global) update->eflag_global = update->ntimestep; if (eflag_atom) update->eflag_atom = update->ntimestep; eflag = eflag_global + eflag_atom; flag = 0; int vflag_global = 0; for (i = 0; i < nvlist_global; i++) if (vlist_global[i]->matchstep(ntimestep)) flag = 1; if (flag) vflag_global = virial_style; flag = 0; int vflag_atom = 0; for (i = 0; i < nvlist_atom; i++) if (vlist_atom[i]->matchstep(ntimestep)) flag = 1; if (flag) vflag_atom = 4; if (vflag_global) update->vflag_global = update->ntimestep; if (vflag_atom) update->vflag_atom = update->ntimestep; vflag = vflag_global + vflag_atom; } /* ---------------------------------------------------------------------- compute and return ||force||_2^2 ------------------------------------------------------------------------- */ double Min::fnorm_sqr() { int i,n; double *fatom; double local_norm2_sqr = 0.0; for (i = 0; i < nvec; i++) local_norm2_sqr += fvec[i]*fvec[i]; if (nextra_atom) { for (int m = 0; m < nextra_atom; m++) { fatom = fextra_atom[m]; n = extra_nlen[m]; for (i = 0; i < n; i++) local_norm2_sqr += fatom[i]*fatom[i]; } } double norm2_sqr = 0.0; MPI_Allreduce(&local_norm2_sqr,&norm2_sqr,1,MPI_DOUBLE,MPI_SUM,world); if (nextra_global) for (i = 0; i < nextra_global; i++) norm2_sqr += fextra[i]*fextra[i]; return norm2_sqr; } /* ---------------------------------------------------------------------- compute and return ||force||_inf ------------------------------------------------------------------------- */ double Min::fnorm_inf() { int i,n; double *fatom; double local_norm_inf = 0.0; for (i = 0; i < nvec; i++) local_norm_inf = MAX(fabs(fvec[i]),local_norm_inf); if (nextra_atom) { for (int m = 0; m < nextra_atom; m++) { fatom = fextra_atom[m]; n = extra_nlen[m]; for (i = 0; i < n; i++) local_norm_inf = MAX(fabs(fatom[i]),local_norm_inf); } } double norm_inf = 0.0; MPI_Allreduce(&local_norm_inf,&norm_inf,1,MPI_DOUBLE,MPI_MAX,world); if (nextra_global) for (i = 0; i < nextra_global; i++) norm_inf = MAX(fabs(fextra[i]),norm_inf); return norm_inf; } /* ---------------------------------------------------------------------- possible stop conditions ------------------------------------------------------------------------- */ char *Min::stopstrings(int n) { const char *strings[] = {"max iterations", "max force evaluations", "energy tolerance", "force tolerance", "search direction is not downhill", "linesearch alpha is zero", "forces are zero", "quadratic factors are zero", "trust region too small", "HFTN minimizer error", "walltime limit reached"}; return (char *) strings[n]; } diff --git a/src/neigh_list.cpp b/src/neigh_list.cpp index 3e347360c..934b9f7d9 100644 --- a/src/neigh_list.cpp +++ b/src/neigh_list.cpp @@ -1,267 +1,330 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "neigh_list.h" #include "atom.h" #include "comm.h" #include "update.h" #include "pair.h" #include "neighbor.h" #include "neigh_request.h" #include "my_page.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define PGDELTA 1 enum{NSQ,BIN,MULTI}; // also in Neighbor /* ---------------------------------------------------------------------- */ NeighList::NeighList(LAMMPS *lmp) : Pointers(lmp) { // initializations maxatom = 0; inum = gnum = 0; ilist = NULL; numneigh = NULL; firstneigh = NULL; // defaults, but may be reset by post_constructor() occasional = 0; ghost = 0; ssa = 0; history = 0; + respaouter = 0; + respamiddle = 0; + respainner = 0; copy = 0; copymode = 0; // ptrs iskip = NULL; ijskip = NULL; listcopy = NULL; listskip = NULL; listfull = NULL; - respamiddle = 0; - listinner = NULL; - listmiddle = NULL; - fix_bond = NULL; ipage = NULL; + // extra rRESPA lists + + inum_inner = gnum_inner = 0; + ilist_inner = NULL; + numneigh_inner = NULL; + firstneigh_inner = NULL; + + inum_middle = gnum_middle = 0; + ilist_middle = NULL; + numneigh_middle = NULL; + firstneigh_middle = NULL; + + ipage_inner = NULL; + ipage_middle = NULL; + // Kokkos package kokkos = 0; execution_space = Host; // USER-DPD package for (int i = 0; i < 8; i++) AIRct_ssa[i] = 0; np = NULL; } /* ---------------------------------------------------------------------- */ NeighList::~NeighList() { if (copymode) return; if (!copy) { memory->destroy(ilist); memory->destroy(numneigh); memory->sfree(firstneigh); delete [] ipage; } + if (respainner) { + memory->destroy(ilist_inner); + memory->destroy(numneigh_inner); + memory->sfree(firstneigh_inner); + delete [] ipage_inner; + } + + if (respamiddle) { + memory->destroy(ilist_middle); + memory->destroy(numneigh_middle); + memory->sfree(firstneigh_middle); + delete [] ipage_middle; + } + delete [] iskip; memory->destroy(ijskip); } /* ---------------------------------------------------------------------- adjust settings to match corresponding NeighRequest cannot do this in constructor b/c not all NeighLists are allocated yet copy -> set listcopy for list to copy from skip -> set listskip for list to skip from, create copy of itype,ijtype halffull -> set listfull for full list to derive from - respaouter -> set listinner/listmiddle for other rRESPA lists + respaouter -> set all 3 outer/middle/inner flags bond -> set fix_bond to Fix that made the request ------------------------------------------------------------------------- */ void NeighList::post_constructor(NeighRequest *nq) { // copy request settings used by list itself occasional = nq->occasional; ghost = nq->ghost; ssa = nq->ssa; history = nq->history; + respaouter = nq->respaouter; + respamiddle = nq->respamiddle; + respainner = nq->respainner; copy = nq->copy; if (nq->copy) listcopy = neighbor->lists[nq->copylist]; if (nq->skip) { listskip = neighbor->lists[nq->skiplist]; int ntypes = atom->ntypes; iskip = new int[ntypes+1]; memory->create(ijskip,ntypes+1,ntypes+1,"neigh_list:ijskip"); int i,j; for (i = 1; i <= ntypes; i++) iskip[i] = nq->iskip[i]; for (i = 1; i <= ntypes; i++) for (j = 1; j <= ntypes; j++) ijskip[i][j] = nq->ijskip[i][j]; } if (nq->halffull) listfull = neighbor->lists[nq->halffulllist]; - if (nq->respaouter) { - if (nq->respamiddlelist < 0) { - respamiddle = 0; - listinner = neighbor->lists[nq->respainnerlist]; - } else { - respamiddle = 1; - listmiddle = neighbor->lists[nq->respamiddlelist]; - listinner = neighbor->lists[nq->respainnerlist]; - } - } - if (nq->bond) fix_bond = (Fix *) nq->requestor; } /* ---------------------------------------------------------------------- */ void NeighList::setup_pages(int pgsize_caller, int oneatom_caller) { pgsize = pgsize_caller; oneatom = oneatom_caller; int nmypage = comm->nthreads; ipage = new MyPage[nmypage]; for (int i = 0; i < nmypage; i++) ipage[i].init(oneatom,pgsize,PGDELTA); + + if (respainner) { + ipage_inner = new MyPage[nmypage]; + for (int i = 0; i < nmypage; i++) + ipage_inner[i].init(oneatom,pgsize,PGDELTA); + } + + if (respamiddle) { + ipage_middle = new MyPage[nmypage]; + for (int i = 0; i < nmypage; i++) + ipage_middle[i].init(oneatom,pgsize,PGDELTA); + } } /* ---------------------------------------------------------------------- grow per-atom data to allow for nlocal/nall atoms - for parent lists: - also trigger grow in child list(s) which are not built themselves - history calls grow() in listhistory - respaouter calls grow() in respainner, respamiddle triggered by neighbor list build not called if a copy list ------------------------------------------------------------------------- */ void NeighList::grow(int nlocal, int nall) { - // trigger grow() in children before possible return - - if (listinner) listinner->grow(nlocal,nall); - if (listmiddle) listmiddle->grow(nlocal,nall); - // skip if data structs are already big enough if (ssa) { if ((nlocal * 3) + nall <= maxatom) return; } else if (ghost) { if (nall <= maxatom) return; } else { if (nlocal <= maxatom) return; } if (ssa) maxatom = (nlocal * 3) + nall; else maxatom = atom->nmax; memory->destroy(ilist); memory->destroy(numneigh); memory->sfree(firstneigh); memory->create(ilist,maxatom,"neighlist:ilist"); memory->create(numneigh,maxatom,"neighlist:numneigh"); firstneigh = (int **) memory->smalloc(maxatom*sizeof(int *), "neighlist:firstneigh"); + + if (respainner) { + memory->destroy(ilist_inner); + memory->destroy(numneigh_inner); + memory->sfree(firstneigh_inner); + memory->create(ilist_inner,maxatom,"neighlist:ilist_inner"); + memory->create(numneigh_inner,maxatom,"neighlist:numneigh_inner"); + firstneigh_inner = (int **) memory->smalloc(maxatom*sizeof(int *), + "neighlist:firstneigh_inner"); + } + + if (respamiddle) { + memory->destroy(ilist_middle); + memory->destroy(numneigh_middle); + memory->sfree(firstneigh_middle); + memory->create(ilist_middle,maxatom,"neighlist:ilist_middle"); + memory->create(numneigh_middle,maxatom,"neighlist:numneigh_middle"); + firstneigh_middle = (int **) memory->smalloc(maxatom*sizeof(int *), + "neighlist:firstneigh_middle"); + } } /* ---------------------------------------------------------------------- print attributes of this list and associated request ------------------------------------------------------------------------- */ void NeighList::print_attributes() { if (comm->me != 0) return; NeighRequest *rq = neighbor->requests[index]; printf("Neighbor list/request %d:\n",index); printf(" %p = requestor ptr (instance %d id %d)\n", rq->requestor,rq->requestor_instance,rq->id); printf(" %d = pair\n",rq->pair); printf(" %d = fix\n",rq->fix); printf(" %d = compute\n",rq->compute); printf(" %d = command\n",rq->command); printf(" %d = neigh\n",rq->neigh); printf("\n"); printf(" %d = half\n",rq->half); printf(" %d = full\n",rq->full); printf("\n"); printf(" %d = occasional\n",occasional); printf(" %d = newton\n",rq->newton); printf(" %d = ghost flag\n",ghost); printf(" %d = size\n",rq->size); printf(" %d = history\n",rq->history); printf(" %d = granonesided\n",rq->granonesided); - printf(" %d = respainner\n",rq->respainner); - printf(" %d = respamiddle\n",rq->respamiddle); printf(" %d = respaouter\n",rq->respaouter); + printf(" %d = respamiddle\n",rq->respamiddle); + printf(" %d = respainner\n",rq->respainner); printf(" %d = bond\n",rq->bond); printf(" %d = omp\n",rq->omp); printf(" %d = intel\n",rq->intel); printf(" %d = kokkos host\n",rq->kokkos_host); printf(" %d = kokkos device\n",rq->kokkos_device); printf(" %d = ssa flag\n",ssa); printf("\n"); printf(" %d = skip flag\n",rq->skip); printf(" %d = off2on\n",rq->off2on); printf(" %d = copy flag\n",rq->copy); printf(" %d = half/full\n",rq->halffull); printf("\n"); } /* ---------------------------------------------------------------------- return # of bytes of allocated memory if growflag = 0, maxatom & maxpage will also be 0 if stencilflag = 0, maxstencil * maxstencil_multi will also be 0 ------------------------------------------------------------------------- */ bigint NeighList::memory_usage() { bigint bytes = 0; bytes += memory->usage(ilist,maxatom); bytes += memory->usage(numneigh,maxatom); bytes += maxatom * sizeof(int *); int nmypage = comm->nthreads; if (ipage) { for (int i = 0; i < nmypage; i++) bytes += ipage[i].size(); } + if (respainner) { + bytes += memory->usage(ilist_inner,maxatom); + bytes += memory->usage(numneigh_inner,maxatom); + bytes += maxatom * sizeof(int *); + if (ipage_inner) { + for (int i = 0; i < nmypage; i++) + bytes += ipage_inner[i].size(); + } + } + + if (respamiddle) { + bytes += memory->usage(ilist_middle,maxatom); + bytes += memory->usage(numneigh_middle,maxatom); + bytes += maxatom * sizeof(int *); + if (ipage_middle) { + for (int i = 0; i < nmypage; i++) + bytes += ipage_middle[i].size(); + } + } + return bytes; } diff --git a/src/neigh_list.h b/src/neigh_list.h index c5b685ca3..d633ba839 100644 --- a/src/neigh_list.h +++ b/src/neigh_list.h @@ -1,96 +1,112 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifndef LMP_NEIGH_LIST_H #define LMP_NEIGH_LIST_H #include "pointers.h" #include "my_page.h" namespace LAMMPS_NS { class NeighList : protected Pointers { public: int index; // index of which neigh list this is // also indexes the request it came from // and the npair list of NPair classes int bin_method; // 0 if no binning, else 1-N index into binnames int stencil_method; // 0 if no stencil, else 1-N index into stencilnames int pair_method; // 0 if no pair, else 1-N index into pairnames // settings from NeighRequest int occasional; // 0 if build every reneighbor, 1 if not int ghost; // 1 if list stores neighbors of ghosts int ssa; // 1 if list stores Shardlow data int history; // 1 if there is neigh history (FixNeighHist) + int respaouter; // 1 if list is a rRespa outer list + int respamiddle; // 1 if there is also a rRespa middle list + int respainner; // 1 if there is also a rRespa inner list int copy; // 1 if this list is copied from another list int copymode; // 1 if this is a Kokkos on-device copy // data structs to store neighbor pairs I,J and associated values int inum; // # of I atoms neighbors are stored for int gnum; // # of ghost atoms neighbors are stored for int *ilist; // local indices of I atoms int *numneigh; // # of J neighbors for each I atom int **firstneigh; // ptr to 1st J int value of each I atom int maxatom; // size of allocated per-atom arrays int pgsize; // size of each page int oneatom; // max size for one atom MyPage *ipage; // pages of neighbor indices + // data structs to store rRESPA neighbor pairs I,J and associated values + + int inum_inner; // # of I atoms neighbors are stored for + int gnum_inner; // # of ghost atoms neighbors are stored for + int *ilist_inner; // local indices of I atoms + int *numneigh_inner; // # of J neighbors for each I atom + int **firstneigh_inner; // ptr to 1st J int value of each I atom + + int inum_middle; // # of I atoms neighbors are stored for + int gnum_middle; // # of ghost atoms neighbors are stored for + int *ilist_middle; // local indices of I atoms + int *numneigh_middle; // # of J neighbors for each I atom + int **firstneigh_middle; // ptr to 1st J int value of each I atom + + MyPage *ipage_inner; // pages of neighbor indices for inner + MyPage *ipage_middle; // pages of neighbor indices for middle + // atom types to skip when building list // copied info from corresponding request into realloced vec/array int *iskip; // iskip[i] = 1 if atoms of type I are not in list int **ijskip; // ijskip[i][j] = 1 if pairs of type I,J are not in list // settings and pointers for related neighbor lists and fixes NeighList *listcopy; // me = copy list, point to list I copy from NeighList *listskip; // me = skip list, point to list I skip from NeighList *listfull; // me = half list, point to full I derive from - int respamiddle; // 1 if this respaouter has middle list - NeighList *listinner; // me = respaouter, point to respainner - NeighList *listmiddle; // me = respaouter, point to respamiddle - class Fix *fix_bond; // fix that stores bond info // Kokkos package int kokkos; // 1 if list stores Kokkos data ExecutionSpace execution_space; // USER-DPD package and Shardlow Splitting Algorithm (SSA) support int AIRct_ssa[8]; // count of how many atoms in each AIR class NPair *np; // ptr to NPair instance I depend on // methods NeighList(class LAMMPS *); virtual ~NeighList(); void post_constructor(class NeighRequest *); void setup_pages(int, int); // setup page data structures void grow(int,int); // grow all data structs void print_attributes(); // debug routine int get_maxlocal() {return maxatom;} bigint memory_usage(); }; } #endif diff --git a/src/neigh_request.cpp b/src/neigh_request.cpp index d5397dcf7..6325eec56 100644 --- a/src/neigh_request.cpp +++ b/src/neigh_request.cpp @@ -1,244 +1,241 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "neigh_request.h" #include "atom.h" #include "memory.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NeighRequest::NeighRequest(LAMMPS *lmp) : Pointers(lmp) { // default ID = 0 id = 0; // class user of list: default is pair request // only one is set to 1 pair = 1; fix = compute = command = neigh = 0; // kind of list: default is half neighbor list // only one is set to 1 half = 1; full = 0; // attribute flags, mutiple can be set to 1 // default is every reneighboring, not occasional // default is use newton_pair setting in force // default is no neighbors of ghosts // default is use cutoffs, not size of particles // default is no associated neighbor history info in FixNeighHistory // default is no one-sided sphere/surface interactions (when size = 1) // default is neighbors of atoms, not bonds // default is no multilevel rRESPA neighbors // default is no OpenMP multi-threaded neighbor list build // default is no Intel-specific neighbor list build // default is no Kokkos neighbor list build // default is no Shardlow Splitting Algorithm (SSA) neighbor list build // default is no list-specific cutoff // default is no storage of auxiliary floating point values occasional = 0; newton = 0; ghost = 0; size = 0; history = 0; granonesided = 0; respainner = respamiddle = respaouter = 0; bond = 0; omp = 0; intel = 0; kokkos_host = kokkos_device = 0; ssa = 0; cut = 0; cutoff = 0.0; // skip info, default is no skipping skip = 0; iskip = NULL; ijskip = NULL; // only set when command = 1; command_style = NULL; // info set by Neighbor class when morphing original requests skiplist = -1; off2on = 0; copy = 0; copylist = -1; halffull = 0; halffulllist = -1; - respaouterlist = -1; - respamiddlelist = -1; - respainnerlist = -1; unique = 0; // internal settings index_bin = index_stencil = index_pair = -1; } /* ---------------------------------------------------------------------- */ NeighRequest::~NeighRequest() { delete [] iskip; memory->destroy(ijskip); } /* ---------------------------------------------------------------------- compare this request to other request identical means requestor identity and all params it sets are the same do not check other params that Neighbor can change after requests are made return 1 if identical, 0 if not ------------------------------------------------------------------------- */ int NeighRequest::identical(NeighRequest *other) { int same = 1; // check for match of requestor_instance and instance counter // prevents an old fix from being unfix/refix in same memory location // stored in requestor, and thus appearing old, when really new // only needed for classes with persistent neigh lists: Pair, Fix, Compute if (requestor != other->requestor) same = 0; if (requestor_instance != other->requestor_instance) same = 0; if (id != other->id) same = 0; // only compare settings made by requestors // not settings made later by Neighbor class if (pair != other->pair) same = 0; if (fix != other->fix) same = 0; if (compute != other->compute) same = 0; if (command != other->command) same = 0; if (neigh != other->neigh) same = 0; if (half != other->half) same = 0; if (full != other->full) same = 0; if (occasional != other->occasional) same = 0; if (newton != other->newton) same = 0; if (ghost != other->ghost) same = 0; if (size != other->size) same = 0; if (history != other->history) same = 0; if (granonesided != other->granonesided) same = 0; if (respainner != other->respainner) same = 0; if (respamiddle != other->respamiddle) same = 0; if (respaouter != other->respaouter) same = 0; if (bond != other->bond) same = 0; if (omp != other->omp) same = 0; if (intel != other->intel) same = 0; if (kokkos_host != other->kokkos_host) same = 0; if (kokkos_device != other->kokkos_device) same = 0; if (ssa != other->ssa) same = 0; if (copy != other->copy) same = 0; if (cutoff != other->cutoff) same = 0; if (skip != other->skip) same = 0; if (skip) same = same_skip(other); return same; } /* ---------------------------------------------------------------------- compare same info for two requests that have skip = 1 return 1 if identical, 0 if not ------------------------------------------------------------------------- */ int NeighRequest::same_skip(NeighRequest *other) { int i,j; int ntypes = atom->ntypes; int same = 1; for (i = 1; i <= ntypes; i++) if (iskip[i] != other->iskip[i]) same = 0; for (i = 1; i <= ntypes; i++) for (j = 1; j <= ntypes; j++) if (ijskip[i][j] != other->ijskip[i][j]) same = 0; return same; } /* ---------------------------------------------------------------------- set params in this request to those of other request copy same fields that are checked in identical() purpose is to allow comparison of new requests to old requests skipflag = 1 to copy skip vector/array ------------------------------------------------------------------------- */ void NeighRequest::copy_request(NeighRequest *other, int skipflag) { requestor = other->requestor; requestor_instance = other->requestor_instance; id = other->id; pair = other->pair; fix = other->fix; compute = other->compute; command = other->command; half = other->half; full = other->full; occasional = other->occasional; newton = other->newton; ghost = other->ghost; size = other->size; history = other->history; granonesided = other->granonesided; respainner = other->respainner; respamiddle = other->respamiddle; respaouter = other->respaouter; bond = other->bond; omp = other->omp; intel = other->intel; kokkos_host = other->kokkos_host; kokkos_device = other->kokkos_device; ssa = other->ssa; cut = other->cut; cutoff = other->cutoff; iskip = NULL; ijskip = NULL; if (!skipflag) return; int i,j; int ntypes = atom->ntypes; if (other->iskip) { iskip = new int[ntypes+1]; for (i = 1; i <= ntypes; i++) iskip[i] = other->iskip[i]; } if (other->ijskip) { memory->create(ijskip,ntypes+1,ntypes+1,"neigh_request:ijskip"); for (i = 1; i <= ntypes; i++) for (j = 1; j <= ntypes; j++) ijskip[i][j] = other->ijskip[i][j]; } } diff --git a/src/neigh_request.h b/src/neigh_request.h index 615b60dfe..16e6f1a8c 100644 --- a/src/neigh_request.h +++ b/src/neigh_request.h @@ -1,132 +1,124 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifndef LMP_NEIGH_REQUEST_H #define LMP_NEIGH_REQUEST_H #include "pointers.h" namespace LAMMPS_NS { class NeighRequest : protected Pointers { public: int index; // index of which neigh request this is void *requestor; // class that made request int requestor_instance; // instance of that class (only Fix, Compute, Pair) int id; // ID of request as stored by requestor // used to track multiple requests from one class // ----------------------------- // flags set by requesting class for attributes of neighor list they need // all must be set appropriately, all have defaults // ----------------------------- // which class style requests the list // one flag is 1, others are 0 int pair; // pair is set by default int fix; int compute; int command; int neigh; // half/full setting, determines which neighbors appear in list // one flag is 1, other is 0 int half; // half neigh list (set by default) int full; // full neigh list // attribute flags, all are 0 by default int occasional; // how often list is built // 0 if needed every reneighboring during run // 1 if only occasionally needed by a fix, compute, etc int newton; // which owned/ghost pairs appear in list // 0 if use force::newton_pair setting // 1 if override with pair newton on // 2 if override with pair newton off int ghost; // 1 if includes ghost atom neighbors int size; // 1 if pair cutoff set by particle radius int history; // 1 if there is also neigh history info (FixNeighHist) int granonesided; // 1 if one-sided granular list for // sphere/surf interactions - int respainner; // 1 if a rRESPA inner list - int respamiddle; // 1 if a rRESPA middle list - int respaouter; // 1 if a rRESPA outer list + int respainner; // 1 if need a rRESPA inner list + int respamiddle; // 1 if need a rRESPA middle list + int respaouter; // 1 if need a rRESPA outer list int bond; // 1 if store bond neighbors instead of atom neighs int omp; // set by USER-OMP package int intel; // set by USER-INTEL package int kokkos_host; // set by KOKKOS package int kokkos_device; int ssa; // set by USER-DPD package, for Shardlow lists int cut; // 1 if use a non-standard cutoff length double cutoff; // special cutoff distance for this list // flags set by pair hybrid int skip; // 1 if this list skips atom types from another list int *iskip; // iskip[i] if atoms of type I are not in list int **ijskip; // ijskip[i][j] if pairs of type I,J are not in list // command_style only set if command = 1 // allows print_pair_info() to access command name const char *command_style; // ----------------------------- // flags set by Neighbor class to morph original requests // ----------------------------- int skiplist; // index of list to skip from int off2on; // 1 if this is newton on list, but skips from off list int copy; // 1 if this list copied from another list int copylist; // index of list to copy from int halffull; // 1 if half list computed from another full list int halffulllist; // index of full list to derive half from - int respaouterlist; // index of respaouter/middle/inner lists - int respamiddlelist; // which this rREPSA list is associated with - int respainnerlist; // each rRESPA style list points at the others - int unique; // 1 if this list requires its own // NStencil, Nbin class - because of requestor cutoff - // pointer to FSH class, set by requestor class (not by Neighbor) - - class FixShearHistory *fix_history; // fix that stores per-atom history info - // ----------------------------- // internal settings made by Neighbor class // ----------------------------- int index_bin; // index of NBin class assigned to this request int index_stencil; // index of NStencil class assigned to this request int index_pair; // index of NPair class assigned to this request // methods NeighRequest(class LAMMPS *); ~NeighRequest(); void archive(); int identical(NeighRequest *); int same_skip(NeighRequest *); void copy_request(NeighRequest *, int); }; } #endif diff --git a/src/neighbor.cpp b/src/neighbor.cpp index 2d3ed0990..cc2e5d6d1 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -1,2433 +1,2400 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author (triclinic and multi-neigh) : Pieter in 't Veld (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "nbin.h" #include "nstencil.h" #include "npair.h" #include "ntopo.h" #include "style_nbin.h" #include "style_nstencil.h" #include "style_npair.h" #include "style_ntopo.h" #include "atom.h" #include "atom_vec.h" #include "comm.h" #include "force.h" #include "pair.h" #include "domain.h" #include "group.h" #include "modify.h" #include "fix.h" #include "compute.h" #include "update.h" #include "respa.h" #include "output.h" #include "citeme.h" #include "memory.h" #include "error.h" #include using namespace LAMMPS_NS; using namespace NeighConst; #define RQDELTA 1 #define EXDELTA 1 #define BIG 1.0e20 enum{NSQ,BIN,MULTI}; // also in NBin, NeighList, NStencil enum{NONE,ALL,PARTIAL,TEMPLATE}; static const char cite_neigh_multi[] = "neighbor multi command:\n\n" "@Article{Intveld08,\n" " author = {P.{\\,}J.~in{\\,}'t~Veld and S.{\\,}J.~Plimpton" " and G.{\\,}S.~Grest},\n" " title = {Accurate and Efficient Methods for Modeling Colloidal\n" " Mixtures in an Explicit Solvent using Molecular Dynamics},\n" " journal = {Comp.~Phys.~Comm.},\n" " year = 2008,\n" " volume = 179,\n" " pages = {320--329}\n" "}\n\n"; //#define NEIGH_LIST_DEBUG 1 /* ---------------------------------------------------------------------- */ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp), pairclass(NULL), pairnames(NULL), pairmasks(NULL) { MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); firsttime = 1; style = BIN; every = 1; delay = 10; dist_check = 1; pgsize = 100000; oneatom = 2000; binsizeflag = 0; build_once = 0; cluster_check = 0; ago = -1; cutneighmax = 0.0; cutneighsq = NULL; cutneighghostsq = NULL; cuttype = NULL; cuttypesq = NULL; fixchecklist = NULL; // pairwise neighbor lists and associated data structs nlist = 0; lists = NULL; nbin = 0; neigh_bin = NULL; nstencil = 0; neigh_stencil = NULL; neigh_pair = NULL; nstencil_perpetual = 0; slist = NULL; npair_perpetual = 0; plist = NULL; nrequest = maxrequest = 0; requests = NULL; old_nrequest = 0; old_requests = NULL; old_style = style; old_triclinic = 0; old_pgsize = pgsize; old_oneatom = oneatom; binclass = NULL; binnames = NULL; binmasks = NULL; stencilclass = NULL; stencilnames = NULL; stencilmasks = NULL; // topology lists bondwhich = anglewhich = dihedralwhich = improperwhich = NONE; neigh_bond = NULL; neigh_angle = NULL; neigh_dihedral = NULL; neigh_improper = NULL; // coords at last neighboring maxhold = 0; xhold = NULL; lastcall = -1; last_setup_bins = -1; // pair exclusion list info includegroup = 0; nex_type = maxex_type = 0; ex1_type = ex2_type = NULL; ex_type = NULL; nex_group = maxex_group = 0; ex1_group = ex2_group = ex1_bit = ex2_bit = NULL; nex_mol = maxex_mol = 0; ex_mol_group = ex_mol_bit = ex_mol_intra = NULL; // Kokkos setting copymode = 0; } /* ---------------------------------------------------------------------- */ Neighbor::~Neighbor() { if (copymode) return; memory->destroy(cutneighsq); memory->destroy(cutneighghostsq); delete [] cuttype; delete [] cuttypesq; delete [] fixchecklist; for (int i = 0; i < nlist; i++) delete lists[i]; for (int i = 0; i < nbin; i++) delete neigh_bin[i]; for (int i = 0; i < nstencil; i++) delete neigh_stencil[i]; for (int i = 0; i < nlist; i++) delete neigh_pair[i]; delete [] lists; delete [] neigh_bin; delete [] neigh_stencil; delete [] neigh_pair; delete [] slist; delete [] plist; for (int i = 0; i < nrequest; i++) if (requests[i]) delete requests[i]; memory->sfree(requests); for (int i = 0; i < old_nrequest; i++) if (old_requests[i]) delete old_requests[i]; memory->sfree(old_requests); delete [] binclass; delete [] binnames; delete [] binmasks; delete [] stencilclass; delete [] stencilnames; delete [] stencilmasks; delete [] pairclass; delete [] pairnames; delete [] pairmasks; delete neigh_bond; delete neigh_angle; delete neigh_dihedral; delete neigh_improper; memory->destroy(xhold); memory->destroy(ex1_type); memory->destroy(ex2_type); memory->destroy(ex_type); memory->destroy(ex1_group); memory->destroy(ex2_group); delete [] ex1_bit; delete [] ex2_bit; memory->destroy(ex_mol_group); delete [] ex_mol_bit; memory->destroy(ex_mol_intra); } /* ---------------------------------------------------------------------- */ void Neighbor::init() { int i,j,n; ncalls = ndanger = 0; dimension = domain->dimension; triclinic = domain->triclinic; newton_pair = force->newton_pair; // error check if (delay > 0 && (delay % every) != 0) error->all(FLERR,"Neighbor delay must be 0 or multiple of every setting"); if (pgsize < 10*oneatom) error->all(FLERR,"Neighbor page size must be >= 10x the one atom setting"); // ------------------------------------------------------------------ // settings // bbox lo/hi ptrs = bounding box of entire domain, stored by Domain if (triclinic == 0) { bboxlo = domain->boxlo; bboxhi = domain->boxhi; } else { bboxlo = domain->boxlo_bound; bboxhi = domain->boxhi_bound; } // set neighbor cutoffs (force cutoff + skin) // trigger determines when atoms migrate and neighbor lists are rebuilt // needs to be non-zero for migration distance check // even if pair = NULL and no neighbor lists are used // cutneigh = force cutoff + skin if cutforce > 0, else cutneigh = 0 // cutneighghost = pair cutghost if it requests it, else same as cutneigh triggersq = 0.25*skin*skin; boxcheck = 0; if (domain->box_change && (domain->xperiodic || domain->yperiodic || (dimension == 3 && domain->zperiodic))) boxcheck = 1; n = atom->ntypes; if (cutneighsq == NULL) { if (lmp->kokkos) init_cutneighsq_kokkos(n); else memory->create(cutneighsq,n+1,n+1,"neigh:cutneighsq"); memory->create(cutneighghostsq,n+1,n+1,"neigh:cutneighghostsq"); cuttype = new double[n+1]; cuttypesq = new double[n+1]; } double cutoff,delta,cut; cutneighmin = BIG; cutneighmax = 0.0; for (i = 1; i <= n; i++) { cuttype[i] = cuttypesq[i] = 0.0; for (j = 1; j <= n; j++) { if (force->pair) cutoff = sqrt(force->pair->cutsq[i][j]); else cutoff = 0.0; if (cutoff > 0.0) delta = skin; else delta = 0.0; cut = cutoff + delta; cutneighsq[i][j] = cut*cut; cuttype[i] = MAX(cuttype[i],cut); cuttypesq[i] = MAX(cuttypesq[i],cut*cut); cutneighmin = MIN(cutneighmin,cut); cutneighmax = MAX(cutneighmax,cut); if (force->pair && force->pair->ghostneigh) { cut = force->pair->cutghost[i][j] + skin; cutneighghostsq[i][j] = cut*cut; } else cutneighghostsq[i][j] = cut*cut; } } cutneighmaxsq = cutneighmax * cutneighmax; // rRESPA cutoffs int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; } if (respa) { double *cut_respa = ((Respa *) update->integrate)->cutoff; cut_inner_sq = (cut_respa[1] + skin) * (cut_respa[1] + skin); cut_middle_sq = (cut_respa[3] + skin) * (cut_respa[3] + skin); cut_middle_inside_sq = (cut_respa[0] - skin) * (cut_respa[0] - skin); if (cut_respa[0]-skin < 0) cut_middle_inside_sq = 0.0; } // fixchecklist = other classes that can induce reneighboring in decide() restart_check = 0; if (output->restart_flag) restart_check = 1; delete [] fixchecklist; fixchecklist = NULL; fixchecklist = new int[modify->nfix]; fix_check = 0; for (i = 0; i < modify->nfix; i++) if (modify->fix[i]->force_reneighbor) fixchecklist[fix_check++] = i; must_check = 0; if (restart_check || fix_check) must_check = 1; // set special_flag for 1-2, 1-3, 1-4 neighbors // flag[0] is not used, flag[1] = 1-2, flag[2] = 1-3, flag[3] = 1-4 // flag = 0 if both LJ/Coulomb special values are 0.0 // flag = 1 if both LJ/Coulomb special values are 1.0 // flag = 2 otherwise or if KSpace solver is enabled // pairwise portion of KSpace solver uses all 1-2,1-3,1-4 neighbors // or selected Coulomb-approixmation pair styles require it if (force->special_lj[1] == 0.0 && force->special_coul[1] == 0.0) special_flag[1] = 0; else if (force->special_lj[1] == 1.0 && force->special_coul[1] == 1.0) special_flag[1] = 1; else special_flag[1] = 2; if (force->special_lj[2] == 0.0 && force->special_coul[2] == 0.0) special_flag[2] = 0; else if (force->special_lj[2] == 1.0 && force->special_coul[2] == 1.0) special_flag[2] = 1; else special_flag[2] = 2; if (force->special_lj[3] == 0.0 && force->special_coul[3] == 0.0) special_flag[3] = 0; else if (force->special_lj[3] == 1.0 && force->special_coul[3] == 1.0) special_flag[3] = 1; else special_flag[3] = 2; if (force->kspace || force->pair_match("coul/wolf",0) || force->pair_match("coul/dsf",0) || force->pair_match("thole",0)) special_flag[1] = special_flag[2] = special_flag[3] = 2; // maxwt = max multiplicative factor on atom indices stored in neigh list maxwt = 0; if (special_flag[1] == 2) maxwt = 2; if (special_flag[2] == 2) maxwt = 3; if (special_flag[3] == 2) maxwt = 4; // ------------------------------------------------------------------ // xhold array // free if not needed for this run if (dist_check == 0) { memory->destroy(xhold); maxhold = 0; xhold = NULL; } // first time allocation if (dist_check) { if (maxhold == 0) { maxhold = atom->nmax; memory->create(xhold,maxhold,3,"neigh:xhold"); } } // ------------------------------------------------------------------ // exclusion lists // depend on type, group, molecule settings from neigh_modify // warn if exclusions used with KSpace solver n = atom->ntypes; if (nex_type == 0 && nex_group == 0 && nex_mol == 0) exclude = 0; else exclude = 1; if (nex_type) { if (lmp->kokkos) init_ex_type_kokkos(n); else { memory->destroy(ex_type); memory->create(ex_type,n+1,n+1,"neigh:ex_type"); } for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) ex_type[i][j] = 0; for (i = 0; i < nex_type; i++) { if (ex1_type[i] <= 0 || ex1_type[i] > n || ex2_type[i] <= 0 || ex2_type[i] > n) error->all(FLERR,"Invalid atom type in neighbor exclusion list"); ex_type[ex1_type[i]][ex2_type[i]] = 1; ex_type[ex2_type[i]][ex1_type[i]] = 1; } } if (nex_group) { if (lmp->kokkos) init_ex_bit_kokkos(); else { delete [] ex1_bit; delete [] ex2_bit; ex1_bit = new int[nex_group]; ex2_bit = new int[nex_group]; } for (i = 0; i < nex_group; i++) { ex1_bit[i] = group->bitmask[ex1_group[i]]; ex2_bit[i] = group->bitmask[ex2_group[i]]; } } if (nex_mol) { if (lmp->kokkos) init_ex_mol_bit_kokkos(); else { delete [] ex_mol_bit; ex_mol_bit = new int[nex_mol]; } for (i = 0; i < nex_mol; i++) ex_mol_bit[i] = group->bitmask[ex_mol_group[i]]; } if (exclude && force->kspace && me == 0) error->warning(FLERR,"Neighbor exclusions used with KSpace solver " "may give inconsistent Coulombic energies"); // ------------------------------------------------------------------ // create pairwise lists // one-time call to init_styles() to scan style files and setup // init_pair() creates auxiliary classes: NBin, NStencil, NPair if (firsttime) init_styles(); firsttime = 0; int same = init_pair(); // invoke copy_neighbor_info() in Bin,Stencil,Pair classes // copied once per run in case any cutoff, exclusion, special info changed for (i = 0; i < nbin; i++) neigh_bin[i]->copy_neighbor_info(); for (i = 0; i < nstencil; i++) neigh_stencil[i]->copy_neighbor_info(); for (i = 0; i < nlist; i++) if (neigh_pair[i]) neigh_pair[i]->copy_neighbor_info(); if (!same && comm->me == 0) print_pairwise_info(); // can now delete requests so next run can make new ones // print_pairwise_info() made use of requests // set of NeighLists now stores all needed info for (int i = 0; i < nrequest; i++) { delete requests[i]; requests[i] = NULL; } nrequest = 0; // ------------------------------------------------------------------ // create topology lists // instantiated topo styles can change from run to run init_topology(); } /* ---------------------------------------------------------------------- create and initialize lists of Nbin, Nstencil, NPair classes lists have info on all classes in 3 style*.h files cannot do this in constructor, b/c too early to instantiate classes ------------------------------------------------------------------------- */ void Neighbor::init_styles() { // extract info from NBin classes listed in style_nbin.h nbclass = 0; #define NBIN_CLASS #define NBinStyle(key,Class,bitmasks) nbclass++; #include "style_nbin.h" #undef NBinStyle #undef NBIN_CLASS binclass = new BinCreator[nbclass]; binnames = new char*[nbclass]; binmasks = new int[nbclass]; nbclass = 0; #define NBIN_CLASS #define NBinStyle(key,Class,bitmasks) \ binnames[nbclass] = (char *) #key; \ binclass[nbclass] = &bin_creator; \ binmasks[nbclass++] = bitmasks; #include "style_nbin.h" #undef NBinStyle #undef NBIN_CLASS // extract info from NStencil classes listed in style_nstencil.h nsclass = 0; #define NSTENCIL_CLASS #define NStencilStyle(key,Class,bitmasks) nsclass++; #include "style_nstencil.h" #undef NStencilStyle #undef NSTENCIL_CLASS stencilclass = new StencilCreator[nsclass]; stencilnames = new char*[nsclass]; stencilmasks = new int[nsclass]; nsclass = 0; #define NSTENCIL_CLASS #define NStencilStyle(key,Class,bitmasks) \ stencilnames[nsclass] = (char *) #key; \ stencilclass[nsclass] = &stencil_creator; \ stencilmasks[nsclass++] = bitmasks; #include "style_nstencil.h" #undef NStencilStyle #undef NSTENCIL_CLASS // extract info from NPair classes listed in style_npair.h npclass = 0; #define NPAIR_CLASS #define NPairStyle(key,Class,bitmasks) npclass++; #include "style_npair.h" #undef NPairStyle #undef NPAIR_CLASS pairclass = new PairCreator[npclass]; pairnames = new char*[npclass]; pairmasks = new int[npclass]; npclass = 0; #define NPAIR_CLASS #define NPairStyle(key,Class,bitmasks) \ pairnames[npclass] = (char *) #key; \ pairclass[npclass] = &pair_creator; \ pairmasks[npclass++] = bitmasks; #include "style_npair.h" #undef NPairStyle #undef NPAIR_CLASS } /* ---------------------------------------------------------------------- create and initialize NPair classes ------------------------------------------------------------------------- */ int Neighbor::init_pair() { int i,j,k,m; // test if pairwise lists need to be re-created // no need to re-create if: // neigh style, triclinic, pgsize, oneatom have not changed // current requests = old requests // so just return: // delete requests so next run can make new ones // current set of NeighLists already stores all needed info // requests are compared via identical() before: // any requests are morphed using logic below // any requests are added below, e.g. as parents of pair hybrid skip lists // copy them via requests_new2old() BEFORE any changes made to requests // necessary b/c morphs can change requestor settings (see comment below) int same = 1; if (style != old_style) same = 0; if (triclinic != old_triclinic) same = 0; if (pgsize != old_pgsize) same = 0; if (oneatom != old_oneatom) same = 0; if (nrequest != old_nrequest) same = 0; else for (i = 0; i < nrequest; i++) if (requests[i]->identical(old_requests[i]) == 0) same = 0; #ifdef NEIGH_LIST_DEBUG if (comm->me == 0) printf("SAME flag %d\n",same); #endif if (same) return same; requests_new2old(); // delete old lists since creating new ones for (i = 0; i < nlist; i++) delete lists[i]; for (i = 0; i < nbin; i++) delete neigh_bin[i]; for (i = 0; i < nstencil; i++) delete neigh_stencil[i]; for (i = 0; i < nlist; i++) delete neigh_pair[i]; delete [] lists; delete [] neigh_bin; delete [] neigh_stencil; delete [] neigh_pair; // error check on requests // do not allow occasional, ghost, bin list // b/c it still uses variant of coord2bin() in NPair() method // instead of atom2bin, this could cause error b/c stoms have // moved out of proc domain by time occasional list is built // solution would be to use a different NBin variant // that used Npair::coord2bin(x,ix,iy,iz) (then delete it from NPair) // and stored the ix,iy,iz values for all atoms (including ghosts) // at time of binning when neighbor lists are rebuilt, // similar to what vanilla Nbin::coord2atom() does now in atom2bin if (style == BIN) { for (i = 0; i < nrequest; i++) if (requests[i]->occasional && requests[i]->ghost) error->all(FLERR,"Cannot request an occasional binned neighbor list " "with ghost info"); } // morph requests in various ways // purpose is to avoid duplicate or inefficient builds // may add new requests if a needed request to derive from does not exist // methods: - // (1) other = point rRESPA lists at their partner lists + // (1) unique = create unique lists if cutoff is explicitly set // (2) skip = create any new non-skip lists needed by pair hybrid skip lists // (3) granular = adjust parent and skip lists for granular onesided usage // (4) h/f = pair up any matching half/full lists // (5) copy = convert as many lists as possible to copy lists // order of morph methods matters: // (3) after (2), b/c it adjusts lists created by (2) // (4) after (2) and (3), // b/c (2) may create new full lists, (3) may change them // (5) last, after all lists are finalized, so all possible copies found int nrequest_original = nrequest; - morph_other(); + morph_unique(); morph_skip(); morph_granular(); // this method can change flags set by requestor morph_halffull(); morph_copy(); // create new lists, one per request including added requests // wait to allocate initial pages until copy lists are detected // NOTE: can I allocate now, instead of down below? nlist = nrequest; lists = new NeighList*[nrequest]; neigh_bin = new NBin*[nrequest]; neigh_stencil = new NStencil*[nrequest]; neigh_pair = new NPair*[nrequest]; // allocate new lists // pass list ptr back to requestor (except for Command class) // only for original requests, not ones added by Neighbor class for (i = 0; i < nrequest; i++) { if (requests[i]->kokkos_host || requests[i]->kokkos_device) create_kokkos_list(i); else lists[i] = new NeighList(lmp); lists[i]->index = i; if (requests[i]->pair && i < nrequest_original) { Pair *pair = (Pair *) requests[i]->requestor; pair->init_list(requests[i]->id,lists[i]); } else if (requests[i]->fix && i < nrequest_original) { Fix *fix = (Fix *) requests[i]->requestor; fix->init_list(requests[i]->id,lists[i]); } else if (requests[i]->compute && i < nrequest_original) { Compute *compute = (Compute *) requests[i]->requestor; compute->init_list(requests[i]->id,lists[i]); } } // invoke post_constructor() for all lists // copies info from requests to lists, sets ptrs to related lists for (i = 0; i < nrequest; i++) lists[i]->post_constructor(requests[i]); // assign Bin,Stencil,Pair style to each list int flag; for (i = 0; i < nrequest; i++) { flag = choose_bin(requests[i]); lists[i]->bin_method = flag; if (flag < 0) error->all(FLERR,"Requested neighbor bin option does not exist"); flag = choose_stencil(requests[i]); lists[i]->stencil_method = flag; if (flag < 0) error->all(FLERR,"Requested neighbor stencil method does not exist"); flag = choose_pair(requests[i]); lists[i]->pair_method = flag; if (flag < 0) error->all(FLERR,"Requested neighbor pair method does not exist"); } // instantiate unique Bin,Stencil classes in neigh_bin & neigh_stencil vecs // unique = only one of its style, or request unique flag set (custom cutoff) nbin = 0; for (i = 0; i < nrequest; i++) { requests[i]->index_bin = -1; flag = lists[i]->bin_method; if (flag == 0) continue; for (j = 0; j < nbin; j++) if (neigh_bin[j]->istyle == flag) break; if (j < nbin && !requests[i]->unique) { requests[i]->index_bin = j; continue; } BinCreator bin_creator = binclass[flag-1]; neigh_bin[nbin] = bin_creator(lmp); neigh_bin[nbin]->post_constructor(requests[i]); neigh_bin[nbin]->istyle = flag; requests[i]->index_bin = nbin; nbin++; } nstencil = 0; for (i = 0; i < nrequest; i++) { requests[i]->index_stencil = -1; flag = lists[i]->stencil_method; if (flag == 0) continue; for (j = 0; j < nstencil; j++) if (neigh_stencil[j]->istyle == flag) break; if (j < nstencil && !requests[i]->unique) { requests[i]->index_stencil = j; continue; } StencilCreator stencil_creator = stencilclass[flag-1]; neigh_stencil[nstencil] = stencil_creator(lmp); neigh_stencil[nstencil]->post_constructor(requests[i]); neigh_stencil[nstencil]->istyle = flag; if (lists[i]->bin_method > 0) { neigh_stencil[nstencil]->nb = neigh_bin[requests[i]->index_bin]; if (neigh_stencil[nstencil]->nb == NULL) error->all(FLERR,"Could not assign bin method to neighbor stencil"); } requests[i]->index_stencil = nstencil; nstencil++; } // instantiate one Pair class per list in neigh_pair vec for (i = 0; i < nrequest; i++) { requests[i]->index_pair = -1; flag = lists[i]->pair_method; if (flag == 0) { neigh_pair[i] = NULL; continue; } PairCreator pair_creator = pairclass[flag-1]; lists[i]->np = neigh_pair[i] = pair_creator(lmp); neigh_pair[i]->post_constructor(requests[i]); neigh_pair[i]->istyle = flag; if (lists[i]->bin_method > 0) { neigh_pair[i]->nb = neigh_bin[requests[i]->index_bin]; if (neigh_pair[i]->nb == NULL) error->all(FLERR,"Could not assign bin method to neighbor pair"); } if (lists[i]->stencil_method > 0) { neigh_pair[i]->ns = neigh_stencil[requests[i]->index_stencil]; if (neigh_pair[i]->ns == NULL) error->all(FLERR,"Could not assign stencil method to neighbor pair"); } requests[i]->index_pair = i; } // allocate initial pages for each list, except if copy flag set for (i = 0; i < nlist; i++) { if (lists[i]->copy) continue; lists[i]->setup_pages(pgsize,oneatom); } // first-time allocation of per-atom data for lists that are built and store - // lists that are not built: respa inner/middle (no neigh_pair) // lists that do not store: copy // use atom->nmax for both grow() args // i.e. grow first time to expanded size to avoid future reallocs // also Kokkos list initialization int maxatom = atom->nmax; for (i = 0; i < nlist; i++) if (neigh_pair[i] && !lists[i]->copy) lists[i]->grow(maxatom,maxatom); // plist = indices of perpetual NPair classes // perpetual = non-occasional, re-built at every reneighboring // slist = indices of perpetual NStencil classes // perpetual = used by any perpetual NPair class delete [] slist; delete [] plist; nstencil_perpetual = npair_perpetual = 0; slist = new int[nstencil]; plist = new int[nlist]; for (i = 0; i < nlist; i++) { if (lists[i]->occasional == 0 && lists[i]->pair_method) plist[npair_perpetual++] = i; } for (i = 0; i < nstencil; i++) { flag = 0; for (j = 0; j < npair_perpetual; j++) if (lists[plist[j]]->stencil_method == neigh_stencil[i]->istyle) flag = 1; if (flag) slist[nstencil_perpetual++] = i; } // reorder plist vector if necessary // relevant for lists that are derived from a parent list: // half-full,copy,skip // the child index must appear in plist after the parent index // swap two indices within plist when dependency is mis-ordered // start double loop check again whenever a swap is made // done when entire double loop test results in no swaps NeighList *ptr; int done = 0; while (!done) { done = 1; for (i = 0; i < npair_perpetual; i++) { for (k = 0; k < 3; k++) { ptr = NULL; if (k == 0) ptr = lists[plist[i]]->listcopy; if (k == 1) ptr = lists[plist[i]]->listskip; if (k == 2) ptr = lists[plist[i]]->listfull; if (ptr == NULL) continue; for (m = 0; m < nrequest; m++) if (ptr == lists[m]) break; for (j = 0; j < npair_perpetual; j++) if (m == plist[j]) break; if (j < i) continue; int tmp = plist[i]; // swap I,J indices plist[i] = plist[j]; plist[j] = tmp; done = 0; break; } if (!done) break; } } // debug output #ifdef NEIGH_LIST_DEBUG for (i = 0; i < nrequest; i++) lists[i]->print_attributes(); #endif return same; } /* ---------------------------------------------------------------------- scan NeighRequests to set additional flags - only for respaouter, custom cutoff lists + only for custom cutoff lists ------------------------------------------------------------------------- */ -void Neighbor::morph_other() +void Neighbor::morph_unique() { NeighRequest *irq; for (int i = 0; i < nrequest; i++) { irq = requests[i]; - // if respaouter, point all associated rRESPA lists at each other - - if (irq->respaouter) { - if (requests[i-1]->respainner) { - irq->respainnerlist = i-1; - requests[i-1]->respaouterlist = i; - } else { - irq->respamiddlelist = i-1; - requests[i-1]->respaouterlist = i; - requests[i-1]->respainnerlist = i-1; - irq->respainnerlist = i-2; - requests[i-2]->respaouterlist = i; - requests[i-2]->respamiddlelist = i-1; - } - } - // if cut flag set by requestor, set unique flag // this forces Pair,Stencil,Bin styles to be instantiated separately if (irq->cut) irq->unique = 1; } } /* ---------------------------------------------------------------------- scan NeighRequests to process all skip lists look for a matching non-skip list if one exists, point at it via skiplist else make new parent via copy_request() and point at it ------------------------------------------------------------------------- */ void Neighbor::morph_skip() { int i,j,inewton,jnewton; NeighRequest *irq,*jrq,*nrq; for (i = 0; i < nrequest; i++) { irq = requests[i]; // only processing skip lists if (!irq->skip) continue; // these lists are created other ways, no need for skipping // halffull list and its full parent may both skip, // but are checked to insure matching skip info - if (irq->respainner || irq->respamiddle) continue; if (irq->halffull) continue; if (irq->copy) continue; // check all other lists for (j = 0; j < nrequest; j++) { if (i == j) continue; jrq = requests[j]; // can only skip from a perpetual non-skip list if (jrq->occasional) continue; if (jrq->skip) continue; // both lists must be half, or both full if (irq->half != jrq->half) continue; if (irq->full != jrq->full) continue; // both lists must be newton on, or both newton off // IJ newton = 1 for newton on, 2 for newton off inewton = irq->newton; if (inewton == 0) inewton = force->newton_pair ? 1 : 2; jnewton = jrq->newton; if (jnewton == 0) jnewton = force->newton_pair ? 1 : 2; if (inewton != jnewton) continue; // these flags must be same, // else 2 lists do not store same pairs // or their data structures are different // this includes custom cutoff set by requestor - // no need to check respaouter b/c it stores same pairs // NOTE: need check for 2 Kokkos flags? if (irq->ghost != jrq->ghost) continue; if (irq->size != jrq->size) continue; if (irq->history != jrq->history) continue; if (irq->bond != jrq->bond) continue; if (irq->omp != jrq->omp) continue; if (irq->intel != jrq->intel) continue; if (irq->kokkos_host != jrq->kokkos_host) continue; if (irq->kokkos_device != jrq->kokkos_device) continue; if (irq->ssa != jrq->ssa) continue; if (irq->cut != jrq->cut) continue; if (irq->cutoff != jrq->cutoff) continue; // 2 lists are a match break; } // if matching list exists, point to it // else create a new identical list except non-skip // for new list, set neigh = 1, skip = 0, no skip vec/array, // copy unique flag (since copy_request() will not do it) // note: parents of skip lists do not have associated history // b/c child skip lists have the associated history if (j < nrequest) irq->skiplist = j; else { int newrequest = request(this,-1); irq->skiplist = newrequest; nrq = requests[newrequest]; nrq->copy_request(irq,0); nrq->pair = nrq->fix = nrq->compute = nrq->command = 0; nrq->neigh = 1; nrq->skip = 0; if (irq->unique) nrq->unique = 1; } } } /* ---------------------------------------------------------------------- scan NeighRequests just added by morph_skip for hybrid granular adjust newton/oneside parent settings if children require onesided skipping also set children off2on flag if parent becomes a newton off list this is needed because line/gran and tri/gran pair styles require onesided neigh lists and system newton on, but parent list must be newton off to enable the onesided skipping ------------------------------------------------------------------------- */ void Neighbor::morph_granular() { int i,j; NeighRequest *irq,*jrq; for (i = 0; i < nrequest; i++) { irq = requests[i]; // only examine NeighRequests added by morph_skip() // only those with size attribute for granular systems if (!irq->neigh) continue; if (!irq->size) continue; // check children of this list int onesided = -1; for (j = 0; j < nrequest; j++) { jrq = requests[j]; // only consider JRQ pair, size lists that skip from Irq list if (!jrq->pair) continue; if (!jrq->size) continue; if (!jrq->skip || jrq->skiplist != i) continue; // onesided = -1 if no children // onesided = 0/1 = child granonesided value if same for all children // onesided = 2 if children have different granonesided values if (onesided < 0) onesided = jrq->granonesided; else if (onesided != jrq->granonesided) onesided = 2; if (onesided == 2) break; } // if onesided = 2, parent has children with both granonesided = 0/1 // force parent newton off (newton = 2) to enable onesided skip by child // set parent granonesided = 0, so it stores all neighs in usual manner // set off2on = 1 for all children, since they expect newton on lists // this is b/c granonesided only set by line/gran and tri/gran which // both require system newton on if (onesided == 2) { irq->newton = 2; irq->granonesided = 0; for (j = 0; j < nrequest; j++) { jrq = requests[j]; // only consider JRQ pair, size lists that skip from Irq list if (!jrq->pair) continue; if (!jrq->size) continue; if (!jrq->skip || jrq->skiplist != i) continue; jrq->off2on = 1; } } } } /* ---------------------------------------------------------------------- scan NeighRequests for possible half lists to derive from full lists if 2 requests match, set half list to derive from full list ------------------------------------------------------------------------- */ void Neighbor::morph_halffull() { int i,j; NeighRequest *irq,*jrq; for (i = 0; i < nrequest; i++) { irq = requests[i]; // only processing half lists if (!irq->half) continue; // Kokkos doesn't yet support half from full if (irq->kokkos_host) continue; if (irq->kokkos_device) continue; // these lists are created other ways, no need for halffull // do want to process skip lists - if (irq->respainner || irq->respamiddle) continue; if (irq->copy) continue; // check all other lists for (j = 0; j < nrequest; j++) { if (i == j) continue; jrq = requests[j]; // can only derive from a perpetual full list // newton setting of derived list does not matter if (jrq->occasional) continue; if (!jrq->full) continue; // these flags must be same, // else 2 lists do not store same pairs // or their data structures are different // this includes custom cutoff set by requestor - // no need to check respaouter b/c it stores same pairs if (irq->ghost != jrq->ghost) continue; if (irq->size != jrq->size) continue; if (irq->history != jrq->history) continue; if (irq->bond != jrq->bond) continue; if (irq->omp != jrq->omp) continue; if (irq->intel != jrq->intel) continue; if (irq->kokkos_host != jrq->kokkos_host) continue; if (irq->kokkos_device != jrq->kokkos_device) continue; if (irq->ssa != jrq->ssa) continue; if (irq->cut != jrq->cut) continue; if (irq->cutoff != jrq->cutoff) continue; // skip flag must be same // if both are skip lists, skip info must match if (irq->skip != jrq->skip) continue; if (irq->skip && irq->same_skip(jrq) == 0) continue; // 2 lists are a match break; } // if matching list exists, point to it if (j < nrequest) { irq->halffull = 1; irq->halffulllist = j; } } } /* ---------------------------------------------------------------------- scan NeighRequests for possible copies if 2 requests match, turn one into a copy of the other ------------------------------------------------------------------------- */ void Neighbor::morph_copy() { int i,j,inewton,jnewton; NeighRequest *irq,*jrq; for (i = 0; i < nrequest; i++) { irq = requests[i]; // this list is already a copy list due to another morph method if (irq->copy) continue; - // these lists are created other ways, no need to copy - // skip lists are eligible to become a copy list - - if (irq->respainner || irq->respamiddle) continue; - // check all other lists for (j = 0; j < nrequest; j++) { if (i == j) continue; jrq = requests[j]; // other list is already copied from this one if (jrq->copy && jrq->copylist == i) continue; // other list (jrq) to copy from must be perpetual // list that becomes a copy list (irq) can be perpetual or occasional // if both lists are perpetual, require j < i // to prevent circular dependence with 3 or more copies of a list if (jrq->occasional) continue; if (!irq->occasional && j > i) continue; // both lists must be half, or both full if (irq->half != jrq->half) continue; if (irq->full != jrq->full) continue; // both lists must be newton on, or both newton off // IJ newton = 1 for newton on, 2 for newton off inewton = irq->newton; if (inewton == 0) inewton = force->newton_pair ? 1 : 2; jnewton = jrq->newton; if (jnewton == 0) jnewton = force->newton_pair ? 1 : 2; if (inewton != jnewton) continue; // ok for non-ghost list to copy from ghost list, but not vice versa if (irq->ghost && !jrq->ghost) continue; - // do not copy from a respa middle/inner list + // do not copy from a list with respa middle/inner + // b/c its outer list will not be complete if (jrq->respamiddle) continue; if (jrq->respainner) continue; // these flags must be same, // else 2 lists do not store same pairs // or their data structures are different // this includes custom cutoff set by requestor - // no need to check respaouter b/c it stores same pairs // no need to check omp b/c it stores same pairs // NOTE: need check for 2 Kokkos flags? if (irq->size != jrq->size) continue; if (irq->history != jrq->history) continue; if (irq->bond != jrq->bond) continue; if (irq->intel != jrq->intel) continue; if (irq->kokkos_host != jrq->kokkos_host) continue; if (irq->kokkos_device != jrq->kokkos_device) continue; if (irq->ssa != jrq->ssa) continue; if (irq->cut != jrq->cut) continue; if (irq->cutoff != jrq->cutoff) continue; // skip flag must be same // if both are skip lists, skip info must match if (irq->skip != jrq->skip) continue; if (irq->skip && irq->same_skip(jrq) == 0) continue; // 2 lists are a match break; } // turn list I into a copy of list J // do not copy a list from another copy list, but from its parent list if (j < nrequest) { irq->copy = 1; if (jrq->copy) irq->copylist = jrq->copylist; else irq->copylist = j; } } } /* ---------------------------------------------------------------------- create and initialize NTopo classes ------------------------------------------------------------------------- */ void Neighbor::init_topology() { int i,m; if (!atom->molecular) return; // set flags that determine which topology neighbor classes to use // these settings could change from run to run, depending on fixes defined // bonds,etc can only be broken for atom->molecular = 1, not 2 // SHAKE sets bonds and angles negative // gcmc sets all bonds, angles, etc negative // bond_quartic sets bonds to 0 // delete_bonds sets all interactions negative int bond_off = 0; int angle_off = 0; for (i = 0; i < modify->nfix; i++) if ((strcmp(modify->fix[i]->style,"shake") == 0) || (strcmp(modify->fix[i]->style,"rattle") == 0)) bond_off = angle_off = 1; if (force->bond && force->bond_match("quartic")) bond_off = 1; if (atom->avec->bonds_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (bond_off) break; for (m = 0; m < atom->num_bond[i]; m++) if (atom->bond_type[i][m] <= 0) bond_off = 1; } } if (atom->avec->angles_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (angle_off) break; for (m = 0; m < atom->num_angle[i]; m++) if (atom->angle_type[i][m] <= 0) angle_off = 1; } } int dihedral_off = 0; if (atom->avec->dihedrals_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (dihedral_off) break; for (m = 0; m < atom->num_dihedral[i]; m++) if (atom->dihedral_type[i][m] <= 0) dihedral_off = 1; } } int improper_off = 0; if (atom->avec->impropers_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (improper_off) break; for (m = 0; m < atom->num_improper[i]; m++) if (atom->improper_type[i][m] <= 0) improper_off = 1; } } for (i = 0; i < modify->nfix; i++) if ((strcmp(modify->fix[i]->style,"gcmc") == 0)) bond_off = angle_off = dihedral_off = improper_off = 1; // sync on/off settings across all procs int onoff = bond_off; MPI_Allreduce(&onoff,&bond_off,1,MPI_INT,MPI_MAX,world); onoff = angle_off; MPI_Allreduce(&onoff,&angle_off,1,MPI_INT,MPI_MAX,world); onoff = dihedral_off; MPI_Allreduce(&onoff,&dihedral_off,1,MPI_INT,MPI_MAX,world); onoff = improper_off; MPI_Allreduce(&onoff,&improper_off,1,MPI_INT,MPI_MAX,world); // instantiate NTopo classes if (atom->avec->bonds_allow) { int old_bondwhich = bondwhich; if (atom->molecular == 2) bondwhich = TEMPLATE; else if (bond_off) bondwhich = PARTIAL; else bondwhich = ALL; if (!neigh_bond || bondwhich != old_bondwhich) { delete neigh_bond; if (bondwhich == ALL) neigh_bond = new NTopoBondAll(lmp); else if (bondwhich == PARTIAL) neigh_bond = new NTopoBondPartial(lmp); else if (bondwhich == TEMPLATE) neigh_bond = new NTopoBondTemplate(lmp); } } if (atom->avec->angles_allow) { int old_anglewhich = anglewhich; if (atom->molecular == 2) anglewhich = TEMPLATE; else if (angle_off) anglewhich = PARTIAL; else anglewhich = ALL; if (!neigh_angle || anglewhich != old_anglewhich) { delete neigh_angle; if (anglewhich == ALL) neigh_angle = new NTopoAngleAll(lmp); else if (anglewhich == PARTIAL) neigh_angle = new NTopoAnglePartial(lmp); else if (anglewhich == TEMPLATE) neigh_angle = new NTopoAngleTemplate(lmp); } } if (atom->avec->dihedrals_allow) { int old_dihedralwhich = dihedralwhich; if (atom->molecular == 2) dihedralwhich = TEMPLATE; else if (dihedral_off) dihedralwhich = PARTIAL; else dihedralwhich = ALL; if (!neigh_dihedral || dihedralwhich != old_dihedralwhich) { delete neigh_dihedral; if (dihedralwhich == ALL) neigh_dihedral = new NTopoDihedralAll(lmp); else if (dihedralwhich == PARTIAL) neigh_dihedral = new NTopoDihedralPartial(lmp); else if (dihedralwhich == TEMPLATE) neigh_dihedral = new NTopoDihedralTemplate(lmp); } } if (atom->avec->impropers_allow) { int old_improperwhich = improperwhich; if (atom->molecular == 2) improperwhich = TEMPLATE; else if (improper_off) improperwhich = PARTIAL; else improperwhich = ALL; if (!neigh_improper || improperwhich != old_improperwhich) { delete neigh_improper; if (improperwhich == ALL) neigh_improper = new NTopoImproperAll(lmp); else if (improperwhich == PARTIAL) neigh_improper = new NTopoImproperPartial(lmp); else if (improperwhich == TEMPLATE) neigh_improper = new NTopoImproperTemplate(lmp); } } } /* ---------------------------------------------------------------------- output summary of pairwise neighbor list info only called by proc 0 ------------------------------------------------------------------------- */ void Neighbor::print_pairwise_info() { int i,m; char str[128]; NeighRequest *rq; FILE *out; const double cutghost = MAX(cutneighmax,comm->cutghostuser); double binsize, bbox[3]; bbox[0] = bboxhi[0]-bboxlo[0]; bbox[1] = bboxhi[1]-bboxlo[1]; bbox[2] = bboxhi[2]-bboxlo[2]; if (binsizeflag) binsize = binsize_user; else if (style == BIN) binsize = 0.5*cutneighmax; else binsize = 0.5*cutneighmin; if (binsize == 0.0) binsize = bbox[0]; int nperpetual = 0; int noccasional = 0; int nextra = 0; for (i = 0; i < nlist; i++) { if (lists[i]->pair_method == 0) nextra++; else if (lists[i]->occasional) noccasional++; else nperpetual++; } for (m = 0; m < 2; m++) { if (m == 0) out = screen; else out = logfile; if (out) { fprintf(out,"Neighbor list info ...\n"); fprintf(out," update every %d steps, delay %d steps, check %s\n", every,delay,dist_check ? "yes" : "no"); fprintf(out," max neighbors/atom: %d, page size: %d\n", oneatom, pgsize); fprintf(out," master list distance cutoff = %g\n",cutneighmax); fprintf(out," ghost atom cutoff = %g\n",cutghost); if (style != NSQ) fprintf(out," binsize = %g, bins = %g %g %g\n",binsize, ceil(bbox[0]/binsize), ceil(bbox[1]/binsize), ceil(bbox[2]/binsize)); fprintf(out," %d neighbor lists, " "perpetual/occasional/extra = %d %d %d\n", nlist,nperpetual,noccasional,nextra); for (i = 0; i < nlist; i++) { rq = requests[i]; if (rq->pair) { char *pname = force->pair_match_ptr((Pair *) rq->requestor); sprintf(str," (%d) pair %s",i+1,pname); } else if (rq->fix) { sprintf(str," (%d) fix %s",i+1,((Fix *) rq->requestor)->style); } else if (rq->compute) { sprintf(str," (%d) compute %s",i+1, ((Compute *) rq->requestor)->style); } else if (rq->command) { sprintf(str," (%d) command %s",i+1,rq->command_style); } else if (rq->neigh) { sprintf(str," (%d) neighbor class addition",i+1); } fprintf(out,"%s",str); if (rq->occasional) fprintf(out,", occasional"); else fprintf(out,", perpetual"); // order these to get single output of most relevant if (rq->copy) fprintf(out,", copy from (%d)",rq->copylist+1); else if (rq->halffull) fprintf(out,", half/full from (%d)",rq->halffulllist+1); else if (rq->skip) fprintf(out,", skip from (%d)",rq->skiplist+1); fprintf(out,"\n"); // list of neigh list attributes fprintf(out," attributes: "); if (rq->half) fprintf(out,"half"); else if (rq->full) fprintf(out,"full"); if (rq->newton == 0) { if (force->newton_pair) fprintf(out,", newton on"); else fprintf(out,", newton off"); } else if (rq->newton == 1) fprintf(out,", newton on"); else if (rq->newton == 2) fprintf(out,", newton off"); if (rq->ghost) fprintf(out,", ghost"); if (rq->size) fprintf(out,", size"); if (rq->history) fprintf(out,", history"); if (rq->granonesided) fprintf(out,", onesided"); - if (rq->respainner) fprintf(out,", respa outer"); - if (rq->respamiddle) fprintf(out,", respa middle"); - if (rq->respaouter) fprintf(out,", respa inner"); + if (rq->respamiddle) fprintf(out,", respa outer/middle/inner"); + else if (rq->respainner) fprintf(out,", respa outer/inner"); if (rq->bond) fprintf(out,", bond"); if (rq->omp) fprintf(out,", omp"); if (rq->intel) fprintf(out,", intel"); if (rq->kokkos_device) fprintf(out,", kokkos_device"); if (rq->kokkos_host) fprintf(out,", kokkos_host"); if (rq->ssa) fprintf(out,", ssa"); if (rq->cut) fprintf(out,", cut %g",rq->cutoff); if (rq->off2on) fprintf(out,", off2on"); fprintf(out,"\n"); fprintf(out," "); if (lists[i]->pair_method == 0) fprintf(out,"pair build: none\n"); else fprintf(out,"pair build: %s\n",pairnames[lists[i]->pair_method-1]); fprintf(out," "); if (lists[i]->stencil_method == 0) fprintf(out,"stencil: none\n"); else fprintf(out,"stencil: %s\n", stencilnames[lists[i]->stencil_method-1]); fprintf(out," "); if (lists[i]->bin_method == 0) fprintf(out,"bin: none\n"); else fprintf(out,"bin: %s\n",binnames[lists[i]->bin_method-1]); } /* fprintf(out," %d stencil methods\n",nstencil); for (i = 0; i < nstencil; i++) fprintf(out," (%d) %s\n", i+1,stencilnames[neigh_stencil[i]->istyle-1]); fprintf(out," %d bin methods\n",nbin); for (i = 0; i < nbin; i++) fprintf(out," (%d) %s\n",i+1,binnames[neigh_bin[i]->istyle-1]); */ } } } /* ---------------------------------------------------------------------- make copy of current requests and Neighbor params used to compare to when next run occurs ------------------------------------------------------------------------- */ void Neighbor::requests_new2old() { for (int i = 0; i < old_nrequest; i++) delete old_requests[i]; memory->sfree(old_requests); old_nrequest = nrequest; old_requests = (NeighRequest **) memory->smalloc(old_nrequest*sizeof(NeighRequest *), "neighbor:old_requests"); for (int i = 0; i < old_nrequest; i++) { old_requests[i] = new NeighRequest(lmp); old_requests[i]->copy_request(requests[i],1); } old_style = style; old_triclinic = triclinic; old_pgsize = pgsize; old_oneatom = oneatom; } /* ---------------------------------------------------------------------- find and return request made by classptr if not found or classpt = NULL, return NULL ------------------------------------------------------------------------- */ NeighRequest *Neighbor::find_request(void *classptr) { if (classptr == NULL) return NULL; for (int i = 0; i < nrequest; i++) if (requests[i]->requestor == classptr) return requests[i]; return NULL; } /* ---------------------------------------------------------------------- assign NBin class to a NeighList use neigh request settings to build mask match mask to list of masks of known Nbin classes return index+1 of match in list of masks return 0 for no binning return -1 if no match ------------------------------------------------------------------------- */ int Neighbor::choose_bin(NeighRequest *rq) { // no binning needed if (style == NSQ) return 0; if (rq->skip || rq->copy || rq->halffull) return 0; - if (rq->respainner || rq->respamiddle) return 0; // use request settings to match exactly one NBin class mask // checks are bitwise using NeighConst bit masks int mask; for (int i = 0; i < nbclass; i++) { mask = binmasks[i]; // require match of these request flags and mask bits // (!A != !B) is effectively a logical xor if (!rq->intel != !(mask & NB_INTEL)) continue; if (!rq->ssa != !(mask & NB_SSA)) continue; if (!rq->kokkos_device != !(mask & NB_KOKKOS_DEVICE)) continue; if (!rq->kokkos_host != !(mask & NB_KOKKOS_HOST)) continue; return i+1; } // error return if matched none return -1; } /* ---------------------------------------------------------------------- assign NStencil class to a NeighList use neigh request settings to build mask match mask to list of masks of known NStencil classes return index+1 of match in list of masks return 0 for no binning return -1 if no match ------------------------------------------------------------------------- */ int Neighbor::choose_stencil(NeighRequest *rq) { // no stencil creation needed if (style == NSQ) return 0; if (rq->skip || rq->copy || rq->halffull) return 0; - if (rq->respainner || rq->respamiddle) return 0; // convert newton request to newtflag = on or off int newtflag; if (rq->newton == 0 && newton_pair) newtflag = 1; else if (rq->newton == 0 && !newton_pair) newtflag = 0; else if (rq->newton == 1) newtflag = 1; else if (rq->newton == 2) newtflag = 0; //printf("STENCIL RQ FLAGS: hff %d %d n %d g %d s %d newtflag %d\n", // rq->half,rq->full,rq->newton,rq->ghost,rq->ssa, // newtflag); // use request and system settings to match exactly one NStencil class mask // checks are bitwise using NeighConst bit masks int mask; for (int i = 0; i < nsclass; i++) { mask = stencilmasks[i]; //printf("III %d: half %d full %d newton %d newtoff %d ghost %d ssa %d\n", // i,mask & NS_HALF,mask & NS_FULL,mask & NS_NEWTON, // mask & NS_NEWTOFF,mask & NS_GHOST,mask & NS_SSA); // exactly one of half or full is set and must match if (rq->half) { if (!(mask & NS_HALF)) continue; } else if (rq->full) { if (!(mask & NS_FULL)) continue; } // newtflag is on or off and must match if (newtflag) { if (!(mask & NS_NEWTON)) continue; } else if (!newtflag) { if (!(mask & NS_NEWTOFF)) continue; } // require match of these request flags and mask bits // (!A != !B) is effectively a logical xor if (!rq->ghost != !(mask & NS_GHOST)) continue; if (!rq->ssa != !(mask & NS_SSA)) continue; // neighbor style is BIN or MULTI and must match if (style == BIN) { if (!(mask & NS_BIN)) continue; } else if (style == MULTI) { if (!(mask & NS_MULTI)) continue; } // dimension is 2 or 3 and must match if (dimension == 2) { if (!(mask & NS_2D)) continue; } else if (dimension == 3) { if (!(mask & NS_3D)) continue; } // domain triclinic flag is on or off and must match if (triclinic) { if (!(mask & NS_TRI)) continue; } else if (!triclinic) { if (!(mask & NS_ORTHO)) continue; } return i+1; } // error return if matched none return -1; } /* ---------------------------------------------------------------------- assign NPair class to a NeighList use neigh request settings to build mask match mask to list of masks of known NPair classes return index+1 of match in list of masks return 0 for no binning return -1 if no match ------------------------------------------------------------------------- */ int Neighbor::choose_pair(NeighRequest *rq) { - // no neighbor list build performed - - if (rq->respainner || rq->respamiddle) return 0; - // error check for includegroup with ghost neighbor request if (includegroup && rq->ghost) error->all(FLERR,"Neighbor include group not allowed with ghost neighbors"); // convert newton request to newtflag = on or off int newtflag; if (rq->newton == 0 && newton_pair) newtflag = 1; else if (rq->newton == 0 && !newton_pair) newtflag = 0; else if (rq->newton == 1) newtflag = 1; else if (rq->newton == 2) newtflag = 0; int molecular = atom->molecular; //printf("PAIR RQ FLAGS: hf %d %d n %d g %d sz %d gos %d r %d b %d o %d i %d " // "kk %d %d ss %d dn %d sk %d cp %d hf %d oo %d\n", // rq->half,rq->full,rq->newton,rq->ghost,rq->size, // rq->granonesided,rq->respaouter,rq->bond,rq->omp,rq->intel, // rq->kokkos_host,rq->kokkos_device,rq->ssa,rq->dnum, // rq->skip,rq->copy,rq->halffull,rq->off2on); // use request and system settings to match exactly one NPair class mask // checks are bitwise using NeighConst bit masks int mask; for (int i = 0; i < npclass; i++) { mask = pairmasks[i]; //printf(" PAIR NAMES i %d %d name %s mask %d\n",i,nrequest, // pairnames[i],pairmasks[i]); // if copy request, no further checks needed, just return or continue // Kokkos device/host flags must also match in order to copy if (rq->copy) { if (!(mask & NP_COPY)) continue; if (!rq->kokkos_device != !(mask & NP_KOKKOS_DEVICE)) continue; if (!rq->kokkos_host != !(mask & NP_KOKKOS_HOST)) continue; return i+1; } // exactly one of half or full is set and must match if (rq->half) { if (!(mask & NP_HALF)) continue; } else if (rq->full) { if (!(mask & NP_FULL)) continue; } // newtflag is on or off and must match if (newtflag) { if (!(mask & NP_NEWTON)) continue; } else if (!newtflag) { if (!(mask & NP_NEWTOFF)) continue; } // if molecular on, do not match ATOMONLY (b/c a MOLONLY Npair exists) // if molecular off, do not match MOLONLY (b/c an ATOMONLY Npair exists) if (molecular) { if (mask & NP_ATOMONLY) continue; } else if (!molecular) { if (mask & NP_MOLONLY) continue; } // require match of these request flags and mask bits // (!A != !B) is effectively a logical xor if (!rq->ghost != !(mask & NP_GHOST)) continue; if (!rq->size != !(mask & NP_SIZE)) continue; if (!rq->respaouter != !(mask & NP_RESPA)) continue; if (!rq->granonesided != !(mask & NP_ONESIDE)) continue; if (!rq->respaouter != !(mask & NP_RESPA)) continue; if (!rq->bond != !(mask & NP_BOND)) continue; if (!rq->omp != !(mask & NP_OMP)) continue; if (!rq->intel != !(mask & NP_INTEL)) continue; if (!rq->kokkos_device != !(mask & NP_KOKKOS_DEVICE)) continue; if (!rq->kokkos_host != !(mask & NP_KOKKOS_HOST)) continue; if (!rq->ssa != !(mask & NP_SSA)) continue; if (!rq->skip != !(mask & NP_SKIP)) continue; if (!rq->halffull != !(mask & NP_HALF_FULL)) continue; if (!rq->off2on != !(mask & NP_OFF2ON)) continue; // neighbor style is one of NSQ,BIN,MULTI and must match if (style == NSQ) { if (!(mask & NP_NSQ)) continue; } else if (style == BIN) { if (!(mask & NP_BIN)) continue; } else if (style == MULTI) { if (!(mask & NP_MULTI)) continue; } // domain triclinic flag is on or off and must match if (triclinic) { if (!(mask & NP_TRI)) continue; } else if (!triclinic) { if (!(mask & NP_ORTHO)) continue; } return i+1; } // error return if matched none return -1; } /* ---------------------------------------------------------------------- called by other classes to request a pairwise neighbor list ------------------------------------------------------------------------- */ int Neighbor::request(void *requestor, int instance) { if (nrequest == maxrequest) { maxrequest += RQDELTA; requests = (NeighRequest **) memory->srealloc(requests,maxrequest*sizeof(NeighRequest *), "neighbor:requests"); } requests[nrequest] = new NeighRequest(lmp); requests[nrequest]->index = nrequest; requests[nrequest]->requestor = requestor; requests[nrequest]->requestor_instance = instance; nrequest++; return nrequest-1; } /* ---------------------------------------------------------------------- one instance per entry in style_neigh_bin.h ------------------------------------------------------------------------- */ template NBin *Neighbor::bin_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- one instance per entry in style_neigh_stencil.h ------------------------------------------------------------------------- */ template NStencil *Neighbor::stencil_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- one instance per entry in style_neigh_pair.h ------------------------------------------------------------------------- */ template NPair *Neighbor::pair_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- setup neighbor binning and neighbor stencils called before run and every reneighbor if box size/shape changes only operates on perpetual lists build_one() operates on occasional lists ------------------------------------------------------------------------- */ void Neighbor::setup_bins() { // invoke setup_bins() for all NBin // actual binning is performed in build() for (int i = 0; i < nbin; i++) neigh_bin[i]->setup_bins(style); // invoke create_setup() and create() for all perpetual NStencil // same ops performed for occasional lists in build_one() for (int i = 0; i < nstencil_perpetual; i++) { neigh_stencil[slist[i]]->create_setup(); neigh_stencil[slist[i]]->create(); } last_setup_bins = update->ntimestep; } /* ---------------------------------------------------------------------- */ int Neighbor::decide() { if (must_check) { bigint n = update->ntimestep; if (restart_check && n == output->next_restart) return 1; for (int i = 0; i < fix_check; i++) if (n == modify->fix[fixchecklist[i]]->next_reneighbor) return 1; } ago++; if (ago >= delay && ago % every == 0) { if (build_once) return 0; if (dist_check == 0) return 1; return check_distance(); } else return 0; } /* ---------------------------------------------------------------------- if any atom moved trigger distance (half of neighbor skin) return 1 shrink trigger distance if box size has changed conservative shrink procedure: compute distance each of 8 corners of box has moved since last reneighbor reduce skin distance by sum of 2 largest of the 8 values new trigger = 1/2 of reduced skin distance for orthogonal box, only need 2 lo/hi corners for triclinic, need all 8 corners since deformations can displace all 8 ------------------------------------------------------------------------- */ int Neighbor::check_distance() { double delx,dely,delz,rsq; double delta,deltasq,delta1,delta2; if (boxcheck) { if (triclinic == 0) { delx = bboxlo[0] - boxlo_hold[0]; dely = bboxlo[1] - boxlo_hold[1]; delz = bboxlo[2] - boxlo_hold[2]; delta1 = sqrt(delx*delx + dely*dely + delz*delz); delx = bboxhi[0] - boxhi_hold[0]; dely = bboxhi[1] - boxhi_hold[1]; delz = bboxhi[2] - boxhi_hold[2]; delta2 = sqrt(delx*delx + dely*dely + delz*delz); delta = 0.5 * (skin - (delta1+delta2)); deltasq = delta*delta; } else { domain->box_corners(); delta1 = delta2 = 0.0; for (int i = 0; i < 8; i++) { delx = corners[i][0] - corners_hold[i][0]; dely = corners[i][1] - corners_hold[i][1]; delz = corners[i][2] - corners_hold[i][2]; delta = sqrt(delx*delx + dely*dely + delz*delz); if (delta > delta1) delta1 = delta; else if (delta > delta2) delta2 = delta; } delta = 0.5 * (skin - (delta1+delta2)); deltasq = delta*delta; } } else deltasq = triggersq; double **x = atom->x; int nlocal = atom->nlocal; if (includegroup) nlocal = atom->nfirst; int flag = 0; for (int i = 0; i < nlocal; i++) { delx = x[i][0] - xhold[i][0]; dely = x[i][1] - xhold[i][1]; delz = x[i][2] - xhold[i][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq > deltasq) flag = 1; } int flagall; MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world); if (flagall && ago == MAX(every,delay)) ndanger++; return flagall; } /* ---------------------------------------------------------------------- build perpetual neighbor lists called at setup and every few timesteps during run or minimization topology lists also built if topoflag = 1 (Kokkos calls with topoflag=0) ------------------------------------------------------------------------- */ void Neighbor::build(int topoflag) { int i,m; ago = 0; ncalls++; lastcall = update->ntimestep; int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; // check that using special bond flags will not overflow neigh lists if (nall > NEIGHMASK) error->one(FLERR,"Too many local+ghost atoms for neighbor list"); // store current atom positions and box size if needed if (dist_check) { double **x = atom->x; if (includegroup) nlocal = atom->nfirst; if (atom->nmax > maxhold) { maxhold = atom->nmax; memory->destroy(xhold); memory->create(xhold,maxhold,3,"neigh:xhold"); } for (i = 0; i < nlocal; i++) { xhold[i][0] = x[i][0]; xhold[i][1] = x[i][1]; xhold[i][2] = x[i][2]; } if (boxcheck) { if (triclinic == 0) { boxlo_hold[0] = bboxlo[0]; boxlo_hold[1] = bboxlo[1]; boxlo_hold[2] = bboxlo[2]; boxhi_hold[0] = bboxhi[0]; boxhi_hold[1] = bboxhi[1]; boxhi_hold[2] = bboxhi[2]; } else { domain->box_corners(); corners = domain->corners; for (i = 0; i < 8; i++) { corners_hold[i][0] = corners[i][0]; corners_hold[i][1] = corners[i][1]; corners_hold[i][2] = corners[i][2]; } } } } // bin atoms for all NBin instances // not just NBin associated with perpetual lists, also occasional lists // b/c cannot wait to bin occasional lists in build_one() call // if bin then, atoms may have moved outside of proc domain & bin extent, // leading to errors or even a crash if (style != NSQ) { for (int i = 0; i < nbin; i++) { neigh_bin[i]->bin_atoms_setup(nall); neigh_bin[i]->bin_atoms(); } } // build pairwise lists for all perpetual NPair/NeighList // grow() with nlocal/nall args so that only realloc if have to for (i = 0; i < npair_perpetual; i++) { m = plist[i]; if (!lists[m]->copy) lists[m]->grow(nlocal,nall); neigh_pair[m]->build_setup(); neigh_pair[m]->build(lists[m]); } // build topology lists for bonds/angles/etc if (atom->molecular && topoflag) build_topology(); } /* ---------------------------------------------------------------------- build topology neighbor lists: bond, angle, dihedral, improper copy their list info back to Neighbor for access by bond/angle/etc classes ------------------------------------------------------------------------- */ void Neighbor::build_topology() { if (force->bond) { neigh_bond->build(); nbondlist = neigh_bond->nbondlist; bondlist = neigh_bond->bondlist; } if (force->angle) { neigh_angle->build(); nanglelist = neigh_angle->nanglelist; anglelist = neigh_angle->anglelist; } if (force->dihedral) { neigh_dihedral->build(); ndihedrallist = neigh_dihedral->ndihedrallist; dihedrallist = neigh_dihedral->dihedrallist; } if (force->improper) { neigh_improper->build(); nimproperlist = neigh_improper->nimproperlist; improperlist = neigh_improper->improperlist; } } /* ---------------------------------------------------------------------- build a single occasional pairwise neighbor list indexed by I called by other classes ------------------------------------------------------------------------- */ void Neighbor::build_one(class NeighList *mylist, int preflag) { // check if list structure is initialized if (mylist == NULL) error->all(FLERR,"Trying to build an occasional neighbor list " "before initialization completed"); // build_one() should never be invoked on a perpetual list if (!mylist->occasional) error->all(FLERR,"Neighbor build one invoked on perpetual list"); // no need to build if already built since last re-neighbor // preflag is set by fix bond/create and fix bond/swap // b/c they invoke build_one() on same step neigh list is re-built, // but before re-build, so need to use ">" instead of ">=" NPair *np = neigh_pair[mylist->index]; if (preflag) { if (np->last_build > lastcall) return; } else { if (np->last_build >= lastcall) return; } // if this is copy list and parent is occasional list, // or this is halffull and parent is occasional list, // insure parent is current if (mylist->listcopy && mylist->listcopy->occasional) build_one(mylist->listcopy,preflag); if (mylist->listfull && mylist->listfull->occasional) build_one(mylist->listfull,preflag); // create stencil if hasn't been created since last setup_bins() call NStencil *ns = np->ns; if (ns && ns->last_stencil < last_setup_bins) { ns->create_setup(); ns->create(); } // build the list if (!mylist->copy) mylist->grow(atom->nlocal,atom->nlocal+atom->nghost); np->build_setup(); np->build(mylist); } /* ---------------------------------------------------------------------- set neighbor style and skin distance ------------------------------------------------------------------------- */ void Neighbor::set(int narg, char **arg) { if (narg != 2) error->all(FLERR,"Illegal neighbor command"); skin = force->numeric(FLERR,arg[0]); if (skin < 0.0) error->all(FLERR,"Illegal neighbor command"); if (strcmp(arg[1],"nsq") == 0) style = NSQ; else if (strcmp(arg[1],"bin") == 0) style = BIN; else if (strcmp(arg[1],"multi") == 0) style = MULTI; else error->all(FLERR,"Illegal neighbor command"); if (style == MULTI && lmp->citeme) lmp->citeme->add(cite_neigh_multi); } /* ---------------------------------------------------------------------- reset timestamps in all NeignBin, NStencil, NPair classes so that neighbor lists will rebuild properly with timestep change ditto for lastcall and last_setup_bins ------------------------------------------------------------------------- */ void Neighbor::reset_timestep(bigint ntimestep) { for (int i = 0; i < nbin; i++) neigh_bin[i]->last_bin = -1; for (int i = 0; i < nstencil; i++) neigh_stencil[i]->last_stencil = -1; for (int i = 0; i < nlist; i++) { if (!neigh_pair[i]) continue; neigh_pair[i]->last_build = -1; } lastcall = -1; last_setup_bins = -1; } /* ---------------------------------------------------------------------- modify parameters of the pair-wise neighbor build ------------------------------------------------------------------------- */ void Neighbor::modify_params(int narg, char **arg) { int iarg = 0; while (iarg < narg) { if (strcmp(arg[iarg],"every") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); every = force->inumeric(FLERR,arg[iarg+1]); if (every <= 0) error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"delay") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); delay = force->inumeric(FLERR,arg[iarg+1]); if (delay < 0) error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"check") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) dist_check = 1; else if (strcmp(arg[iarg+1],"no") == 0) dist_check = 0; else error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"once") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) build_once = 1; else if (strcmp(arg[iarg+1],"no") == 0) build_once = 0; else error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"page") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); old_pgsize = pgsize; pgsize = force->inumeric(FLERR,arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"one") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); old_oneatom = oneatom; oneatom = force->inumeric(FLERR,arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"binsize") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); binsize_user = force->numeric(FLERR,arg[iarg+1]); if (binsize_user <= 0.0) binsizeflag = 0; else binsizeflag = 1; iarg += 2; } else if (strcmp(arg[iarg],"cluster") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) cluster_check = 1; else if (strcmp(arg[iarg+1],"no") == 0) cluster_check = 0; else error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"include") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); includegroup = group->find(arg[iarg+1]); if (includegroup < 0) error->all(FLERR,"Invalid group ID in neigh_modify command"); if (includegroup && (atom->firstgroupname == NULL || strcmp(arg[iarg+1],atom->firstgroupname) != 0)) error->all(FLERR, "Neigh_modify include group != atom_modify first group"); iarg += 2; } else if (strcmp(arg[iarg],"exclude") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"type") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (nex_type == maxex_type) { maxex_type += EXDELTA; memory->grow(ex1_type,maxex_type,"neigh:ex1_type"); memory->grow(ex2_type,maxex_type,"neigh:ex2_type"); } ex1_type[nex_type] = force->inumeric(FLERR,arg[iarg+2]); ex2_type[nex_type] = force->inumeric(FLERR,arg[iarg+3]); nex_type++; iarg += 4; } else if (strcmp(arg[iarg+1],"group") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (nex_group == maxex_group) { maxex_group += EXDELTA; memory->grow(ex1_group,maxex_group,"neigh:ex1_group"); memory->grow(ex2_group,maxex_group,"neigh:ex2_group"); } ex1_group[nex_group] = group->find(arg[iarg+2]); ex2_group[nex_group] = group->find(arg[iarg+3]); if (ex1_group[nex_group] == -1 || ex2_group[nex_group] == -1) error->all(FLERR,"Invalid group ID in neigh_modify command"); nex_group++; iarg += 4; } else if (strcmp(arg[iarg+1],"molecule/inter") == 0 || strcmp(arg[iarg+1],"molecule/intra") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (atom->molecule_flag == 0) error->all(FLERR,"Neigh_modify exclude molecule " "requires atom attribute molecule"); if (nex_mol == maxex_mol) { maxex_mol += EXDELTA; memory->grow(ex_mol_group,maxex_mol,"neigh:ex_mol_group"); if (lmp->kokkos) grow_ex_mol_intra_kokkos(); else memory->grow(ex_mol_intra,maxex_mol,"neigh:ex_mol_intra"); } ex_mol_group[nex_mol] = group->find(arg[iarg+2]); if (ex_mol_group[nex_mol] == -1) error->all(FLERR,"Invalid group ID in neigh_modify command"); if (strcmp(arg[iarg+1],"molecule/intra") == 0) ex_mol_intra[nex_mol] = 1; else ex_mol_intra[nex_mol] = 0; nex_mol++; iarg += 3; } else if (strcmp(arg[iarg+1],"none") == 0) { nex_type = nex_group = nex_mol = 0; iarg += 2; } else error->all(FLERR,"Illegal neigh_modify command"); } else error->all(FLERR,"Illegal neigh_modify command"); } } /* ---------------------------------------------------------------------- remove the first group-group exclusion matching group1, group2 ------------------------------------------------------------------------- */ void Neighbor::exclusion_group_group_delete(int group1, int group2) { int m, mlast; for (m = 0; m < nex_group; m++) if (ex1_group[m] == group1 && ex2_group[m] == group2 ) break; mlast = m; if (mlast == nex_group) error->all(FLERR,"Unable to find group-group exclusion"); for (m = mlast+1; m < nex_group; m++) { ex1_group[m-1] = ex1_group[m]; ex2_group[m-1] = ex2_group[m]; ex1_bit[m-1] = ex1_bit[m]; ex2_bit[m-1] = ex2_bit[m]; } nex_group--; } /* ---------------------------------------------------------------------- return the value of exclude - used to check compatibility with GPU ------------------------------------------------------------------------- */ int Neighbor::exclude_setting() { return exclude; } /* ---------------------------------------------------------------------- return # of bytes of allocated memory ------------------------------------------------------------------------- */ bigint Neighbor::memory_usage() { bigint bytes = 0; bytes += memory->usage(xhold,maxhold,3); for (int i = 0; i < nlist; i++) if (lists[i]) bytes += lists[i]->memory_usage(); for (int i = 0; i < nstencil; i++) bytes += neigh_stencil[i]->memory_usage(); for (int i = 0; i < nbin; i++) bytes += neigh_bin[i]->memory_usage(); if (neigh_bond) bytes += neigh_bond->memory_usage(); if (neigh_angle) bytes += neigh_angle->memory_usage(); if (neigh_dihedral) bytes += neigh_dihedral->memory_usage(); if (neigh_improper) bytes += neigh_improper->memory_usage(); return bytes; } diff --git a/src/neighbor.h b/src/neighbor.h index 7520e191e..9244bc575 100644 --- a/src/neighbor.h +++ b/src/neighbor.h @@ -1,374 +1,374 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifndef LMP_NEIGHBOR_H #define LMP_NEIGHBOR_H #include "pointers.h" #include namespace LAMMPS_NS { class Neighbor : protected Pointers { public: int style; // 0,1,2 = nsq, bin, multi int every; // build every this many steps int delay; // delay build for this many steps int dist_check; // 0 = always build, 1 = only if 1/2 dist int ago; // how many steps ago neighboring occurred int pgsize; // size of neighbor page int oneatom; // max # of neighbors for one atom int includegroup; // only build pairwise lists for this group int build_once; // 1 if only build lists once per run double skin; // skin distance double cutneighmin; // min neighbor cutoff for all type pairs double cutneighmax; // max neighbor cutoff for all type pairs double cutneighmaxsq; // cutneighmax squared double **cutneighsq; // neighbor cutneigh sq for each type pair double **cutneighghostsq; // cutneigh sq for each ghost type pair double *cuttype; // for each type, max neigh cut w/ others double *cuttypesq; // cuttype squared double cut_inner_sq; // outer cutoff for inner neighbor list double cut_middle_sq; // outer cutoff for middle neighbor list double cut_middle_inside_sq; // inner cutoff for middle neighbor list int binsizeflag; // user-chosen bin size double binsize_user; // set externally by some accelerator pkgs bigint ncalls; // # of times build has been called bigint ndanger; // # of dangerous builds bigint lastcall; // timestep of last neighbor::build() call // geometry and static info, used by other Neigh classes double *bboxlo,*bboxhi; // ptrs to full domain bounding box // different for orthog vs triclinic // exclusion info, used by NeighPair int exclude; // 0 if no type/group exclusions, 1 if yes int nex_type; // # of entries in type exclusion list int *ex1_type,*ex2_type; // pairs of types to exclude int **ex_type; // 2d array of excluded type pairs int nex_group; // # of entries in group exclusion list int *ex1_group,*ex2_group; // pairs of group #'s to exclude int *ex1_bit,*ex2_bit; // pairs of group bits to exclude int nex_mol; // # of entries in molecule exclusion list int *ex_mol_group; // molecule group #'s to exclude int *ex_mol_bit; // molecule group bits to exclude int *ex_mol_intra; // 0 = exclude if in 2 molecules (inter) // 1 = exclude if in same molecule (intra) // special info, used by NeighPair int special_flag[4]; // flags for 1-2, 1-3, 1-4 neighbors // cluster setting, used by NeighTopo int cluster_check; // 1 if check bond/angle/etc satisfies minimg // pairwise neighbor lists and corresponding requests int nlist; // # of pairwise neighbor lists int nrequest; // # of requests, same as nlist int old_nrequest; // # of requests for previous run class NeighList **lists; class NeighRequest **requests; // from Pair,Fix,Compute,Command classes class NeighRequest **old_requests; // copy of requests to compare to // data from topology neighbor lists int nbondlist; // list of bonds to compute int **bondlist; int nanglelist; // list of angles to compute int **anglelist; int ndihedrallist; // list of dihedrals to compute int **dihedrallist; int nimproperlist; // list of impropers to compute int **improperlist; // public methods Neighbor(class LAMMPS *); virtual ~Neighbor(); virtual void init(); int request(void *, int instance=0); int decide(); // decide whether to build or not virtual int check_distance(); // check max distance moved since last build void setup_bins(); // setup bins based on box and cutoff virtual void build(int topoflag=1); // build all perpetual neighbor lists virtual void build_topology(); // pairwise topology neighbor lists void build_one(class NeighList *list, int preflag=0); // create a one-time pairwise neigh list void set(int, char **); // set neighbor style and skin distance void reset_timestep(bigint); // reset of timestep counter void modify_params(int, char**); // modify params that control builds void exclusion_group_group_delete(int, int); // rm a group-group exclusion int exclude_setting(); // return exclude value to accelerator pkg class NeighRequest *find_request(void *); // find a neighbor request bigint memory_usage(); protected: int me,nprocs; int firsttime; // flag for calling init_styles() only once int dimension; // 2/3 for 2d/3d int triclinic; // 0 if domain is orthog, 1 if triclinic int newton_pair; // 0 if newton off for pairwise, 1 if on int must_check; // 1 if must check other classes to reneigh int restart_check; // 1 if restart enabled, 0 if no int fix_check; // # of fixes that induce reneigh int *fixchecklist; // which fixes to check bigint last_setup_bins; // step of last neighbor::setup_bins() call double triggersq; // trigger = build when atom moves this dist double **xhold; // atom coords at last neighbor build int maxhold; // size of xhold array int boxcheck; // 1 if need to store box size double boxlo_hold[3],boxhi_hold[3]; // box size at last neighbor build double corners_hold[8][3]; // box corners at last neighbor build double (*corners)[3]; // ptr to 8 corners of triclinic box double inner[2],middle[2]; // rRESPA cutoffs for extra lists int old_style,old_triclinic; // previous run info int old_pgsize,old_oneatom; // used to avoid re-creating neigh lists int nstencil_perpetual; // # of perpetual NeighStencil classes int npair_perpetual; // #x of perpetual NeighPair classes int *slist; // indices of them in neigh_stencil int *plist; // indices of them in neigh_pair int maxex_type; // max # in exclusion type list int maxex_group; // max # in exclusion group list int maxex_mol; // max # in exclusion molecule list int maxatom; // max size of atom-based NeighList arrays int maxrequest; // max size of NeighRequest list int maxwt; // max weighting factor applied + 1 // info for other Neigh classes: NBin,NStencil,NPair,NTopo int nbin,nstencil; int nbclass,nsclass,npclass; int bondwhich,anglewhich,dihedralwhich,improperwhich; typedef class NBin *(*BinCreator)(class LAMMPS *); BinCreator *binclass; char **binnames; int *binmasks; class NBin **neigh_bin; typedef class NStencil *(*StencilCreator)(class LAMMPS *); StencilCreator *stencilclass; char **stencilnames; int *stencilmasks; class NStencil **neigh_stencil; typedef class NPair *(*PairCreator)(class LAMMPS *); PairCreator *pairclass; char **pairnames; int *pairmasks; class NPair **neigh_pair; class NTopo *neigh_bond; class NTopo *neigh_angle; class NTopo *neigh_dihedral; class NTopo *neigh_improper; // internal methods // including creator methods for Nbin,Nstencil,Npair instances void init_styles(); int init_pair(); virtual void init_topology(); - void morph_other(); + void morph_unique(); void morph_skip(); void morph_granular(); void morph_halffull(); void morph_copy(); void print_pairwise_info(); void requests_new2old(); int choose_bin(class NeighRequest *); int choose_stencil(class NeighRequest *); int choose_pair(class NeighRequest *); template static NBin *bin_creator(class LAMMPS *); template static NStencil *stencil_creator(class LAMMPS *); template static NPair *pair_creator(class LAMMPS *); // dummy functions provided by NeighborKokkos, called in init() // otherwise NeighborKokkos would have to overwrite init() int copymode; virtual void init_cutneighsq_kokkos(int) {} virtual void create_kokkos_list(int) {} virtual void init_ex_type_kokkos(int) {} virtual void init_ex_bit_kokkos() {} virtual void init_ex_mol_bit_kokkos() {} virtual void grow_ex_mol_intra_kokkos() {} }; namespace NeighConst { static const int NB_INTEL = 1<<0; static const int NB_KOKKOS_DEVICE = 1<<1; static const int NB_KOKKOS_HOST = 1<<2; static const int NB_SSA = 1<<3; static const int NS_BIN = 1<<0; static const int NS_MULTI = 1<<1; static const int NS_HALF = 1<<2; static const int NS_FULL = 1<<3; static const int NS_2D = 1<<4; static const int NS_3D = 1<<5; static const int NS_NEWTON = 1<<6; static const int NS_NEWTOFF = 1<<7; static const int NS_ORTHO = 1<<8; static const int NS_TRI = 1<<9; static const int NS_GHOST = 1<<10; static const int NS_SSA = 1<<11; static const int NP_NSQ = 1<<0; static const int NP_BIN = 1<<1; static const int NP_MULTI = 1<<2; static const int NP_HALF = 1<<3; static const int NP_FULL = 1<<4; static const int NP_ORTHO = 1<<5; static const int NP_TRI = 1<<6; static const int NP_ATOMONLY = 1<<7; static const int NP_MOLONLY = 1<<8; static const int NP_NEWTON = 1<<9; static const int NP_NEWTOFF = 1<<10; static const int NP_GHOST = 1<<11; static const int NP_SIZE = 1<<12; static const int NP_ONESIDE = 1<<13; static const int NP_RESPA = 1<<14; static const int NP_BOND = 1<<15; static const int NP_OMP = 1<<16; static const int NP_INTEL = 1<<17; static const int NP_KOKKOS_DEVICE = 1<<18; static const int NP_KOKKOS_HOST = 1<<19; static const int NP_SSA = 1<<20; static const int NP_COPY = 1<<21; static const int NP_SKIP = 1<<22; static const int NP_HALF_FULL = 1<<23; static const int NP_OFF2ON = 1<<24; } } #endif /* ERROR/WARNING messages: E: Neighbor delay must be 0 or multiple of every setting The delay and every parameters set via the neigh_modify command are inconsistent. If the delay setting is non-zero, then it must be a multiple of the every setting. E: Neighbor page size must be >= 10x the one atom setting This is required to prevent wasting too much memory. E: Invalid atom type in neighbor exclusion list Atom types must range from 1 to Ntypes inclusive. W: Neighbor exclusions used with KSpace solver may give inconsistent Coulombic energies This is because excluding specific pair interactions also excludes them from long-range interactions which may not be the desired effect. The special_bonds command handles this consistently by insuring excluded (or weighted) 1-2, 1-3, 1-4 interactions are treated consistently by both the short-range pair style and the long-range solver. This is not done for exclusions of charged atom pairs via the neigh_modify exclude command. E: Neighbor include group not allowed with ghost neighbors This is a current restriction within LAMMPS. E: Neighbor multi not yet enabled for ghost neighbors This is a current restriction within LAMMPS. E: Neighbor multi not yet enabled for granular Self-explanatory. E: Neighbor multi not yet enabled for rRESPA Self-explanatory. E: Too many local+ghost atoms for neighbor list The number of nlocal + nghost atoms on a processor is limited by the size of a 32-bit integer with 2 bits removed for masking 1-2, 1-3, 1-4 neighbors. E: Trying to build an occasional neighbor list before initialization completed This is not allowed. Source code caller needs to be modified. E: Domain too large for neighbor bins The domain has become extremely large so that neighbor bins cannot be used. Most likely, one or more atoms have been blown out of the simulation box to a great distance. E: Cannot use neighbor bins - box size << cutoff Too many neighbor bins will be created. This typically happens when the simulation box is very small in some dimension, compared to the neighbor cutoff. Use the "nsq" style instead of "bin" style. E: Too many neighbor bins This is likely due to an immense simulation box that has blown up to a large size. E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Invalid group ID in neigh_modify command A group ID used in the neigh_modify command does not exist. E: Neigh_modify include group != atom_modify first group Self-explanatory. E: Neigh_modify exclude molecule requires atom attribute molecule Self-explanatory. */ diff --git a/src/npair_half_respa_bin_newtoff.cpp b/src/npair_half_respa_bin_newtoff.cpp index 11246b4af..0145771f4 100644 --- a/src/npair_half_respa_bin_newtoff.cpp +++ b/src/npair_half_respa_bin_newtoff.cpp @@ -1,190 +1,187 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "npair_half_respa_bin_newtoff.h" #include "neighbor.h" #include "neigh_list.h" #include "atom.h" #include "atom_vec.h" #include "molecule.h" #include "domain.h" #include "my_page.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NPairHalfRespaBinNewtoff::NPairHalfRespaBinNewtoff(LAMMPS *lmp) : NPair(lmp) {} /* ---------------------------------------------------------------------- multiple respa lists binned neighbor list construction with partial Newton's 3rd law each owned atom i checks own bin and surrounding bins in non-Newton stencil pair stored once if i,j are both owned and i < j pair stored by me if j is ghost (also stored by proc owning j) ------------------------------------------------------------------------- */ void NPairHalfRespaBinNewtoff::build(NeighList *list) { int i,j,k,n,itype,jtype,ibin,n_inner,n_middle,imol,iatom,moltemplate; tagint tagprev; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*neighptr_inner,*neighptr_middle; double **x = atom->x; int *type = atom->type; int *mask = atom->mask; tagint *tag = atom->tag; tagint *molecule = atom->molecule; tagint **special = atom->special; int **nspecial = atom->nspecial; int nlocal = atom->nlocal; if (includegroup) nlocal = atom->nfirst; int *molindex = atom->molindex; int *molatom = atom->molatom; Molecule **onemols = atom->avec->onemols; if (molecular == 2) moltemplate = 1; else moltemplate = 0; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; MyPage *ipage = list->ipage; - NeighList *listinner = list->listinner; - int *ilist_inner = listinner->ilist; - int *numneigh_inner = listinner->numneigh; - int **firstneigh_inner = listinner->firstneigh; - MyPage *ipage_inner = listinner->ipage; + int *ilist_inner = list->ilist_inner; + int *numneigh_inner = list->numneigh_inner; + int **firstneigh_inner = list->firstneigh_inner; + MyPage *ipage_inner = list->ipage_inner; - NeighList *listmiddle; int *ilist_middle,*numneigh_middle,**firstneigh_middle; MyPage *ipage_middle; int respamiddle = list->respamiddle; if (respamiddle) { - listmiddle = list->listmiddle; - ilist_middle = listmiddle->ilist; - numneigh_middle = listmiddle->numneigh; - firstneigh_middle = listmiddle->firstneigh; - ipage_middle = listmiddle->ipage; + ilist_middle = list->ilist_middle; + numneigh_middle = list->numneigh_middle; + firstneigh_middle = list->firstneigh_middle; + ipage_middle = list->ipage_middle; } int inum = 0; int which = 0; int minchange = 0; ipage->reset(); ipage_inner->reset(); if (respamiddle) ipage_middle->reset(); for (i = 0; i < nlocal; i++) { n = n_inner = 0; neighptr = ipage->vget(); neighptr_inner = ipage_inner->vget(); if (respamiddle) { n_middle = 0; neighptr_middle = ipage_middle->vget(); } itype = type[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; ibin = atom2bin[i]; if (moltemplate) { imol = molindex[i]; iatom = molatom[i]; tagprev = tag[i] - iatom - 1; } // loop over all atoms in surrounding bins in stencil including self // only store pair if i < j // stores own/own pairs only once // stores own/ghost pairs on both procs for (k = 0; k < nstencil; k++) { for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) { if (j <= i) continue; jtype = type[j]; if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq <= cutneighsq[itype][jtype]) { if (molecular) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); else if (imol >= 0) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j]-tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if ((minchange = domain->minimum_image_check(delx,dely,delz))) neighptr[n++] = j; else if (which > 0) neighptr[n++] = j ^ (which << SBBITS); } else neighptr[n++] = j; if (rsq < cut_inner_sq) { if (which == 0) neighptr_inner[n_inner++] = j; else if (minchange) neighptr_inner[n_inner++] = j; else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS); } if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) { if (which == 0) neighptr_middle[n_middle++] = j; else if (minchange) neighptr_middle[n_middle++] = j; else if (which > 0) neighptr_middle[n_middle++] = j ^ (which << SBBITS); } } } } ilist[inum] = i; firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); if (ipage_inner->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); if (ipage_middle->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); } inum++; } list->inum = inum; - listinner->inum = inum; - if (respamiddle) listmiddle->inum = inum; + list->inum_inner = inum; + if (respamiddle) list->inum_middle = inum; } diff --git a/src/npair_half_respa_bin_newton.cpp b/src/npair_half_respa_bin_newton.cpp index db7667803..72a613204 100644 --- a/src/npair_half_respa_bin_newton.cpp +++ b/src/npair_half_respa_bin_newton.cpp @@ -1,236 +1,233 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "npair_half_respa_bin_newton.h" #include "neighbor.h" #include "neigh_list.h" #include "atom.h" #include "atom_vec.h" #include "molecule.h" #include "domain.h" #include "my_page.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NPairHalfRespaBinNewton::NPairHalfRespaBinNewton(LAMMPS *lmp) : NPair(lmp) {} /* ---------------------------------------------------------------------- multiple respa lists binned neighbor list construction with full Newton's 3rd law each owned atom i checks its own bin and other bins in Newton stencil every pair stored exactly once by some processor ------------------------------------------------------------------------- */ void NPairHalfRespaBinNewton::build(NeighList *list) { int i,j,k,n,itype,jtype,ibin,n_inner,n_middle,imol,iatom,moltemplate; tagint tagprev; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*neighptr_inner,*neighptr_middle; double **x = atom->x; int *type = atom->type; int *mask = atom->mask; tagint *tag = atom->tag; tagint *molecule = atom->molecule; tagint **special = atom->special; int **nspecial = atom->nspecial; int nlocal = atom->nlocal; if (includegroup) nlocal = atom->nfirst; int *molindex = atom->molindex; int *molatom = atom->molatom; Molecule **onemols = atom->avec->onemols; if (molecular == 2) moltemplate = 1; else moltemplate = 0; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; MyPage *ipage = list->ipage; - NeighList *listinner = list->listinner; - int *ilist_inner = listinner->ilist; - int *numneigh_inner = listinner->numneigh; - int **firstneigh_inner = listinner->firstneigh; - MyPage *ipage_inner = listinner->ipage; + int *ilist_inner = list->ilist_inner; + int *numneigh_inner = list->numneigh_inner; + int **firstneigh_inner = list->firstneigh_inner; + MyPage *ipage_inner = list->ipage_inner; - NeighList *listmiddle; int *ilist_middle,*numneigh_middle,**firstneigh_middle; MyPage *ipage_middle; int respamiddle = list->respamiddle; if (respamiddle) { - listmiddle = list->listmiddle; - ilist_middle = listmiddle->ilist; - numneigh_middle = listmiddle->numneigh; - firstneigh_middle = listmiddle->firstneigh; - ipage_middle = listmiddle->ipage; + ilist_middle = list->ilist_middle; + numneigh_middle = list->numneigh_middle; + firstneigh_middle = list->firstneigh_middle; + ipage_middle = list->ipage_middle; } int inum = 0; int which = 0; int minchange = 0; ipage->reset(); ipage_inner->reset(); if (respamiddle) ipage_middle->reset(); for (i = 0; i < nlocal; i++) { n = n_inner = 0; neighptr = ipage->vget(); neighptr_inner = ipage_inner->vget(); if (respamiddle) { n_middle = 0; neighptr_middle = ipage_middle->vget(); } itype = type[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; if (moltemplate) { imol = molindex[i]; iatom = molatom[i]; tagprev = tag[i] - iatom - 1; } // loop over rest of atoms in i's bin, ghosts are at end of linked list // if j is owned atom, store it, since j is beyond i in linked list // if j is ghost, only store if j coords are "above and to the right" of i for (j = bins[i]; j >= 0; j = bins[j]) { if (j >= nlocal) { if (x[j][2] < ztmp) continue; if (x[j][2] == ztmp) { if (x[j][1] < ytmp) continue; if (x[j][1] == ytmp && x[j][0] < xtmp) continue; } } jtype = type[j]; if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq <= cutneighsq[itype][jtype]) { if (molecular) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); else if (imol >= 0) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j]-tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if ((minchange = domain->minimum_image_check(delx,dely,delz))) neighptr[n++] = j; else if (which > 0) neighptr[n++] = j ^ (which << SBBITS); } else neighptr[n++] = j; if (rsq < cut_inner_sq) { if (which == 0) neighptr_inner[n_inner++] = j; else if (minchange) neighptr_inner[n_inner++] = j; else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS); } if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) { if (which == 0) neighptr_middle[n_middle++] = j; else if (minchange) neighptr_middle[n_middle++] = j; else if (which > 0) neighptr_middle[n_middle++] = j ^ (which << SBBITS); } } } // loop over all atoms in other bins in stencil, store every pair ibin = atom2bin[i]; for (k = 0; k < nstencil; k++) { for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) { jtype = type[j]; if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq <= cutneighsq[itype][jtype]) { if (molecular) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); else if (imol >= 0) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j]-tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if ((minchange = domain->minimum_image_check(delx,dely,delz))) neighptr[n++] = j; else if (which > 0) neighptr[n++] = j ^ (which << SBBITS); } else neighptr[n++] = j; if (rsq < cut_inner_sq) { if (which == 0) neighptr_inner[n_inner++] = j; else if (minchange) neighptr_inner[n_inner++] = j; else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS); } if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) { if (which == 0) neighptr_middle[n_middle++] = j; else if (minchange) neighptr_middle[n_middle++] = j; else if (which > 0) neighptr_middle[n_middle++] = j ^ (which << SBBITS); } } } } ilist[inum] = i; firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); if (ipage_inner->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); if (ipage_middle->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); } inum++; } list->inum = inum; - listinner->inum = inum; - if (respamiddle) listmiddle->inum = inum; + list->inum_inner = inum; + if (respamiddle) list->inum_middle = inum; } diff --git a/src/npair_half_respa_bin_newton_tri.cpp b/src/npair_half_respa_bin_newton_tri.cpp index 4ec6685e1..add1cf6e5 100644 --- a/src/npair_half_respa_bin_newton_tri.cpp +++ b/src/npair_half_respa_bin_newton_tri.cpp @@ -1,198 +1,195 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "npair_half_respa_bin_newton_tri.h" #include "neighbor.h" #include "neigh_list.h" #include "atom.h" #include "atom_vec.h" #include "molecule.h" #include "domain.h" #include "my_page.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NPairHalfRespaBinNewtonTri::NPairHalfRespaBinNewtonTri(LAMMPS *lmp) : NPair(lmp) {} /* ---------------------------------------------------------------------- multiple respa lists binned neighbor list construction with Newton's 3rd law for triclinic each owned atom i checks its own bin and other bins in triclinic stencil every pair stored exactly once by some processor ------------------------------------------------------------------------- */ void NPairHalfRespaBinNewtonTri::build(NeighList *list) { int i,j,k,n,itype,jtype,ibin,n_inner,n_middle,imol,iatom,moltemplate; tagint tagprev; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*neighptr_inner,*neighptr_middle; double **x = atom->x; int *type = atom->type; int *mask = atom->mask; tagint *tag = atom->tag; tagint *molecule = atom->molecule; tagint **special = atom->special; int **nspecial = atom->nspecial; int nlocal = atom->nlocal; if (includegroup) nlocal = atom->nfirst; int *molindex = atom->molindex; int *molatom = atom->molatom; Molecule **onemols = atom->avec->onemols; if (molecular == 2) moltemplate = 1; else moltemplate = 0; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; MyPage *ipage = list->ipage; - NeighList *listinner = list->listinner; - int *ilist_inner = listinner->ilist; - int *numneigh_inner = listinner->numneigh; - int **firstneigh_inner = listinner->firstneigh; - MyPage *ipage_inner = listinner->ipage; + int *ilist_inner = list->ilist_inner; + int *numneigh_inner = list->numneigh_inner; + int **firstneigh_inner = list->firstneigh_inner; + MyPage *ipage_inner = list->ipage_inner; - NeighList *listmiddle; int *ilist_middle,*numneigh_middle,**firstneigh_middle; MyPage *ipage_middle; int respamiddle = list->respamiddle; if (respamiddle) { - listmiddle = list->listmiddle; - ilist_middle = listmiddle->ilist; - numneigh_middle = listmiddle->numneigh; - firstneigh_middle = listmiddle->firstneigh; - ipage_middle = listmiddle->ipage; + ilist_middle = list->ilist_middle; + numneigh_middle = list->numneigh_middle; + firstneigh_middle = list->firstneigh_middle; + ipage_middle = list->ipage_middle; } int inum = 0; int which = 0; int minchange = 0; ipage->reset(); ipage_inner->reset(); if (respamiddle) ipage_middle->reset(); for (i = 0; i < nlocal; i++) { n = n_inner = 0; neighptr = ipage->vget(); neighptr_inner = ipage_inner->vget(); if (respamiddle) { n_middle = 0; neighptr_middle = ipage_middle->vget(); } itype = type[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; if (moltemplate) { imol = molindex[i]; iatom = molatom[i]; tagprev = tag[i] - iatom - 1; } // loop over all atoms in bins in stencil // pairs for atoms j "below" i are excluded // below = lower z or (equal z and lower y) or (equal zy and lower x) // (equal zyx and j <= i) // latter excludes self-self interaction but allows superposed atoms ibin = atom2bin[i]; for (k = 0; k < nstencil; k++) { for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) { if (x[j][2] < ztmp) continue; if (x[j][2] == ztmp) { if (x[j][1] < ytmp) continue; if (x[j][1] == ytmp) { if (x[j][0] < xtmp) continue; if (x[j][0] == xtmp && j <= i) continue; } } jtype = type[j]; if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq <= cutneighsq[itype][jtype]) { if (molecular) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); else if (imol >= 0) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j]-tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if ((minchange = domain->minimum_image_check(delx,dely,delz))) neighptr[n++] = j; else if (which > 0) neighptr[n++] = j ^ (which << SBBITS); } else neighptr[n++] = j; if (rsq < cut_inner_sq) { if (which == 0) neighptr_inner[n_inner++] = j; else if (minchange) neighptr_inner[n_inner++] = j; else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS); } if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) { if (which == 0) neighptr_middle[n_middle++] = j; else if (minchange) neighptr_middle[n_middle++] = j; else if (which > 0) neighptr_middle[n_middle++] = j ^ (which << SBBITS); } } } } ilist[inum] = i; firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); if (ipage_inner->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); if (ipage_middle->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); } inum++; } list->inum = inum; - listinner->inum = inum; - if (respamiddle) listmiddle->inum = inum; + list->inum_inner = inum; + if (respamiddle) list->inum_middle = inum; } diff --git a/src/npair_half_respa_nsq_newtoff.cpp b/src/npair_half_respa_nsq_newtoff.cpp index 1bb203438..c0e932f0a 100644 --- a/src/npair_half_respa_nsq_newtoff.cpp +++ b/src/npair_half_respa_nsq_newtoff.cpp @@ -1,185 +1,182 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "npair_half_respa_nsq_newtoff.h" #include "neighbor.h" #include "neigh_list.h" #include "atom.h" #include "atom_vec.h" #include "group.h" #include "molecule.h" #include "domain.h" #include "my_page.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NPairHalfRespaNsqNewtoff::NPairHalfRespaNsqNewtoff(LAMMPS *lmp) : NPair(lmp) {} /* ---------------------------------------------------------------------- multiple respa lists N^2 / 2 search for neighbor pairs with partial Newton's 3rd law pair added to list if atoms i and j are both owned and i < j pair added if j is ghost (also stored by proc owning j) ------------------------------------------------------------------------- */ void NPairHalfRespaNsqNewtoff::build(NeighList *list) { int i,j,n,itype,jtype,n_inner,n_middle,bitmask,imol,iatom,moltemplate; tagint tagprev; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*neighptr_inner,*neighptr_middle; double **x = atom->x; int *type = atom->type; int *mask = atom->mask; tagint *tag = atom->tag; tagint *molecule = atom->molecule; tagint **special = atom->special; int **nspecial = atom->nspecial; int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; if (includegroup) { nlocal = atom->nfirst; bitmask = group->bitmask[includegroup]; } int *molindex = atom->molindex; int *molatom = atom->molatom; Molecule **onemols = atom->avec->onemols; if (molecular == 2) moltemplate = 1; else moltemplate = 0; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; MyPage *ipage = list->ipage; - NeighList *listinner = list->listinner; - int *ilist_inner = listinner->ilist; - int *numneigh_inner = listinner->numneigh; - int **firstneigh_inner = listinner->firstneigh; - MyPage *ipage_inner = listinner->ipage; + int *ilist_inner = list->ilist_inner; + int *numneigh_inner = list->numneigh_inner; + int **firstneigh_inner = list->firstneigh_inner; + MyPage *ipage_inner = list->ipage_inner; - NeighList *listmiddle; int *ilist_middle,*numneigh_middle,**firstneigh_middle; MyPage *ipage_middle; int respamiddle = list->respamiddle; if (respamiddle) { - listmiddle = list->listmiddle; - ilist_middle = listmiddle->ilist; - numneigh_middle = listmiddle->numneigh; - firstneigh_middle = listmiddle->firstneigh; - ipage_middle = listmiddle->ipage; + ilist_middle = list->ilist_middle; + numneigh_middle = list->numneigh_middle; + firstneigh_middle = list->firstneigh_middle; + ipage_middle = list->ipage_middle; } int inum = 0; int which = 0; int minchange = 0; ipage->reset(); ipage_inner->reset(); if (respamiddle) ipage_middle->reset(); for (i = 0; i < nlocal; i++) { n = n_inner = 0; neighptr = ipage->vget(); neighptr_inner = ipage_inner->vget(); if (respamiddle) { n_middle = 0; neighptr_middle = ipage_middle->vget(); } itype = type[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; if (moltemplate) { imol = molindex[i]; iatom = molatom[i]; tagprev = tag[i] - iatom - 1; } // loop over remaining atoms, owned and ghost for (j = i+1; j < nall; j++) { if (includegroup && !(mask[j] & bitmask)) continue; jtype = type[j]; if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq <= cutneighsq[itype][jtype]) { if (molecular) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); else if (imol >= 0) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j]-tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if ((minchange = domain->minimum_image_check(delx,dely,delz))) neighptr[n++] = j; else if (which > 0) neighptr[n++] = j ^ (which << SBBITS); } else neighptr[n++] = j; if (rsq < cut_inner_sq) { if (which == 0) neighptr_inner[n_inner++] = j; else if (minchange) neighptr_inner[n_inner++] = j; else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS); } if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) { if (which == 0) neighptr_middle[n_middle++] = j; else if (minchange) neighptr_middle[n_middle++] = j; else if (which > 0) neighptr_middle[n_middle++] = j ^ (which << SBBITS); } } } ilist[inum] = i; firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); if (ipage_inner->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); if (ipage_middle->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); } inum++; } list->inum = inum; - listinner->inum = inum; - if (respamiddle) listmiddle->inum = inum; + list->inum_inner = inum; + if (respamiddle) list->inum_middle = inum; } diff --git a/src/npair_half_respa_nsq_newton.cpp b/src/npair_half_respa_nsq_newton.cpp index 9aacc702c..f7d161896 100644 --- a/src/npair_half_respa_nsq_newton.cpp +++ b/src/npair_half_respa_nsq_newton.cpp @@ -1,205 +1,202 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "npair_half_respa_nsq_newton.h" #include "neighbor.h" #include "neigh_list.h" #include "atom.h" #include "atom_vec.h" #include "group.h" #include "molecule.h" #include "domain.h" #include "my_page.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NPairHalfRespaNsqNewton::NPairHalfRespaNsqNewton(LAMMPS *lmp) : NPair(lmp) {} /* ---------------------------------------------------------------------- multiple respa lists N^2 / 2 search for neighbor pairs with full Newton's 3rd law pair added to list if atoms i and j are both owned and i < j if j is ghost only me or other proc adds pair decision based on itag,jtag tests ------------------------------------------------------------------------- */ void NPairHalfRespaNsqNewton::build(NeighList *list) { int i,j,n,itype,jtype,itag,jtag,n_inner,n_middle,bitmask; int imol,iatom,moltemplate; tagint tagprev; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*neighptr_inner,*neighptr_middle; double **x = atom->x; int *type = atom->type; int *mask = atom->mask; tagint *tag = atom->tag; tagint *molecule = atom->molecule; tagint **special = atom->special; int **nspecial = atom->nspecial; int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; if (includegroup) { nlocal = atom->nfirst; bitmask = group->bitmask[includegroup]; } int *molindex = atom->molindex; int *molatom = atom->molatom; Molecule **onemols = atom->avec->onemols; if (molecular == 2) moltemplate = 1; else moltemplate = 0; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; MyPage *ipage = list->ipage; - NeighList *listinner = list->listinner; - int *ilist_inner = listinner->ilist; - int *numneigh_inner = listinner->numneigh; - int **firstneigh_inner = listinner->firstneigh; - MyPage *ipage_inner = listinner->ipage; + int *ilist_inner = list->ilist_inner; + int *numneigh_inner = list->numneigh_inner; + int **firstneigh_inner = list->firstneigh_inner; + MyPage *ipage_inner = list->ipage_inner; - NeighList *listmiddle; int *ilist_middle,*numneigh_middle,**firstneigh_middle; MyPage *ipage_middle; int respamiddle = list->respamiddle; if (respamiddle) { - listmiddle = list->listmiddle; - ilist_middle = listmiddle->ilist; - numneigh_middle = listmiddle->numneigh; - firstneigh_middle = listmiddle->firstneigh; - ipage_middle = listmiddle->ipage; + ilist_middle = list->ilist_middle; + numneigh_middle = list->numneigh_middle; + firstneigh_middle = list->firstneigh_middle; + ipage_middle = list->ipage_middle; } int inum = 0; int which = 0; int minchange = 0; ipage->reset(); ipage_inner->reset(); if (respamiddle) ipage_middle->reset(); for (i = 0; i < nlocal; i++) { n = n_inner = 0; neighptr = ipage->vget(); neighptr_inner = ipage_inner->vget(); if (respamiddle) { n_middle = 0; neighptr_middle = ipage_middle->vget(); } itag = tag[i]; itype = type[i]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; if (moltemplate) { imol = molindex[i]; iatom = molatom[i]; tagprev = tag[i] - iatom - 1; } // loop over remaining atoms, owned and ghost for (j = i+1; j < nall; j++) { if (includegroup && !(mask[j] & bitmask)) continue; if (j >= nlocal) { jtag = tag[j]; if (itag > jtag) { if ((itag+jtag) % 2 == 0) continue; } else if (itag < jtag) { if ((itag+jtag) % 2 == 1) continue; } else { if (x[j][2] < ztmp) continue; if (x[j][2] == ztmp) { if (x[j][1] < ytmp) continue; if (x[j][1] == ytmp && x[j][0] < xtmp) continue; } } } jtype = type[j]; if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq <= cutneighsq[itype][jtype]) { if (molecular) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); else if (imol >= 0) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j]-tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if ((minchange = domain->minimum_image_check(delx,dely,delz))) neighptr[n++] = j; else if (which > 0) neighptr[n++] = j ^ (which << SBBITS); } else neighptr[n++] = j; if (rsq < cut_inner_sq) { if (which == 0) neighptr_inner[n_inner++] = j; else if (minchange) neighptr_inner[n_inner++] = j; else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS); } if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) { if (which == 0) neighptr_middle[n_middle++] = j; else if (minchange) neighptr_middle[n_middle++] = j; else if (which > 0) neighptr_middle[n_middle++] = j ^ (which << SBBITS); } } } ilist[inum] = i; firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); if (ipage_inner->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); if (ipage_middle->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); } inum++; } list->inum = inum; - listinner->inum = inum; - if (respamiddle) listmiddle->inum = inum; + list->inum_inner = inum; + if (respamiddle) list->inum_middle = inum; } diff --git a/src/npair_skip_respa.cpp b/src/npair_skip_respa.cpp index 31420b32d..1d4eda535 100644 --- a/src/npair_skip_respa.cpp +++ b/src/npair_skip_respa.cpp @@ -1,169 +1,165 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #include "npair_skip_respa.h" #include "neighbor.h" #include "neigh_list.h" #include "atom.h" #include "atom_vec.h" #include "molecule.h" #include "domain.h" #include "my_page.h" #include "error.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NPairSkipRespa::NPairSkipRespa(LAMMPS *lmp) : NPair(lmp) {} /* ---------------------------------------------------------------------- build skip list for subset of types from parent list iskip and ijskip flag which atom types and type pairs to skip this is for respa lists, copy the inner/middle values from parent ------------------------------------------------------------------------- */ void NPairSkipRespa::build(NeighList *list) { int i,j,ii,jj,n,itype,jnum,joriginal,n_inner,n_middle; int *neighptr,*jlist,*neighptr_inner,*neighptr_middle; int *type = atom->type; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; MyPage *ipage = list->ipage; int *ilist_skip = list->listskip->ilist; int *numneigh_skip = list->listskip->numneigh; int **firstneigh_skip = list->listskip->firstneigh; int inum_skip = list->listskip->inum; int *iskip = list->iskip; int **ijskip = list->ijskip; - NeighList *listinner = list->listinner; - int *ilist_inner = listinner->ilist; - int *numneigh_inner = listinner->numneigh; - int **firstneigh_inner = listinner->firstneigh; - MyPage *ipage_inner = listinner->ipage; + int *ilist_inner = list->ilist_inner; + int *numneigh_inner = list->numneigh_inner; + int **firstneigh_inner = list->firstneigh_inner; + MyPage *ipage_inner = list->ipage_inner; + int *numneigh_inner_skip = list->listskip->numneigh_inner; + int **firstneigh_inner_skip = list->listskip->firstneigh_inner; - int *numneigh_inner_skip = list->listskip->listinner->numneigh; - int **firstneigh_inner_skip = list->listskip->listinner->firstneigh; - - NeighList *listmiddle; int *ilist_middle,*numneigh_middle,**firstneigh_middle; MyPage *ipage_middle; int *numneigh_middle_skip,**firstneigh_middle_skip; int respamiddle = list->respamiddle; if (respamiddle) { - listmiddle = list->listmiddle; - ilist_middle = listmiddle->ilist; - numneigh_middle = listmiddle->numneigh; - firstneigh_middle = listmiddle->firstneigh; - ipage_middle = listmiddle->ipage; - numneigh_middle_skip = list->listskip->listmiddle->numneigh; - firstneigh_middle_skip = list->listskip->listmiddle->firstneigh; + ilist_middle = list->ilist_middle; + numneigh_middle = list->numneigh_middle; + firstneigh_middle = list->firstneigh_middle; + ipage_middle = list->ipage_middle; + numneigh_middle_skip = list->listskip->numneigh_middle; + firstneigh_middle_skip = list->listskip->firstneigh_middle; } int inum = 0; ipage->reset(); ipage_inner->reset(); if (respamiddle) ipage_middle->reset(); // loop over atoms in other list // skip I atom entirely if iskip is set for type[I] // skip I,J pair if ijskip is set for type[I],type[J] for (ii = 0; ii < inum_skip; ii++) { i = ilist_skip[ii]; itype = type[i]; if (iskip[itype]) continue; n = n_inner = 0; neighptr = ipage->vget(); neighptr_inner = ipage_inner->vget(); if (respamiddle) { n_middle = 0; neighptr_middle = ipage_middle->vget(); } // loop over parent outer rRESPA list jlist = firstneigh_skip[i]; jnum = numneigh_skip[i]; for (jj = 0; jj < jnum; jj++) { joriginal = jlist[jj]; j = joriginal & NEIGHMASK; if (ijskip[itype][type[j]]) continue; neighptr[n++] = joriginal; } // loop over parent inner rRESPA list jlist = firstneigh_inner_skip[i]; jnum = numneigh_inner_skip[i]; for (jj = 0; jj < jnum; jj++) { joriginal = jlist[jj]; j = joriginal & NEIGHMASK; if (ijskip[itype][type[j]]) continue; neighptr_inner[n_inner++] = joriginal; } // loop over parent middle rRESPA list if (respamiddle) { jlist = firstneigh_middle_skip[i]; jnum = numneigh_middle_skip[i]; for (jj = 0; jj < jnum; jj++) { joriginal = jlist[jj]; j = joriginal & NEIGHMASK; if (ijskip[itype][type[j]]) continue; neighptr_middle[n_middle++] = joriginal; } } ilist[inum] = i; firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n); if (ipage_inner->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n); if (ipage_middle->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); } inum++; } list->inum = inum; - listinner->inum = inum; - if (respamiddle) listmiddle->inum = inum; + list->inum_inner = inum; + if (respamiddle) list->inum_middle = inum; } diff --git a/src/pair.h b/src/pair.h index 0f7b0f85b..eb71e8822 100644 --- a/src/pair.h +++ b/src/pair.h @@ -1,364 +1,360 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifndef LMP_PAIR_H #define LMP_PAIR_H #include "pointers.h" #include "accelerator_kokkos.h" namespace LAMMPS_NS { class Pair : protected Pointers { friend class AngleSDK; friend class AngleSDKOMP; friend class BondQuartic; friend class BondQuarticOMP; friend class DihedralCharmm; friend class DihedralCharmmOMP; friend class FixGPU; friend class FixOMP; friend class ThrOMP; friend class Info; public: static int instance_total; // # of Pair classes ever instantiated double eng_vdwl,eng_coul; // accumulated energies double virial[6]; // accumulated virial double *eatom,**vatom; // accumulated per-atom energy/virial double cutforce; // max cutoff for all atom pairs double **cutsq; // cutoff sq for each atom pair int **setflag; // 0/1 = whether each i,j has been set int comm_forward; // size of forward communication (0 if none) int comm_reverse; // size of reverse communication (0 if none) int comm_reverse_off; // size of reverse comm even if newton off int single_enable; // 1 if single() routine exists int restartinfo; // 1 if pair style writes restart info int respa_enable; // 1 if inner/middle/outer rRESPA routines int one_coeff; // 1 if allows only one coeff * * call int manybody_flag; // 1 if a manybody potential int no_virial_fdotr_compute; // 1 if does not invoke virial_fdotr_compute() int writedata; // 1 if writes coeffs to data file int ghostneigh; // 1 if pair style needs neighbors of ghosts double **cutghost; // cutoff for each ghost pair int ewaldflag; // 1 if compatible with Ewald solver int pppmflag; // 1 if compatible with PPPM solver int msmflag; // 1 if compatible with MSM solver int dispersionflag; // 1 if compatible with LJ/dispersion solver int tip4pflag; // 1 if compatible with TIP4P solver int dipoleflag; // 1 if compatible with dipole solver int reinitflag; // 1 if compatible with fix adapt and alike int tail_flag; // pair_modify flag for LJ tail correction double etail,ptail; // energy/pressure tail corrections double etail_ij,ptail_ij; int evflag; // energy,virial settings int eflag_either,eflag_global,eflag_atom; int vflag_either,vflag_global,vflag_atom; int ncoultablebits; // size of Coulomb table, accessed by KSpace int ndisptablebits; // size of dispersion table double tabinnersq; double tabinnerdispsq; double *rtable,*drtable,*ftable,*dftable,*ctable,*dctable; double *etable,*detable,*ptable,*dptable,*vtable,*dvtable; double *rdisptable, *drdisptable, *fdisptable, *dfdisptable; double *edisptable, *dedisptable; int ncoulshiftbits,ncoulmask; int ndispshiftbits, ndispmask; int nextra; // # of extra quantities pair style calculates double *pvector; // vector of extra pair quantities int single_extra; // number of extra single values calculated double *svector; // vector of extra single quantities class NeighList *list; // standard neighbor list used by most pairs class NeighList *listhalf; // half list used by some pairs class NeighList *listfull; // full list used by some pairs - class NeighList *listhistory; // neighbor history list used by some pairs - class NeighList *listinner; // rRESPA lists used by some pairs - class NeighList *listmiddle; - class NeighList *listouter; int allocated; // 0/1 = whether arrays are allocated // public so external driver can check int compute_flag; // 0 if skip compute() // KOKKOS host/device flag and data masks ExecutionSpace execution_space; unsigned int datamask_read,datamask_modify; Pair(class LAMMPS *); virtual ~Pair(); // top-level Pair methods void init(); virtual void reinit(); virtual void setup() {} double mix_energy(double, double, double, double); double mix_distance(double, double); void write_file(int, char **); void init_bitmap(double, double, int, int &, int &, int &, int &); virtual void modify_params(int, char **); void compute_dummy(int, int); // need to be public, so can be called by pair_style reaxc void v_tally(int, double *, double *); void ev_tally(int, int, int, int, double, double, double, double, double, double); void ev_tally3(int, int, int, double, double, double *, double *, double *, double *); void v_tally3(int, int, int, double *, double *, double *, double *); void v_tally4(int, int, int, int, double *, double *, double *, double *, double *, double *); void ev_tally_xyz(int, int, int, int, double, double, double, double, double, double, double, double); // general child-class methods virtual void compute(int, int) = 0; virtual void compute_inner() {} virtual void compute_middle() {} virtual void compute_outer(int, int) {} virtual double single(int, int, int, int, double, double, double, double& fforce) { fforce = 0.0; return 0.0; } virtual void settings(int, char **) = 0; virtual void coeff(int, char **) = 0; virtual void init_style(); virtual void init_list(int, class NeighList *); virtual double init_one(int, int) {return 0.0;} virtual void init_tables(double, double *); virtual void init_tables_disp(double); virtual void free_tables(); virtual void free_disp_tables(); virtual void write_restart(FILE *) {} virtual void read_restart(FILE *) {} virtual void write_restart_settings(FILE *) {} virtual void read_restart_settings(FILE *) {} virtual void write_data(FILE *) {} virtual void write_data_all(FILE *) {} virtual int pack_forward_comm(int, int *, double *, int, int *) {return 0;} virtual void unpack_forward_comm(int, int, double *) {} virtual int pack_forward_comm_kokkos(int, DAT::tdual_int_2d, int, DAT::tdual_xfloat_1d &, int, int *) {return 0;}; virtual void unpack_forward_comm_kokkos(int, int, DAT::tdual_xfloat_1d &) {} virtual int pack_reverse_comm(int, int, double *) {return 0;} virtual void unpack_reverse_comm(int, int *, double *) {} virtual double memory_usage(); void set_copymode(int value) {copymode = value;} // specific child-class methods for certain Pair styles virtual void *extract(const char *, int &) {return NULL;} virtual void swap_eam(double *, double **) {} virtual void reset_dt() {} virtual void min_xf_pointers(int, double **, double **) {} virtual void min_xf_get(int) {} virtual void min_x_set(int) {} // management of callbacks to be run from ev_tally() protected: int num_tally_compute; class Compute **list_tally_compute; public: virtual void add_tally_callback(class Compute *); virtual void del_tally_callback(class Compute *); protected: int instance_me; // which Pair class instantiation I am enum{GEOMETRIC,ARITHMETIC,SIXTHPOWER}; // mixing options int special_lj[4]; // copied from force->special_lj for Kokkos int suffix_flag; // suffix compatibility flag // pair_modify settings int offset_flag,mix_flag; // flags for offset and mixing double tabinner; // inner cutoff for Coulomb table double tabinner_disp; // inner cutoff for dispersion table public: // custom data type for accessing Coulomb tables typedef union {int i; float f;} union_int_float_t; protected: int vflag_fdotr; int maxeatom,maxvatom; int copymode; // if set, do not deallocate during destruction // required when classes are used as functors by Kokkos virtual void ev_setup(int, int, int alloc = 1); void ev_unset(); void ev_tally_full(int, double, double, double, double, double, double); void ev_tally_xyz_full(int, double, double, double, double, double, double, double, double); void ev_tally4(int, int, int, int, double, double *, double *, double *, double *, double *, double *); void ev_tally_tip4p(int, int *, double *, double, double); void v_tally2(int, int, double, double *); void v_tally_tensor(int, int, int, int, double, double, double, double, double, double); void virial_fdotr_compute(); // union data struct for packing 32-bit and 64-bit ints into double bufs // see atom_vec.h for documentation union ubuf { double d; int64_t i; ubuf(double arg) : d(arg) {} ubuf(int64_t arg) : i(arg) {} ubuf(int arg) : i(arg) {} }; inline int sbmask(int j) const { return j >> SBBITS & 3; } }; } #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Too many total bits for bitmapped lookup table Table size specified via pair_modify command is too large. Note that a value of N generates a 2^N size table. E: Cannot have both pair_modify shift and tail set to yes These 2 options are contradictory. E: Cannot use pair tail corrections with 2d simulations The correction factors are only currently defined for 3d systems. W: Using pair tail corrections with nonperiodic system This is probably a bogus thing to do, since tail corrections are computed by integrating the density of a periodic system out to infinity. W: Using pair tail corrections with pair_modify compute no The tail corrections will thus not be computed. W: Using pair potential shift with pair_modify compute no The shift effects will thus not be computed. W: Using a manybody potential with bonds/angles/dihedrals and special_bond exclusions This is likely not what you want to do. The exclusion settings will eliminate neighbors in the neighbor list, which the manybody potential needs to calculated its terms correctly. E: All pair coeffs are not set All pair coefficients must be set in the data file or by the pair_coeff command before running a simulation. E: Fix adapt interface to this pair style not supported New coding for the pair style would need to be done. E: Pair style requires a KSpace style No kspace style is defined. E: Cannot yet use compute tally with Kokkos This feature is not yet supported. E: Pair style does not support pair_write The pair style does not have a single() function, so it can not be invoked by pair write. E: Invalid atom types in pair_write command Atom types must range from 1 to Ntypes inclusive. E: Invalid style in pair_write command Self-explanatory. Check the input script. E: Invalid cutoffs in pair_write command Inner cutoff must be larger than 0.0 and less than outer cutoff. E: Cannot open pair_write file The specified output file for pair energies and forces cannot be opened. Check that the path and name are correct. E: Bitmapped lookup tables require int/float be same size Cannot use pair tables on this machine, because of word sizes. Use the pair_modify command with table 0 instead. W: Table inner cutoff >= outer cutoff You specified an inner cutoff for a Coulombic table that is longer than the global cutoff. Probably not what you wanted. E: Too many exponent bits for lookup table Table size specified via pair_modify command does not work with your machine's floating point representation. E: Too many mantissa bits for lookup table Table size specified via pair_modify command does not work with your machine's floating point representation. E: Too few bits for lookup table Table size specified via pair_modify command does not work with your machine's floating point representation. */ diff --git a/src/pair_lj96_cut.cpp b/src/pair_lj96_cut.cpp index 83fc5bcdd..842b918fe 100644 --- a/src/pair_lj96_cut.cpp +++ b/src/pair_lj96_cut.cpp @@ -1,722 +1,696 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Chuanfu Luo (luochuanfu@gmail.com) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj96_cut.h" #include "atom.h" #include "comm.h" #include "force.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; /* ---------------------------------------------------------------------- */ PairLJ96Cut::PairLJ96Cut(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; writedata = 1; } /* ---------------------------------------------------------------------- */ PairLJ96Cut::~PairLJ96Cut() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(offset); } } /* ---------------------------------------------------------------------- */ void PairLJ96Cut::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJ96Cut::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj,rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 - rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJ96Cut::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj,rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJ96Cut::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj,rsw; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; 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]) { if (rsq > cut_in_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } if (eflag) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } if (vflag) { if (rsq <= cut_in_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; } else if (rsq < cut_in_on_sq) fpair = factor_lj*forcelj*r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJ96Cut::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut,n+1,n+1,"pair:cut"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJ96Cut::settings(int narg, char **arg) { if (narg != 1) error->all(FLERR,"Illegal pair_style command"); cut_global = force->numeric(FLERR,arg[0]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut[i][j] = cut_global; } } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJ96Cut::coeff(int narg, char **arg) { if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double cut_one = cut_global; if (narg == 5) cut_one = force->numeric(FLERR,arg[4]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; cut[i][j] = cut_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJ96Cut::init_style() { - // request regular or rRESPA neighbor lists + // request regular or rRESPA neighbor list int irequest; + int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; + } - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } + irequest = neighbor->request(this,instance_me); - } else irequest = neighbor->request(this,instance_me); + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJ96Cut::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJ96Cut::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); cut[i][j] = mix_distance(cut[i][i],cut[j][j]); } lj1[i][j] = 36.0 * epsilon[i][j] * pow(sigma[i][j],9.0); lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],9.0); lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0); if (offset_flag && (cut[i][j] > 0.0)) { double ratio = sigma[i][j] / cut[i][j]; offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,9.0) - pow(ratio,6.0)); } else offset[i][j] = 0.0; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; offset[j][i] = offset[i][j]; // check interior rRESPA cutoff if (cut_respa && cut[i][j] < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); // compute I,J contribution to long-range tail correction // count total # of atoms of type I and J via Allreduce if (tail_flag) { int *type = atom->type; int nlocal = atom->nlocal; double count[2],all[2]; count[0] = count[1] = 0.0; for (int k = 0; k < nlocal; k++) { if (type[k] == i) count[0] += 1.0; if (type[k] == j) count[1] += 1.0; } MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world); double sig3 = sigma[i][j]*sigma[i][j]*sigma[i][j]; double sig6 = sig3*sig3; double rc3 = cut[i][j]*cut[i][j]*cut[i][j]; double rc6 = rc3*rc3; etail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] * sig6 * (sig3 - 2.0*rc3) / (6.0*rc6); ptail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] * sig6 * (3.0*sig3 - 4.0*rc3) / (6.0*rc6); } return cut[i][j]; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJ96Cut::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&cut[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJ96Cut::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&cut[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJ96Cut::write_restart_settings(FILE *fp) { fwrite(&cut_global,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&tail_flag,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJ96Cut::read_restart_settings(FILE *fp) { int me = comm->me; if (me == 0) { fread(&cut_global,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&tail_flag,sizeof(int),1,fp); } MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&tail_flag,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJ96Cut::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g\n",i,epsilon[i][i],sigma[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJ96Cut::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g\n",i,j,epsilon[i][j],sigma[i][j],cut[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJ96Cut::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv,r3inv,r6inv,forcelj,philj; r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; r3inv = sqrt(r6inv); forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); fforce = factor_lj*forcelj*r2inv; philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - offset[itype][jtype]; return factor_lj*philj; } diff --git a/src/pair_lj96_cut.h b/src/pair_lj96_cut.h index 6b677c642..4d6df0212 100644 --- a/src/pair_lj96_cut.h +++ b/src/pair_lj96_cut.h @@ -1,82 +1,81 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj96/cut,PairLJ96Cut) #else #ifndef LMP_PAIR_LJ96_CUT_H #define LMP_PAIR_LJ96_CUT_H #include "pair.h" namespace LAMMPS_NS { class PairLJ96Cut : public Pair { public: PairLJ96Cut(class LAMMPS *); virtual ~PairLJ96Cut(); virtual void compute(int, int); void settings(int, char **); void coeff(int, char **); void init_style(); - void init_list(int, class NeighList *); double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); void compute_outer(int, int); protected: double cut_global; double **cut; double **epsilon,**sigma; double **lj1,**lj2,**lj3,**lj4,**offset; double *cut_respa; void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/pair_lj_cut.cpp b/src/pair_lj_cut.cpp index 7f838061f..215fabecb 100644 --- a/src/pair_lj_cut.cpp +++ b/src/pair_lj_cut.cpp @@ -1,725 +1,699 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Paul Crozier (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_lj_cut.h" #include "atom.h" #include "comm.h" #include "force.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; /* ---------------------------------------------------------------------- */ PairLJCut::PairLJCut(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; writedata = 1; } /* ---------------------------------------------------------------------- */ PairLJCut::~PairLJCut() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(lj1); memory->destroy(lj2); memory->destroy(lj3); memory->destroy(lj4); memory->destroy(offset); } } /* ---------------------------------------------------------------------- */ void PairLJCut::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,r2inv,r6inv,forcelj,factor_lj; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairLJCut::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcelj,factor_lj,rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 - rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCut::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,r6inv,forcelj,factor_lj,rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; jtype = type[j]; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairLJCut::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,r2inv,r6inv,forcelj,factor_lj,rsw; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_lj = force->special_lj; int newton_pair = force->newton_pair; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_lj = special_lj[sbmask(j)]; j &= NEIGHMASK; 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]) { if (rsq > cut_in_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } if (eflag) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; evdwl *= factor_lj; } if (vflag) { if (rsq <= cut_in_off_sq) { r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fpair = factor_lj*forcelj*r2inv; } else if (rsq < cut_in_on_sq) fpair = factor_lj*forcelj*r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairLJCut::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut,n+1,n+1,"pair:cut"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(lj1,n+1,n+1,"pair:lj1"); memory->create(lj2,n+1,n+1,"pair:lj2"); memory->create(lj3,n+1,n+1,"pair:lj3"); memory->create(lj4,n+1,n+1,"pair:lj4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairLJCut::settings(int narg, char **arg) { if (narg != 1) error->all(FLERR,"Illegal pair_style command"); cut_global = force->numeric(FLERR,arg[0]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut[i][j] = cut_global; } } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairLJCut::coeff(int narg, char **arg) { if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double cut_one = cut_global; if (narg == 5) cut_one = force->numeric(FLERR,arg[4]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; cut[i][j] = cut_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairLJCut::init_style() { - // request regular or rRESPA neighbor lists + // request regular or rRESPA neighbor list int irequest; + int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; + } - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } + irequest = neighbor->request(this,instance_me); - } else irequest = neighbor->request(this,instance_me); + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairLJCut::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairLJCut::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); cut[i][j] = mix_distance(cut[i][i],cut[j][j]); } lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0); lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0); lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0); if (offset_flag && (cut[i][j] > 0.0)) { double ratio = sigma[i][j] / cut[i][j]; offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0)); } else offset[i][j] = 0.0; lj1[j][i] = lj1[i][j]; lj2[j][i] = lj2[i][j]; lj3[j][i] = lj3[i][j]; lj4[j][i] = lj4[i][j]; offset[j][i] = offset[i][j]; // check interior rRESPA cutoff if (cut_respa && cut[i][j] < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); // compute I,J contribution to long-range tail correction // count total # of atoms of type I and J via Allreduce if (tail_flag) { int *type = atom->type; int nlocal = atom->nlocal; double count[2],all[2]; count[0] = count[1] = 0.0; for (int k = 0; k < nlocal; k++) { if (type[k] == i) count[0] += 1.0; if (type[k] == j) count[1] += 1.0; } MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world); double sig2 = sigma[i][j]*sigma[i][j]; double sig6 = sig2*sig2*sig2; double rc3 = cut[i][j]*cut[i][j]*cut[i][j]; double rc6 = rc3*rc3; double rc9 = rc3*rc6; etail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] * sig6 * (sig6 - 3.0*rc6) / (9.0*rc9); ptail_ij = 16.0*MY_PI*all[0]*all[1]*epsilon[i][j] * sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9); } return cut[i][j]; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCut::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&cut[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCut::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&cut[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairLJCut::write_restart_settings(FILE *fp) { fwrite(&cut_global,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&tail_flag,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairLJCut::read_restart_settings(FILE *fp) { int me = comm->me; if (me == 0) { fread(&cut_global,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&tail_flag,sizeof(int),1,fp); } MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&tail_flag,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void PairLJCut::write_data(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) fprintf(fp,"%d %g %g\n",i,epsilon[i][i],sigma[i][i]); } /* ---------------------------------------------------------------------- proc 0 writes all pairs to data file ------------------------------------------------------------------------- */ void PairLJCut::write_data_all(FILE *fp) { for (int i = 1; i <= atom->ntypes; i++) for (int j = i; j <= atom->ntypes; j++) fprintf(fp,"%d %d %g %g %g\n",i,j,epsilon[i][j],sigma[i][j],cut[i][j]); } /* ---------------------------------------------------------------------- */ double PairLJCut::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_lj, double &fforce) { double r2inv,r6inv,forcelj,philj; r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); fforce = factor_lj*forcelj*r2inv; philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - offset[itype][jtype]; return factor_lj*philj; } /* ---------------------------------------------------------------------- */ void *PairLJCut::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; return NULL; } diff --git a/src/pair_lj_cut.h b/src/pair_lj_cut.h index 43eeda09c..3724685db 100644 --- a/src/pair_lj_cut.h +++ b/src/pair_lj_cut.h @@ -1,82 +1,81 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(lj/cut,PairLJCut) #else #ifndef LMP_PAIR_LJ_CUT_H #define LMP_PAIR_LJ_CUT_H #include "pair.h" namespace LAMMPS_NS { class PairLJCut : public Pair { public: PairLJCut(class LAMMPS *); virtual ~PairLJCut(); virtual void compute(int, int); void settings(int, char **); void coeff(int, char **); void init_style(); - void init_list(int, class NeighList *); double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); void write_data(FILE *); void write_data_all(FILE *); double single(int, int, int, int, double, double, double, double &); void *extract(const char *, int &); void compute_inner(); void compute_middle(); void compute_outer(int, int); protected: double cut_global; double **cut; double **epsilon,**sigma; double **lj1,**lj2,**lj3,**lj4,**offset; double *cut_respa; virtual void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/pair_mie_cut.cpp b/src/pair_mie_cut.cpp index 320f21248..04f8de8d7 100644 --- a/src/pair_mie_cut.cpp +++ b/src/pair_mie_cut.cpp @@ -1,738 +1,712 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author: Cassiano Aimoli (aimoli@gmail.com) ------------------------------------------------------------------------- */ #include #include #include #include #include "pair_mie_cut.h" #include "atom.h" #include "comm.h" #include "force.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "update.h" #include "integrate.h" #include "respa.h" #include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; using namespace MathConst; /* ---------------------------------------------------------------------- */ PairMIECut::PairMIECut(LAMMPS *lmp) : Pair(lmp) { respa_enable = 1; } /* ---------------------------------------------------------------------- */ PairMIECut::~PairMIECut() { if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cut); memory->destroy(epsilon); memory->destroy(sigma); memory->destroy(gamR); memory->destroy(gamA); memory->destroy(Cmie); memory->destroy(mie1); memory->destroy(mie2); memory->destroy(mie3); memory->destroy(mie4); memory->destroy(offset); } } /* ---------------------------------------------------------------------- */ void PairMIECut::compute(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,r2inv,rgamR,rgamA,forcemie,factor_mie; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = vflag_fdotr = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_mie = force->special_lj; int newton_pair = force->newton_pair; inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_mie = special_mie[sbmask(j)]; j &= NEIGHMASK; 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]) { r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); forcemie = (mie1[itype][jtype]*rgamR - mie2[itype][jtype]*rgamA); fpair = factor_mie*forcemie*r2inv; f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } if (eflag) { evdwl = (mie3[itype][jtype]*rgamR - mie4[itype][jtype]*rgamA) - offset[itype][jtype]; evdwl *= factor_mie; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } if (vflag_fdotr) virial_fdotr_compute(); } /* ---------------------------------------------------------------------- */ void PairMIECut::compute_inner() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,rgamR,rgamA,forcemie,factor_mie,rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_mie = force->special_lj; int newton_pair = force->newton_pair; - inum = listinner->inum; - ilist = listinner->ilist; - numneigh = listinner->numneigh; - firstneigh = listinner->firstneigh; + inum = list->inum_inner; + ilist = list->ilist_inner; + numneigh = list->numneigh_inner; + firstneigh = list->firstneigh_inner; double cut_out_on = cut_respa[0]; double cut_out_off = cut_respa[1]; double cut_out_diff = cut_out_off - cut_out_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_mie = special_mie[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq) { jtype = type[j]; r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); forcemie = (mie1[itype][jtype]*rgamR - mie2[itype][jtype]*rgamA); fpair = factor_mie*forcemie*r2inv; if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 - rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairMIECut::compute_middle() { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,fpair; double rsq,r2inv,rgamR,rgamA,forcemie,factor_mie,rsw; int *ilist,*jlist,*numneigh,**firstneigh; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_mie = force->special_lj; int newton_pair = force->newton_pair; - inum = listmiddle->inum; - ilist = listmiddle->ilist; - numneigh = listmiddle->numneigh; - firstneigh = listmiddle->firstneigh; + inum = list->inum_middle; + ilist = list->ilist_middle; + numneigh = list->numneigh_middle; + firstneigh = list->firstneigh_middle; double cut_in_off = cut_respa[0]; double cut_in_on = cut_respa[1]; double cut_out_on = cut_respa[2]; double cut_out_off = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_out_diff = cut_out_off - cut_out_on; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; double cut_out_on_sq = cut_out_on*cut_out_on; double cut_out_off_sq = cut_out_off*cut_out_off; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_mie = special_mie[sbmask(j)]; j &= NEIGHMASK; delx = xtmp - x[j][0]; dely = ytmp - x[j][1]; delz = ztmp - x[j][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) { jtype = type[j]; r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); forcemie = (mie1[itype][jtype]*rgamR - mie2[itype][jtype]*rgamA); fpair = factor_mie*forcemie*r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } if (rsq > cut_out_on_sq) { rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff; fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } } } } /* ---------------------------------------------------------------------- */ void PairMIECut::compute_outer(int eflag, int vflag) { int i,j,ii,jj,inum,jnum,itype,jtype; double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair; double rsq,r2inv,rgamR,rgamA,forcemie,factor_mie,rsw; int *ilist,*jlist,*numneigh,**firstneigh; evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else evflag = 0; double **x = atom->x; double **f = atom->f; int *type = atom->type; int nlocal = atom->nlocal; double *special_mie = force->special_lj; int newton_pair = force->newton_pair; - inum = listouter->inum; - ilist = listouter->ilist; - numneigh = listouter->numneigh; - firstneigh = listouter->firstneigh; + inum = list->inum; + ilist = list->ilist; + numneigh = list->numneigh; + firstneigh = list->firstneigh; double cut_in_off = cut_respa[2]; double cut_in_on = cut_respa[3]; double cut_in_diff = cut_in_on - cut_in_off; double cut_in_off_sq = cut_in_off*cut_in_off; double cut_in_on_sq = cut_in_on*cut_in_on; // loop over neighbors of my atoms for (ii = 0; ii < inum; ii++) { i = ilist[ii]; xtmp = x[i][0]; ytmp = x[i][1]; ztmp = x[i][2]; itype = type[i]; jlist = firstneigh[i]; jnum = numneigh[i]; for (jj = 0; jj < jnum; jj++) { j = jlist[jj]; factor_mie = special_mie[sbmask(j)]; j &= NEIGHMASK; 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]) { if (rsq > cut_in_off_sq) { r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); forcemie = (mie1[itype][jtype]*rgamR - mie2[itype][jtype]*rgamA); fpair = factor_mie*forcemie*r2inv; if (rsq < cut_in_on_sq) { rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff; fpair *= rsw*rsw*(3.0 - 2.0*rsw); } f[i][0] += delx*fpair; f[i][1] += dely*fpair; f[i][2] += delz*fpair; if (newton_pair || j < nlocal) { f[j][0] -= delx*fpair; f[j][1] -= dely*fpair; f[j][2] -= delz*fpair; } } if (eflag) { r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); evdwl = (mie3[itype][jtype]*rgamR - mie4[itype][jtype]*rgamA) - offset[itype][jtype]; evdwl *= factor_mie; } if (vflag) { if (rsq <= cut_in_off_sq) { r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); forcemie = (mie1[itype][jtype]*rgamR - mie2[itype][jtype]*rgamA); fpair = factor_mie*forcemie*r2inv; } else if (rsq < cut_in_on_sq) fpair = factor_mie*forcemie*r2inv; } if (evflag) ev_tally(i,j,nlocal,newton_pair, evdwl,0.0,fpair,delx,dely,delz); } } } } /* ---------------------------------------------------------------------- allocate all arrays ------------------------------------------------------------------------- */ void PairMIECut::allocate() { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cut,n+1,n+1,"pair:cut"); memory->create(epsilon,n+1,n+1,"pair:epsilon"); memory->create(sigma,n+1,n+1,"pair:sigma"); memory->create(gamR,n+1,n+1,"pair:gamR"); memory->create(gamA,n+1,n+1,"pair:gamA"); memory->create(Cmie,n+1,n+1,"pair:Cmie"); memory->create(mie1,n+1,n+1,"pair:mie1"); memory->create(mie2,n+1,n+1,"pair:mie2"); memory->create(mie3,n+1,n+1,"pair:mie3"); memory->create(mie4,n+1,n+1,"pair:mie4"); memory->create(offset,n+1,n+1,"pair:offset"); } /* ---------------------------------------------------------------------- global settings ------------------------------------------------------------------------- */ void PairMIECut::settings(int narg, char **arg) { if (narg != 1) error->all(FLERR,"Illegal pair_style command"); cut_global = force->numeric(FLERR,arg[0]); // reset cutoffs that have been explicitly set if (allocated) { int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) if (setflag[i][j]) cut[i][j] = cut_global; } } /* ---------------------------------------------------------------------- set coeffs for one or more type pairs ------------------------------------------------------------------------- */ void PairMIECut::coeff(int narg, char **arg) { if (narg < 6 || narg > 7) error->all(FLERR,"Incorrect args for pair coefficients"); if (!allocated) allocate(); int ilo,ihi,jlo,jhi; force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); double epsilon_one = force->numeric(FLERR,arg[2]); double sigma_one = force->numeric(FLERR,arg[3]); double gamR_one = force->numeric(FLERR,arg[4]); double gamA_one = force->numeric(FLERR,arg[5]); double cut_one = cut_global; if (narg == 7) cut_one = force->numeric(FLERR,arg[6]); int count = 0; for (int i = ilo; i <= ihi; i++) { for (int j = MAX(jlo,i); j <= jhi; j++) { epsilon[i][j] = epsilon_one; sigma[i][j] = sigma_one; gamR[i][j] = gamR_one; gamA[i][j] = gamA_one; cut[i][j] = cut_one; setflag[i][j] = 1; count++; } } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- init specific to this pair style ------------------------------------------------------------------------- */ void PairMIECut::init_style() { - // request regular or rRESPA neighbor lists + // request regular or rRESPA neighbor list int irequest; + int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { - int respa = 0; if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; + } - if (respa == 0) irequest = neighbor->request(this,instance_me); - else if (respa == 1) { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } else { - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 1; - neighbor->requests[irequest]->respainner = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 2; - neighbor->requests[irequest]->respamiddle = 1; - irequest = neighbor->request(this,instance_me); - neighbor->requests[irequest]->id = 3; - neighbor->requests[irequest]->respaouter = 1; - } + irequest = neighbor->request(this,instance_me); - } else irequest = neighbor->request(this,instance_me); + if (respa >= 1) { + neighbor->requests[irequest]->respaouter = 1; + neighbor->requests[irequest]->respainner = 1; + } + if (respa == 2) neighbor->requests[irequest]->respamiddle = 1; // set rRESPA cutoffs if (strstr(update->integrate_style,"respa") && ((Respa *) update->integrate)->level_inner >= 0) cut_respa = ((Respa *) update->integrate)->cutoff; else cut_respa = NULL; } -/* ---------------------------------------------------------------------- - neighbor callback to inform pair style of neighbor list to use - regular or rRESPA -------------------------------------------------------------------------- */ - -void PairMIECut::init_list(int id, NeighList *ptr) -{ - if (id == 0) list = ptr; - else if (id == 1) listinner = ptr; - else if (id == 2) listmiddle = ptr; - else if (id == 3) listouter = ptr; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ double PairMIECut::init_one(int i, int j) { if (setflag[i][j] == 0) { epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j], sigma[i][i],sigma[j][j]); sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]); gamR[i][j] = mix_distance(gamR[i][i],gamR[j][j]); gamA[i][j] = mix_distance(gamA[i][i],gamA[j][j]); cut[i][j] = mix_distance(cut[i][i],cut[j][j]); } gamA[j][i] = gamA[i][j]; gamR[j][i] = gamR[i][j]; Cmie[i][j] = (gamR[i][j]/(gamR[i][j]-gamA[i][j]) * pow((gamR[i][j]/gamA[i][j]), (gamA[i][j]/(gamR[i][j]-gamA[i][j])))); mie1[i][j] = Cmie[i][j] * gamR[i][j]* epsilon[i][j] * pow(sigma[i][j],gamR[i][j]); mie2[i][j] = Cmie[i][j] * gamA[i][j] * epsilon[i][j] * pow(sigma[i][j],gamA[i][j]); mie3[i][j] = Cmie[i][j] * epsilon[i][j] * pow(sigma[i][j],gamR[i][j]); mie4[i][j] = Cmie[i][j] * epsilon[i][j] * pow(sigma[i][j],gamA[i][j]); if (offset_flag && (cut[i][j] > 0.0)) { double ratio = sigma[i][j] / cut[i][j]; offset[i][j] = Cmie[i][j] * epsilon[i][j] * (pow(ratio,gamR[i][j]) - pow(ratio,gamA[i][j])); } else offset[i][j] = 0.0; mie1[j][i] = mie1[i][j]; mie2[j][i] = mie2[i][j]; mie3[j][i] = mie3[i][j]; mie4[j][i] = mie4[i][j]; offset[j][i] = offset[i][j]; // check interior rRESPA cutoff if (cut_respa && cut[i][j] < cut_respa[3]) error->all(FLERR,"Pair cutoff < Respa interior cutoff"); // compute I,J contribution to long-range tail correction // count total # of atoms of type I and J via Allreduce if (tail_flag) { int *type = atom->type; int nlocal = atom->nlocal; double count[2],all[2]; count[0] = count[1] = 0.0; for (int k = 0; k < nlocal; k++) { if (type[k] == i) count[0] += 1.0; if (type[k] == j) count[1] += 1.0; } MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world); double siggamA = pow(sigma[i][j],gamA[i][j]); double siggamR = pow(sigma[i][j],gamR[i][j]); double rcgamA = pow(cut[i][j],(gamA[i][j]-3.0)); double rcgamR = pow(cut[i][j],(gamR[i][j]-3.0)); etail_ij = Cmie[i][j]*2.0*MY_PI*all[0]*all[1]*epsilon[i][j]* (siggamR/((gamR[i][j]-3.0)*rcgamR)-siggamA/((gamA[i][j]-3.0)*rcgamA)); ptail_ij = Cmie[i][j]*2.0*MY_PI*all[0]*all[1]*epsilon[i][j]/3.0* ((gamR[i][j]/(gamR[i][j]-3.0))*siggamR/rcgamR- (gamA[i][j]/(gamA[i][j]-3.0))*siggamA/rcgamA); } return cut[i][j]; } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairMIECut::write_restart(FILE *fp) { write_restart_settings(fp); int i,j; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { fwrite(&setflag[i][j],sizeof(int),1,fp); if (setflag[i][j]) { fwrite(&epsilon[i][j],sizeof(double),1,fp); fwrite(&sigma[i][j],sizeof(double),1,fp); fwrite(&gamR[i][j],sizeof(double),1,fp); fwrite(&gamA[i][j],sizeof(double),1,fp); fwrite(&cut[i][j],sizeof(double),1,fp); } } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairMIECut::read_restart(FILE *fp) { read_restart_settings(fp); allocate(); int i,j; int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { fread(&epsilon[i][j],sizeof(double),1,fp); fread(&sigma[i][j],sizeof(double),1,fp); fread(&gamR[i][j],sizeof(double),1,fp); fread(&gamA[i][j],sizeof(double),1,fp); fread(&cut[i][j],sizeof(double),1,fp); } MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&gamR[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&gamA[i][j],1,MPI_DOUBLE,0,world); MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world); } } } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void PairMIECut::write_restart_settings(FILE *fp) { fwrite(&cut_global,sizeof(double),1,fp); fwrite(&offset_flag,sizeof(int),1,fp); fwrite(&mix_flag,sizeof(int),1,fp); fwrite(&tail_flag,sizeof(int),1,fp); } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void PairMIECut::read_restart_settings(FILE *fp) { int me = comm->me; if (me == 0) { fread(&cut_global,sizeof(double),1,fp); fread(&offset_flag,sizeof(int),1,fp); fread(&mix_flag,sizeof(int),1,fp); fread(&tail_flag,sizeof(int),1,fp); } MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world); MPI_Bcast(&offset_flag,1,MPI_INT,0,world); MPI_Bcast(&mix_flag,1,MPI_INT,0,world); MPI_Bcast(&tail_flag,1,MPI_INT,0,world); } /* ---------------------------------------------------------------------- */ double PairMIECut::single(int i, int j, int itype, int jtype, double rsq, double factor_coul, double factor_mie, double &fforce) { double r2inv,rgamR,rgamA,forcemie,phimie; r2inv = 1.0/rsq; rgamA = pow(r2inv,(gamA[itype][jtype]/2.0)); rgamR = pow(r2inv,(gamR[itype][jtype]/2.0)); forcemie = (mie1[itype][jtype]*rgamR - mie2[itype][jtype]*rgamA); fforce = factor_mie*forcemie*r2inv; phimie = (mie3[itype][jtype]*rgamR - mie4[itype][jtype]*rgamA) - offset[itype][jtype]; return factor_mie*phimie; } /* ---------------------------------------------------------------------- */ void *PairMIECut::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"epsilon") == 0) return (void *) epsilon; if (strcmp(str,"sigma") == 0) return (void *) sigma; if (strcmp(str,"gamR") == 0) return (void *) gamR; if (strcmp(str,"gamA") == 0) return (void *) gamA; return NULL; } diff --git a/src/pair_mie_cut.h b/src/pair_mie_cut.h index 2a0a29843..9e12438d1 100644 --- a/src/pair_mie_cut.h +++ b/src/pair_mie_cut.h @@ -1,81 +1,80 @@ /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ #ifdef PAIR_CLASS PairStyle(mie/cut,PairMIECut) #else #ifndef LMP_PAIR_MIE_CUT_H #define LMP_PAIR_MIE_CUT_H #include "pair.h" namespace LAMMPS_NS { class PairMIECut : public Pair { public: PairMIECut(class LAMMPS *); virtual ~PairMIECut(); virtual void compute(int, int); void settings(int, char **); void coeff(int, char **); void init_style(); - void init_list(int, class NeighList *); double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); double single(int, int, int, int, double, double, double, double &); void *extract(const char *, int &); void compute_inner(); void compute_middle(); void compute_outer(int, int); protected: double cut_global; double **cut; double **epsilon,**sigma; double **gamR,**gamA,**Cmie; double **mie1,**mie2,**mie3,**mie4,**offset; double *cut_respa; void allocate(); }; } #endif #endif /* ERROR/WARNING messages: E: Illegal ... command Self-explanatory. Check the input script syntax and compare to the documentation for the command. You can use -echo screen as a command-line option when running LAMMPS to see the offending line. E: Incorrect args for pair coefficients Self-explanatory. Check the input script or data file. E: Pair cutoff < Respa interior cutoff One or more pairwise cutoffs are too short to use with the specified rRESPA cutoffs. */ diff --git a/src/respa.cpp b/src/respa.cpp index 5d51ff64e..23cd94183 100644 --- a/src/respa.cpp +++ b/src/respa.cpp @@ -1,878 +1,885 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing authors: Mark Stevens (SNL), Paul Crozier (SNL) ------------------------------------------------------------------------- */ #include #include #include "respa.h" #include "neighbor.h" #include "atom.h" #include "atom_vec.h" #include "domain.h" #include "comm.h" #include "force.h" #include "pair.h" #include "bond.h" #include "angle.h" #include "dihedral.h" #include "improper.h" #include "kspace.h" #include "output.h" #include "update.h" #include "modify.h" #include "compute.h" #include "fix_respa.h" #include "timer.h" #include "memory.h" #include "error.h" #include "pair_hybrid.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ Respa::Respa(LAMMPS *lmp, int narg, char **arg) : Integrate(lmp, narg, arg), step(NULL), loop(NULL), hybrid_level(NULL), hybrid_compute(NULL), newton(NULL), fix_respa(NULL) { nhybrid_styles = 0; if (narg < 1) error->all(FLERR,"Illegal run_style respa command"); nlevels = force->inumeric(FLERR,arg[0]); if (nlevels < 1) error->all(FLERR,"Respa levels must be >= 1"); if (narg < nlevels) error->all(FLERR,"Illegal run_style respa command"); loop = new int[nlevels]; for (int iarg = 1; iarg < nlevels; iarg++) { loop[iarg-1] = force->inumeric(FLERR,arg[iarg]); if (loop[iarg-1] <= 0) error->all(FLERR,"Illegal run_style respa command"); } loop[nlevels-1] = 1; // set level at which each force is computed // argument settings override defaults level_bond = level_angle = level_dihedral = level_improper = -1; level_pair = level_kspace = -1; level_inner = level_middle = level_outer = -1; // defaults for hybrid pair styles nhybrid_styles = 0; tally_global = 1; pair_compute = 1; int iarg = nlevels; while (iarg < narg) { if (strcmp(arg[iarg],"bond") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_bond = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"angle") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_angle = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"dihedral") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_dihedral = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"improper") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_improper = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"pair") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_pair = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"inner") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal run_style respa command"); level_inner = force->inumeric(FLERR,arg[iarg+1]) - 1; cutoff[0] = force->numeric(FLERR,arg[iarg+2]); cutoff[1] = force->numeric(FLERR,arg[iarg+3]); iarg += 4; } else if (strcmp(arg[iarg],"middle") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal run_style respa command"); level_middle = force->inumeric(FLERR,arg[iarg+1]) - 1; cutoff[2] = force->numeric(FLERR,arg[iarg+2]); cutoff[3] = force->numeric(FLERR,arg[iarg+3]); iarg += 4; } else if (strcmp(arg[iarg],"outer") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_outer = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"kspace") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command"); level_kspace = force->inumeric(FLERR,arg[iarg+1]) - 1; iarg += 2; } else if (strcmp(arg[iarg],"hybrid") == 0) { // the hybrid keyword requires a hybrid pair style if (!strstr(force->pair_style,"hybrid")) error->all(FLERR,"Illegal run_style respa command"); PairHybrid *hybrid = (PairHybrid *) force->pair; nhybrid_styles = hybrid->nstyles; // each hybrid sub-style needs to be assigned to a respa level if (iarg+nhybrid_styles > narg) error->all(FLERR,"Illegal run_style respa command"); hybrid_level = new int[nhybrid_styles]; hybrid_compute = new int[nhybrid_styles]; for (int i=0; i < nhybrid_styles; ++i) { ++iarg; hybrid_level[i] = force->inumeric(FLERR,arg[iarg])-1; } ++iarg; } else error->all(FLERR,"Illegal run_style respa command"); } // cannot specify both pair and inner/middle/outer if (level_pair >= 0 && (level_inner >= 0 || level_middle >= 0 || level_outer >= 0)) error->all(FLERR,"Cannot set both respa pair and inner/middle/outer"); // if either inner and outer is specified, then both must be if ((level_inner >= 0 && level_outer == -1) || (level_outer >= 0 && level_inner == -1)) error->all(FLERR,"Must set both respa inner and outer"); // middle cannot be set without inner/outer if (level_middle >= 0 && level_inner == -1) error->all(FLERR,"Cannot set respa middle without inner/outer"); // cannot combine hybrid with any of pair/inner/middle/outer if ((nhybrid_styles > 0) && (level_pair >= 0 || level_inner >= 0 || level_middle >= 0 || level_outer >= 0)) error->all(FLERR,"Cannot set respa hybrid and " "any of pair/inner/middle/outer"); // set defaults if user did not specify level // bond to innermost level // angle same as bond, dihedral same as angle, improper same as dihedral // pair to outermost level if no inner/middle/outer // inner/middle/outer have no defaults // kspace same as pair or outer if (level_bond == -1) level_bond = 0; if (level_angle == -1) level_angle = level_bond; if (level_dihedral == -1) level_dihedral = level_angle; if (level_improper == -1) level_improper = level_dihedral; if (level_pair == -1 && level_inner == -1 && nhybrid_styles < 1) level_pair = nlevels-1; if (level_kspace == -1 && level_pair >= 0) level_kspace = level_pair; if (level_kspace == -1 && level_pair == -1) { if (nhybrid_styles < 1) { level_kspace = level_outer; } else { int max_hybrid_level = -1; for (int i=0; i < nhybrid_styles; ++i) { if (max_hybrid_level < hybrid_level[i]) max_hybrid_level = hybrid_level[i]; } level_kspace = max_hybrid_level; } } // print respa levels if (comm->me == 0) { if (screen) { fprintf(screen,"Respa levels:\n"); for (int i = 0; i < nlevels; i++) { fprintf(screen," %d =",i+1); if (level_bond == i) fprintf(screen," bond"); if (level_angle == i) fprintf(screen," angle"); if (level_dihedral == i) fprintf(screen," dihedral"); if (level_improper == i) fprintf(screen," improper"); if (level_pair == i) fprintf(screen," pair"); if (level_inner == i) fprintf(screen," pair-inner"); if (level_middle == i) fprintf(screen," pair-middle"); if (level_outer == i) fprintf(screen," pair-outer"); for (int j=0;jall(FLERR,"Invalid order of forces within respa levels"); if (level_pair >= 0) { if (level_pair < level_improper || level_kspace < level_pair) error->all(FLERR,"Invalid order of forces within respa levels"); } if (level_pair == -1 && level_middle == -1 && nhybrid_styles < 1) { if (level_inner < level_improper || level_outer < level_inner || level_kspace < level_outer) error->all(FLERR,"Invalid order of forces within respa levels"); } if (level_pair == -1 && level_middle >= 0) { if (level_inner < level_improper || level_middle < level_inner || level_outer < level_inner || level_kspace < level_outer) error->all(FLERR,"Invalid order of forces within respa levels"); } // warn if any levels are devoid of forces int flag = 0; for (int i = 0; i < nlevels; i++) if (level_bond != i && level_angle != i && level_dihedral != i && level_improper != i && level_pair != i && level_inner != i && level_middle != i && level_outer != i && level_kspace != i) flag = 1; if (flag && comm->me == 0) error->warning(FLERR,"One or more respa levels compute no forces"); // check cutoff consistency if inner/middle/outer are enabled if (level_inner >= 0 && cutoff[1] < cutoff[0]) error->all(FLERR,"Respa inner cutoffs are invalid"); if (level_middle >= 0 && (cutoff[3] < cutoff[2] || cutoff[2] < cutoff[1])) error->all(FLERR,"Respa middle cutoffs are invalid"); // set outer pair of cutoffs to inner pair if middle is not enabled if (level_inner >= 0 && level_middle < 0) { cutoff[2] = cutoff[0]; cutoff[3] = cutoff[1]; } // ensure that pair->compute() is run properly // when the hybrid keyword is not used if (nhybrid_styles < 1) { pair_compute = 1; tally_global = 1; } // allocate other needed arrays newton = new int[nlevels]; step = new double[nlevels]; } /* ---------------------------------------------------------------------- */ Respa::~Respa() { delete [] loop; delete [] newton; delete [] step; if (nhybrid_styles > 0) { delete [] hybrid_level; delete [] hybrid_compute; } } /* ---------------------------------------------------------------------- initialization before run ------------------------------------------------------------------------- */ void Respa::init() { Integrate::init(); // warn if no fixes if (modify->nfix == 0 && comm->me == 0) error->warning(FLERR,"No fixes defined, atoms won't move"); // create fix needed for storing atom-based respa level forces // will delete it at end of run char **fixarg = new char*[5]; fixarg[0] = (char *) "RESPA"; fixarg[1] = (char *) "all"; fixarg[2] = (char *) "RESPA"; fixarg[3] = new char[8]; sprintf(fixarg[3],"%d",nlevels); // if supported, we also store torques on a per-level basis if (atom->torque_flag) { fixarg[4] = (char *) "torque"; modify->add_fix(5,fixarg); } else { modify->add_fix(4,fixarg); } delete [] fixarg[3]; delete [] fixarg; fix_respa = (FixRespa *) modify->fix[modify->nfix-1]; // insure respa inner/middle/outer is using Pair class that supports it if (level_inner >= 0) if (force->pair && force->pair->respa_enable == 0) error->all(FLERR,"Pair style does not support rRESPA inner/middle/outer"); // virial_style = 1 (explicit) since never computed implicitly like Verlet virial_style = 1; // setup lists of computes for global and per-atom PE and pressure ev_setup(); // detect if fix omp is present and will clear force arrays int ifix = modify->find_fix("package_omp"); if (ifix >= 0) external_force_clear = 1; // set flags for arrays to clear in force_clear() torqueflag = extraflag = 0; if (atom->torque_flag) torqueflag = 1; if (atom->avec->forceclearflag) extraflag = 1; // step[] = timestep for each level step[nlevels-1] = update->dt; for (int ilevel = nlevels-2; ilevel >= 0; ilevel--) step[ilevel] = step[ilevel+1]/loop[ilevel]; // set newton flag for each level for (int ilevel = 0; ilevel < nlevels; ilevel++) { newton[ilevel] = 0; if (force->newton_bond) { if (level_bond == ilevel || level_angle == ilevel || level_dihedral == ilevel || level_improper == ilevel) newton[ilevel] = 1; } if (force->newton_pair) { if (level_pair == ilevel || level_inner == ilevel || level_middle == ilevel || level_outer == ilevel) newton[ilevel] = 1; if (nhybrid_styles > 0) { set_compute_flags(ilevel); if (pair_compute) newton[ilevel] = 1; } } } // orthogonal vs triclinic simulation box triclinic = domain->triclinic; } /* ---------------------------------------------------------------------- setup before run ------------------------------------------------------------------------- */ void Respa::setup(int flag) { if (comm->me == 0 && screen) { fprintf(screen,"Setting up r-RESPA run ...\n"); if (flag) { fprintf(screen," Unit style : %s\n", update->unit_style); fprintf(screen," Current step : " BIGINT_FORMAT "\n", update->ntimestep); fprintf(screen," Time steps :"); for (int ilevel=0; ilevel < nlevels; ++ilevel) fprintf(screen," %d:%g",ilevel+1, step[ilevel]); fprintf(screen,"\n r-RESPA fixes :"); for (int l=0; l < modify->n_post_force_respa; ++l) { Fix *f = modify->fix[modify->list_post_force_respa[l]]; if (f->respa_level >= 0) fprintf(screen," %d:%s[%s]", MIN(f->respa_level+1,nlevels),f->style,f->id); } fprintf(screen,"\n"); timer->print_timeout(screen); } } update->setupflag = 1; // setup domain, communication and neighboring // acquire ghosts // build neighbor lists atom->setup(); modify->setup_pre_exchange(); if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); comm->exchange(); if (atom->sortfreq > 0) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); domain->image_check(); domain->box_too_small_check(); modify->setup_pre_neighbor(); neighbor->build(); + modify->setup_post_neighbor(); neighbor->ncalls = 0; // compute all forces force->setup(); ev_set(update->ntimestep); for (int ilevel = 0; ilevel < nlevels; ilevel++) { force_clear(newton[ilevel]); modify->setup_pre_force_respa(vflag,ilevel); if (nhybrid_styles > 0) { set_compute_flags(ilevel); force->pair->compute(eflag,vflag); } if (level_pair == ilevel && pair_compute_flag) force->pair->compute(eflag,vflag); if (level_inner == ilevel && pair_compute_flag) force->pair->compute_inner(); if (level_middle == ilevel && pair_compute_flag) force->pair->compute_middle(); if (level_outer == ilevel && pair_compute_flag) force->pair->compute_outer(eflag,vflag); if (level_bond == ilevel && force->bond) force->bond->compute(eflag,vflag); if (level_angle == ilevel && force->angle) force->angle->compute(eflag,vflag); if (level_dihedral == ilevel && force->dihedral) force->dihedral->compute(eflag,vflag); if (level_improper == ilevel && force->improper) force->improper->compute(eflag,vflag); if (level_kspace == ilevel && force->kspace) { force->kspace->setup(); if (kspace_compute_flag) force->kspace->compute(eflag,vflag); } modify->setup_pre_reverse(eflag,vflag); if (newton[ilevel]) comm->reverse_comm(); copy_f_flevel(ilevel); } sum_flevel_f(); modify->setup(vflag); output->setup(flag); update->setupflag = 0; } /* ---------------------------------------------------------------------- setup without output flag = 0 = just force calculation flag = 1 = reneighbor and force calculation ------------------------------------------------------------------------- */ void Respa::setup_minimal(int flag) { update->setupflag = 1; // setup domain, communication and neighboring // acquire ghosts // build neighbor lists if (flag) { modify->setup_pre_exchange(); if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); comm->exchange(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); domain->image_check(); domain->box_too_small_check(); modify->setup_pre_neighbor(); neighbor->build(); + modify->setup_post_neighbor(); neighbor->ncalls = 0; } // compute all forces ev_set(update->ntimestep); for (int ilevel = 0; ilevel < nlevels; ilevel++) { force_clear(newton[ilevel]); modify->setup_pre_force_respa(vflag,ilevel); if (nhybrid_styles > 0) { set_compute_flags(ilevel); force->pair->compute(eflag,vflag); } if (level_pair == ilevel && pair_compute_flag) force->pair->compute(eflag,vflag); if (level_inner == ilevel && pair_compute_flag) force->pair->compute_inner(); if (level_middle == ilevel && pair_compute_flag) force->pair->compute_middle(); if (level_outer == ilevel && pair_compute_flag) force->pair->compute_outer(eflag,vflag); if (level_bond == ilevel && force->bond) force->bond->compute(eflag,vflag); if (level_angle == ilevel && force->angle) force->angle->compute(eflag,vflag); if (level_dihedral == ilevel && force->dihedral) force->dihedral->compute(eflag,vflag); if (level_improper == ilevel && force->improper) force->improper->compute(eflag,vflag); if (level_kspace == ilevel && force->kspace) { force->kspace->setup(); if (kspace_compute_flag) force->kspace->compute(eflag,vflag); } modify->setup_pre_reverse(eflag,vflag); if (newton[ilevel]) comm->reverse_comm(); copy_f_flevel(ilevel); } sum_flevel_f(); modify->setup(vflag); update->setupflag = 0; } /* ---------------------------------------------------------------------- run for N steps ------------------------------------------------------------------------- */ void Respa::run(int n) { bigint ntimestep; for (int i = 0; i < n; i++) { if (timer->check_timeout(i)) { update->nsteps = i; break; } ntimestep = ++update->ntimestep; ev_set(ntimestep); recurse(nlevels-1); // needed in case end_of_step() or output() use total force sum_flevel_f(); if (modify->n_end_of_step) { timer->stamp(); modify->end_of_step(); timer->stamp(Timer::MODIFY); } if (ntimestep == output->next) { timer->stamp(); output->write(update->ntimestep); timer->stamp(Timer::OUTPUT); } } } /* ---------------------------------------------------------------------- delete rRESPA fix at end of run, so its atom arrays won't persist ------------------------------------------------------------------------- */ void Respa::cleanup() { modify->post_run(); modify->delete_fix("RESPA"); domain->box_too_small_check(); update->update_time(); } /* ---------------------------------------------------------------------- */ void Respa::reset_dt() { step[nlevels-1] = update->dt; for (int ilevel = nlevels-2; ilevel >= 0; ilevel--) step[ilevel] = step[ilevel+1]/loop[ilevel]; } /* ---------------------------------------------------------------------- */ void Respa::recurse(int ilevel) { copy_flevel_f(ilevel); for (int iloop = 0; iloop < loop[ilevel]; iloop++) { timer->stamp(); modify->initial_integrate_respa(vflag,ilevel,iloop); if (modify->n_post_integrate_respa) modify->post_integrate_respa(ilevel,iloop); timer->stamp(Timer::MODIFY); // at outermost level, check on rebuilding neighbor list // at innermost level, communicate // at middle levels, do nothing if (ilevel == nlevels-1) { int nflag = neighbor->decide(); if (nflag) { if (modify->n_pre_exchange) { timer->stamp(); modify->pre_exchange(); timer->stamp(Timer::MODIFY); } if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); if (domain->box_change) { domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); } timer->stamp(); comm->exchange(); if (atom->sortfreq > 0 && update->ntimestep >= atom->nextsort) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); timer->stamp(Timer::COMM); if (modify->n_pre_neighbor) { modify->pre_neighbor(); timer->stamp(Timer::MODIFY); } neighbor->build(); timer->stamp(Timer::NEIGH); + if (modify->n_post_neighbor) { + modify->post_neighbor(); + timer->stamp(Timer::MODIFY); + } + } else if (ilevel == 0) { timer->stamp(); comm->forward_comm(); timer->stamp(Timer::COMM); } } else if (ilevel == 0) { timer->stamp(); comm->forward_comm(); timer->stamp(Timer::COMM); } // rRESPA recursion thru all levels // this used to be before neigh list build, // which prevented per-atom energy/stress being tallied correctly // b/c atoms migrated to new procs between short/long force calls // now they migrate at very start of rRESPA timestep, before all forces if (ilevel) recurse(ilevel-1); // force computations // important that ordering is same as Verlet // so that any order dependencies are the same // when potentials are invoked at same level force_clear(newton[ilevel]); if (modify->n_pre_force_respa) { timer->stamp(); modify->pre_force_respa(vflag,ilevel,iloop); timer->stamp(Timer::MODIFY); } timer->stamp(); if (nhybrid_styles > 0) { set_compute_flags(ilevel); force->pair->compute(eflag,vflag); timer->stamp(Timer::PAIR); } if (level_pair == ilevel && pair_compute_flag) { force->pair->compute(eflag,vflag); timer->stamp(Timer::PAIR); } if (level_inner == ilevel && pair_compute_flag) { force->pair->compute_inner(); timer->stamp(Timer::PAIR); } if (level_middle == ilevel && pair_compute_flag) { force->pair->compute_middle(); timer->stamp(Timer::PAIR); } if (level_outer == ilevel && pair_compute_flag) { force->pair->compute_outer(eflag,vflag); timer->stamp(Timer::PAIR); } if (level_bond == ilevel && force->bond) { force->bond->compute(eflag,vflag); timer->stamp(Timer::BOND); } if (level_angle == ilevel && force->angle) { force->angle->compute(eflag,vflag); timer->stamp(Timer::BOND); } if (level_dihedral == ilevel && force->dihedral) { force->dihedral->compute(eflag,vflag); timer->stamp(Timer::BOND); } if (level_improper == ilevel && force->improper) { force->improper->compute(eflag,vflag); timer->stamp(Timer::BOND); } if (level_kspace == ilevel && kspace_compute_flag) { force->kspace->compute(eflag,vflag); timer->stamp(Timer::KSPACE); } if (modify->n_pre_reverse) { modify->pre_reverse(eflag,vflag); timer->stamp(Timer::MODIFY); } if (newton[ilevel]) { comm->reverse_comm(); timer->stamp(Timer::COMM); } timer->stamp(); if (modify->n_post_force_respa) modify->post_force_respa(vflag,ilevel,iloop); modify->final_integrate_respa(ilevel,iloop); timer->stamp(Timer::MODIFY); } copy_f_flevel(ilevel); } /* ---------------------------------------------------------------------- clear force on own & ghost atoms clear other arrays as needed ------------------------------------------------------------------------- */ void Respa::force_clear(int newtonflag) { if (external_force_clear) return; // clear global force array // if either newton flag is set, also include ghosts size_t nbytes = sizeof(double) * atom->nlocal; if (force->newton) nbytes += sizeof(double) * atom->nghost; if (nbytes) { memset(&atom->f[0][0],0,3*nbytes); if (torqueflag) memset(&atom->torque[0][0],0,3*nbytes); if (extraflag) atom->avec->force_clear(0,nbytes); } } /* ---------------------------------------------------------------------- copy force components from atom->f to FixRespa->f_level ------------------------------------------------------------------------- */ void Respa::copy_f_flevel(int ilevel) { double ***f_level = fix_respa->f_level; double **f = atom->f; double ***t_level = fix_respa->t_level; double **t = atom->torque; int n = atom->nlocal; for (int i = 0; i < n; i++) { f_level[i][ilevel][0] = f[i][0]; f_level[i][ilevel][1] = f[i][1]; f_level[i][ilevel][2] = f[i][2]; if (fix_respa->store_torque) { t_level[i][ilevel][0] = t[i][0]; t_level[i][ilevel][1] = t[i][1]; t_level[i][ilevel][2] = t[i][2]; } } } /* ---------------------------------------------------------------------- copy force components from FixRespa->f_level to atom->f ------------------------------------------------------------------------- */ void Respa::copy_flevel_f(int ilevel) { double ***f_level = fix_respa->f_level; double **f = atom->f; double ***t_level = fix_respa->t_level; double **t = atom->torque; int n = atom->nlocal; for (int i = 0; i < n; i++) { f[i][0] = f_level[i][ilevel][0]; f[i][1] = f_level[i][ilevel][1]; f[i][2] = f_level[i][ilevel][2]; if (fix_respa->store_torque) { t[i][0] = t_level[i][ilevel][0]; t[i][1] = t_level[i][ilevel][1]; t[i][2] = t_level[i][ilevel][2]; } } } /* ---------------------------------------------------------------------- sum all force components from FixRespa->f_level to create full atom->f ------------------------------------------------------------------------- */ void Respa::sum_flevel_f() { copy_flevel_f(0); double ***f_level = fix_respa->f_level; double **f = atom->f; double ***t_level = fix_respa->t_level; double **t = atom->torque; int n = atom->nlocal; for (int ilevel = 1; ilevel < nlevels; ilevel++) { for (int i = 0; i < n; i++) { f[i][0] += f_level[i][ilevel][0]; f[i][1] += f_level[i][ilevel][1]; f[i][2] += f_level[i][ilevel][2]; if (fix_respa->store_torque) { t[i][0] += t_level[i][ilevel][0]; t[i][1] += t_level[i][ilevel][1]; t[i][2] += t_level[i][ilevel][2]; } } } } /*----------------------------------------------------------------------- set flags for when some hybrid forces should be computed ------------------------------------------------------------------------- */ void Respa::set_compute_flags(int ilevel) { if (nhybrid_styles < 1) return; pair_compute = 0; for (int i=0; i