Merge branch 'develop' into collected-small-changes
This commit is contained in:
@ -1,4 +1,3 @@
|
||||
// clang-format off
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
https://www.lammps.org/, Sandia National Laboratories
|
||||
@ -26,36 +25,42 @@
|
||||
#include "memory.h"
|
||||
#include "text_file_reader.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using MathSpecial::square;
|
||||
|
||||
enum { NONE = 0, HARM, MORSE, LJ126 };
|
||||
enum { NONE = 0, HARM, MORSE, LJ126, QUARTIC };
|
||||
|
||||
// clang-format off
|
||||
static std::map<std::string, int> stylename = {
|
||||
{ "none", NONE },
|
||||
{ "harmonic", HARM },
|
||||
{ "morse", MORSE },
|
||||
{ "lj126", LJ126 }
|
||||
{"none", NONE},
|
||||
{"harmonic", HARM},
|
||||
{"morse", MORSE},
|
||||
{"lj126", LJ126},
|
||||
{"quartic", QUARTIC}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// fast power function for integer exponent > 0
|
||||
static double mypow(double x, int n) {
|
||||
static double mypow(double x, int n)
|
||||
{
|
||||
double yy;
|
||||
|
||||
if (x == 0.0) return 0.0;
|
||||
|
||||
for (yy = 1.0; n != 0; n >>= 1, x *=x)
|
||||
for (yy = 1.0; n != 0; n >>= 1, x *= x)
|
||||
if (n & 1) yy *= x;
|
||||
|
||||
return yy;
|
||||
}
|
||||
|
||||
typedef struct { double x,y,z; } dbl3_t;
|
||||
typedef struct {
|
||||
double x, y, z;
|
||||
} dbl3_t;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -86,19 +91,42 @@ PairList::~PairList()
|
||||
|
||||
void PairList::compute(int eflag, int vflag)
|
||||
{
|
||||
ev_init(eflag,vflag);
|
||||
ev_init(eflag, vflag);
|
||||
|
||||
// get maximum allowed tag.
|
||||
|
||||
bigint maxtag_one, maxtag;
|
||||
maxtag_one = maxtag = 0;
|
||||
const int nlocal = atom->nlocal;
|
||||
const int newton_pair = force->newton_pair;
|
||||
const dbl3_t * _noalias const x = (dbl3_t *) atom->x[0];
|
||||
dbl3_t * _noalias const f = (dbl3_t *) atom->f[0]; // NOLINT
|
||||
const tagint *_noalias const tag = atom->tag;
|
||||
for (int i = 0; i < nlocal; ++i) maxtag_one = MAX(maxtag_one, tag[i]);
|
||||
MPI_Allreduce(&maxtag_one, &maxtag, 1, MPI_LMP_TAGINT, MPI_MAX, world);
|
||||
|
||||
double fpair,epair;
|
||||
int i,j;
|
||||
const int newton_pair = force->newton_pair;
|
||||
const dbl3_t *_noalias const x = (dbl3_t *) atom->x[0];
|
||||
dbl3_t *_noalias const f = (dbl3_t *) atom->f[0]; // NOLINT
|
||||
|
||||
double fpair, epair;
|
||||
int i, j;
|
||||
|
||||
int pc = 0;
|
||||
for (int n=0; n < npairs; ++n) {
|
||||
for (int n = 0; n < npairs; ++n) {
|
||||
const list_param &par = params[n];
|
||||
|
||||
// can only use valid tags or else atom->map() below will segfault.
|
||||
if ((par.id1 < 1) || (par.id1 > maxtag)) {
|
||||
if (check_flag)
|
||||
error->all(FLERR, "Invalid pair list atom ID {}", par.id1);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if ((par.id2 < 1) || (par.id2 > maxtag)) {
|
||||
if (check_flag)
|
||||
error->all(FLERR, "Invalid pair list atom ID {}", par.id2);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
i = atom->map(par.id1);
|
||||
j = atom->map(par.id2);
|
||||
|
||||
@ -112,14 +140,14 @@ void PairList::compute(int eflag, int vflag)
|
||||
// if id1 is a ghost, we skip if the sum of both ids is even.
|
||||
// if id2 is a ghost, we skip if the sum of both ids is odd.
|
||||
if (newton_pair) {
|
||||
if ((i >= nlocal) && ((par.id1+par.id2) & 1) == 0) continue;
|
||||
if ((j >= nlocal) && ((par.id1+par.id2) & 1) == 1) continue;
|
||||
if ((i >= nlocal) && ((par.id1 + par.id2) & 1) == 0) continue;
|
||||
if ((j >= nlocal) && ((par.id1 + par.id2) & 1) == 1) continue;
|
||||
}
|
||||
|
||||
const double dx = x[i].x - x[j].x;
|
||||
const double dy = x[i].y - x[j].y;
|
||||
const double dz = x[i].z - x[j].z;
|
||||
const double rsq = dx*dx + dy*dy + dz*dz;
|
||||
const double rsq = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
fpair = epair = 0.0;
|
||||
if (check_flag) {
|
||||
@ -128,61 +156,67 @@ void PairList::compute(int eflag, int vflag)
|
||||
}
|
||||
|
||||
if (rsq < par.cutsq) {
|
||||
const double r2inv = 1.0/rsq;
|
||||
const double r2inv = 1.0 / rsq;
|
||||
|
||||
if (par.style == HARM) {
|
||||
const double r = sqrt(rsq);
|
||||
const double dr = par.param.harm.r0 - r;
|
||||
fpair = 2.0*par.param.harm.k*dr/r;
|
||||
fpair = 2.0 * par.param.harm.k * dr / r;
|
||||
|
||||
if (eflag_either)
|
||||
epair = par.param.harm.k*dr*dr - par.offset;
|
||||
if (eflag_either) epair = par.param.harm.k * dr * dr - par.offset;
|
||||
|
||||
} else if (par.style == MORSE) {
|
||||
|
||||
const double r = sqrt(rsq);
|
||||
const double dr = par.param.morse.r0 - r;
|
||||
const double dexp = exp(par.param.morse.alpha * dr);
|
||||
fpair = 2.0*par.param.morse.d0*par.param.morse.alpha
|
||||
* (dexp*dexp - dexp) / r;
|
||||
const double dr = r - par.param.morse.r0;
|
||||
const double dexp = exp(-par.param.morse.alpha * dr);
|
||||
fpair = 2.0 * par.param.morse.d0 * par.param.morse.alpha * (dexp * dexp - dexp) / r;
|
||||
|
||||
if (eflag_either)
|
||||
epair = par.param.morse.d0 * (dexp*dexp - 2.0*dexp) - par.offset;
|
||||
if (eflag_either) epair = par.param.morse.d0 * (dexp * dexp - 2.0 * dexp + 1.0) - par.offset;
|
||||
|
||||
} else if (par.style == LJ126) {
|
||||
|
||||
const double r6inv = r2inv*r2inv*r2inv;
|
||||
const double sig6 = mypow(par.param.lj126.sigma,6);
|
||||
fpair = 24.0*par.param.lj126.epsilon*r6inv
|
||||
* (2.0*sig6*sig6*r6inv - sig6) * r2inv;
|
||||
const double r6inv = r2inv * r2inv * r2inv;
|
||||
const double sig6 = mypow(par.param.lj126.sigma, 6);
|
||||
fpair = 24.0 * par.param.lj126.epsilon * r6inv * (2.0 * sig6 * sig6 * r6inv - sig6) * r2inv;
|
||||
|
||||
if (eflag_either)
|
||||
epair = 4.0*par.param.lj126.epsilon*r6inv
|
||||
* (sig6*sig6*r6inv - sig6) - par.offset;
|
||||
epair = 4.0 * par.param.lj126.epsilon * r6inv * (sig6 * sig6 * r6inv - sig6) - par.offset;
|
||||
|
||||
} else if (par.style == QUARTIC) {
|
||||
|
||||
const double r = sqrt(rsq);
|
||||
double dr = r - sqrt(par.cutsq);
|
||||
double ra = dr - par.param.quartic.b1;
|
||||
double rb = dr - par.param.quartic.b2;
|
||||
double r2 = dr * dr;
|
||||
fpair = -par.param.quartic.k / r * (r2 * (ra + rb) + 2.0 * dr * ra * rb);
|
||||
|
||||
if (eflag_either) epair = par.param.quartic.k * r2 * ra * rb;
|
||||
}
|
||||
|
||||
if (newton_pair || i < nlocal) {
|
||||
f[i].x += dx*fpair;
|
||||
f[i].y += dy*fpair;
|
||||
f[i].z += dz*fpair;
|
||||
f[i].x += dx * fpair;
|
||||
f[i].y += dy * fpair;
|
||||
f[i].z += dz * fpair;
|
||||
}
|
||||
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j].x -= dx*fpair;
|
||||
f[j].y -= dy*fpair;
|
||||
f[j].z -= dz*fpair;
|
||||
f[j].x -= dx * fpair;
|
||||
f[j].y -= dy * fpair;
|
||||
f[j].z -= dz * fpair;
|
||||
}
|
||||
|
||||
if (evflag) ev_tally(i,j,nlocal,newton_pair,epair,0.0,fpair,dx,dy,dz);
|
||||
if (evflag) ev_tally(i, j, nlocal, newton_pair, epair, 0.0, fpair, dx, dy, dz);
|
||||
}
|
||||
}
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
|
||||
if (check_flag) {
|
||||
int tmp;
|
||||
MPI_Allreduce(&pc,&tmp,1,MPI_INT,MPI_SUM,world);
|
||||
if (tmp != 2*npairs)
|
||||
error->all(FLERR,"Not all pairs processed in pair_style list");
|
||||
MPI_Allreduce(&pc, &tmp, 1, MPI_INT, MPI_SUM, world);
|
||||
if (tmp != 2 * npairs)
|
||||
error->all(FLERR, "Not all pairs processed in pair_style list: {} vs {}", tmp, 2 * npairs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,14 +227,13 @@ void PairList::compute(int eflag, int vflag)
|
||||
void PairList::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
int np1 = atom->ntypes + 1;
|
||||
|
||||
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(setflag, np1, np1, "pair:setflag");
|
||||
for (int i = 1; i < np1; i++)
|
||||
for (int j = i; j < np1; j++) setflag[i][j] = 0;
|
||||
|
||||
memory->create(cutsq,n+1,n+1,"pair:cutsq");
|
||||
memory->create(cutsq, np1, np1, "pair:cutsq");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -209,13 +242,19 @@ void PairList::allocate()
|
||||
|
||||
void PairList::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 2)
|
||||
error->all(FLERR,"Illegal pair_style command");
|
||||
if (narg < 2) utils::missing_cmd_args(FLERR, "pair_style list", error);
|
||||
|
||||
cut_global = utils::numeric(FLERR,arg[1],false,lmp);
|
||||
if (narg > 2) {
|
||||
if (strcmp(arg[2],"nocheck") == 0) check_flag = 0;
|
||||
if (strcmp(arg[2],"check") == 0) check_flag = 1;
|
||||
cut_global = utils::numeric(FLERR, arg[1], false, lmp);
|
||||
int iarg = 2;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg], "nocheck") == 0) {
|
||||
check_flag = 0;
|
||||
++iarg;
|
||||
} else if (strcmp(arg[2], "check") == 0) {
|
||||
check_flag = 1;
|
||||
++iarg;
|
||||
} else
|
||||
error->all(FLERR, "Unknown pair style list keyword: {}", arg[iarg]);
|
||||
}
|
||||
|
||||
std::vector<int> mystyles;
|
||||
@ -223,13 +262,15 @@ void PairList::settings(int narg, char **arg)
|
||||
|
||||
// read and parse potential file only on MPI rank 0.
|
||||
if (comm->me == 0) {
|
||||
int nharm, nmorse, nlj126, nskipped;
|
||||
FILE *fp = utils::open_potential(arg[0],lmp,nullptr);
|
||||
TextFileReader reader(fp,"pair list coeffs");
|
||||
npairs = nharm = nmorse = nlj126 = nskipped = 0;
|
||||
int nharm, nmorse, nlj126, nquartic, nskipped;
|
||||
FILE *fp = utils::open_potential(arg[0], lmp, nullptr);
|
||||
if (!fp)
|
||||
error->one(FLERR, "Error opening pair list coeffs file {}: {}", arg[0], utils::getsyserror());
|
||||
TextFileReader reader(fp, "pair list coeffs");
|
||||
npairs = nharm = nmorse = nlj126 = nquartic = nskipped = 0;
|
||||
char *line;
|
||||
|
||||
try {
|
||||
char *line;
|
||||
while ((line = reader.next_line())) {
|
||||
ValueTokenizer values(line);
|
||||
list_param oneparam;
|
||||
@ -241,75 +282,86 @@ void PairList::settings(int narg, char **arg)
|
||||
|
||||
switch (oneparam.style) {
|
||||
|
||||
case HARM:
|
||||
oneparam.param.harm.k = values.next_double();
|
||||
oneparam.param.harm.r0 = values.next_double();
|
||||
++nharm;
|
||||
break;
|
||||
case HARM:
|
||||
oneparam.param.harm.k = values.next_double();
|
||||
oneparam.param.harm.r0 = values.next_double();
|
||||
++nharm;
|
||||
break;
|
||||
|
||||
case MORSE:
|
||||
oneparam.param.morse.d0 = values.next_double();
|
||||
oneparam.param.morse.alpha = values.next_double();
|
||||
oneparam.param.morse.r0 = values.next_double();
|
||||
++nmorse;
|
||||
break;
|
||||
case MORSE:
|
||||
oneparam.param.morse.d0 = values.next_double();
|
||||
oneparam.param.morse.alpha = values.next_double();
|
||||
oneparam.param.morse.r0 = values.next_double();
|
||||
++nmorse;
|
||||
break;
|
||||
|
||||
case LJ126:
|
||||
oneparam.param.lj126.epsilon = values.next_double();
|
||||
oneparam.param.lj126.sigma = values.next_double();
|
||||
++nlj126;
|
||||
break;
|
||||
case LJ126:
|
||||
oneparam.param.lj126.epsilon = values.next_double();
|
||||
oneparam.param.lj126.sigma = values.next_double();
|
||||
++nlj126;
|
||||
break;
|
||||
|
||||
case NONE: // fallthrough
|
||||
error->warning(FLERR,"Skipping unrecognized pair list potential entry: {}",
|
||||
utils::trim(line));
|
||||
++nskipped;
|
||||
break;
|
||||
case QUARTIC:
|
||||
oneparam.param.quartic.k = values.next_double();
|
||||
oneparam.param.quartic.b1 = values.next_double();
|
||||
oneparam.param.quartic.b2 = values.next_double();
|
||||
if (!values.has_next())
|
||||
throw FileReaderException("Must specify individual cutoff for quartic interaction");
|
||||
++nquartic;
|
||||
break;
|
||||
|
||||
case NONE: // fallthrough
|
||||
error->warning(FLERR, "Skipping unrecognized pair list potential entry: {}",
|
||||
utils::trim(line));
|
||||
++nskipped;
|
||||
break;
|
||||
}
|
||||
if (values.has_next())
|
||||
oneparam.cutsq = square(values.next_double());
|
||||
else
|
||||
oneparam.cutsq = cut_global*cut_global;
|
||||
oneparam.cutsq = cut_global * cut_global;
|
||||
|
||||
myparams.push_back(oneparam);
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
error->one(FLERR,"Error reading pair list coeffs file: {}", e.what());
|
||||
error->one(FLERR, "Error reading pair list coeffs file: {}\n{}", e.what(), line);
|
||||
}
|
||||
utils::logmesg(lmp, "Read {} ({}/{}/{}) interacting pair lines from {}. "
|
||||
"{} skipped entries.\n", npairs, nharm, nmorse, nlj126, arg[0], nskipped);
|
||||
utils::logmesg(lmp,
|
||||
"Read {} ({}/{}/{}/{}) interacting pair lines from {}. "
|
||||
"{} skipped entries.\n",
|
||||
npairs, nharm, nmorse, nlj126, nquartic, arg[0], nskipped);
|
||||
|
||||
memory->create(params,npairs,"pair_list:params");
|
||||
memcpy(params, myparams.data(),npairs*sizeof(list_param));
|
||||
memory->create(params, npairs, "pair_list:params");
|
||||
memcpy(params, myparams.data(), npairs * sizeof(list_param));
|
||||
fclose(fp);
|
||||
}
|
||||
MPI_Bcast(&npairs, 1, MPI_INT, 0, world);
|
||||
if (comm->me != 0) memory->create(params,npairs,"pair_list:params");
|
||||
MPI_Bcast(params, npairs*sizeof(list_param), MPI_BYTE, 0, world);
|
||||
if (comm->me != 0) memory->create(params, npairs, "pair_list:params");
|
||||
MPI_Bcast(params, npairs * sizeof(list_param), MPI_BYTE, 0, world);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
there are no coeffs to be set, but we need to update setflag and pretend
|
||||
there are no coeffs to be set, but we need to update setflag and pretend there are
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairList::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg < 2) error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
if (narg < 2) utils::missing_cmd_args(FLERR, "pair_coeff list", error);
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi,jlo,jhi;
|
||||
utils::bounds(FLERR,arg[0],1,atom->ntypes,ilo,ihi,error);
|
||||
utils::bounds(FLERR,arg[1],1,atom->ntypes,jlo,jhi,error);
|
||||
int ilo, ihi, jlo, jhi;
|
||||
utils::bounds(FLERR, arg[0], 1, atom->ntypes, ilo, ihi, error);
|
||||
utils::bounds(FLERR, arg[1], 1, atom->ntypes, jlo, jhi, error);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
for (int j = MAX(jlo, i); j <= jhi; j++) {
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -318,29 +370,31 @@ void PairList::coeff(int narg, char **arg)
|
||||
|
||||
void PairList::init_style()
|
||||
{
|
||||
if (atom->tag_enable == 0)
|
||||
error->all(FLERR,"Pair style list requires atom IDs");
|
||||
if (atom->tag_enable == 0) error->all(FLERR, "Pair style list requires atom IDs");
|
||||
|
||||
if (atom->map_style == Atom::MAP_NONE)
|
||||
error->all(FLERR,"Pair style list requires an atom map");
|
||||
if (atom->map_style == Atom::MAP_NONE) error->all(FLERR, "Pair style list requires an atom map");
|
||||
|
||||
if (offset_flag) {
|
||||
for (int n=0; n < npairs; ++n) {
|
||||
for (int n = 0; n < npairs; ++n) {
|
||||
list_param &par = params[n];
|
||||
|
||||
if (par.style == HARM) {
|
||||
const double dr = sqrt(par.cutsq) - par.param.harm.r0;
|
||||
par.offset = par.param.harm.k*dr*dr;
|
||||
par.offset = par.param.harm.k * dr * dr;
|
||||
|
||||
} else if (par.style == MORSE) {
|
||||
const double dr = par.param.morse.r0 - sqrt(par.cutsq);
|
||||
const double dexp = exp(par.param.morse.alpha * dr);
|
||||
par.offset = par.param.morse.d0 * (dexp*dexp - 2.0*dexp);
|
||||
par.offset = par.param.morse.d0 * (dexp * dexp - 2.0 * dexp - 1.0);
|
||||
|
||||
} else if (par.style == LJ126) {
|
||||
const double r6inv = par.cutsq*par.cutsq*par.cutsq;
|
||||
const double sig6 = mypow(par.param.lj126.sigma,6);
|
||||
par.offset = 4.0*par.param.lj126.epsilon*r6inv * (sig6*sig6*r6inv - sig6);
|
||||
const double r6inv = par.cutsq * par.cutsq * par.cutsq;
|
||||
const double sig6 = mypow(par.param.lj126.sigma, 6);
|
||||
par.offset = 4.0 * par.param.lj126.epsilon * r6inv * (sig6 * sig6 * r6inv - sig6);
|
||||
|
||||
} else if (par.style == QUARTIC) {
|
||||
// the offset is always 0 at rc
|
||||
par.offset = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -362,10 +416,10 @@ double PairList::init_one(int, int)
|
||||
|
||||
double PairList::memory_usage()
|
||||
{
|
||||
double bytes = (double)npairs * sizeof(int);
|
||||
bytes += (double)npairs * sizeof(list_param);
|
||||
const int n = atom->ntypes+1;
|
||||
bytes += (double)n*(n*sizeof(int) + sizeof(int *));
|
||||
bytes += (double)n*(n*sizeof(double) + sizeof(double *));
|
||||
double bytes = (double) npairs * sizeof(int);
|
||||
bytes += (double) npairs * sizeof(list_param);
|
||||
const int n = atom->ntypes + 1;
|
||||
bytes += (double) n * (n * sizeof(int) + sizeof(int *));
|
||||
bytes += (double) n * (n * sizeof(double) + sizeof(double *));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@ -49,11 +49,16 @@ class PairList : public Pair {
|
||||
struct lj126_p {
|
||||
double epsilon, sigma;
|
||||
};
|
||||
struct quartic_p {
|
||||
double k, b1, b2;
|
||||
};
|
||||
|
||||
|
||||
union param_u {
|
||||
harm_p harm;
|
||||
morse_p morse;
|
||||
lj126_p lj126;
|
||||
quartic_p quartic;
|
||||
};
|
||||
|
||||
struct list_param {
|
||||
|
||||
Reference in New Issue
Block a user