Merge pull request #3091 from akohlmey/more-parsing-refactor

More file parsing refactoring
This commit is contained in:
Axel Kohlmeyer
2022-01-19 12:41:13 -05:00
committed by GitHub
14 changed files with 479 additions and 785 deletions

View File

@ -1,8 +1,8 @@
# Electronic stopping for Si in Si
# Uses metal units
# Electronic stopping for Si in Si UNITS: metal DATE: 2019-02-19 CONTRIBUTOR: Risto Toijala risto.toijala@helsinki.fi
# Kinetic energy in eV, stopping power in eV/A
# For other atom types, add columns.
# atom type 1
# energy Si in Si
3918.2 6.541
15672.9 13.091

View File

@ -1,3 +1,5 @@
# DATE: 2014-11-24 UNITS: real CONTRIBUTOR: Michele Ceriotti michele.ceriotti@gmail.com
3.904138445158e-4 4.681059722010e-2 3.079778738058e-2 4.428079381336e-2 5.057825203477e-2 2.591193419597e-2 1.513907125942e-2
-4.789343294190e-2 2.037551040972e-2 6.597801861779e-2 -8.528273506602e-3 -2.230839572773e-3 6.593086307870e-3 -6.653653981891e-2
-2.905096373618e-2 -6.597801861779e-2 2.086885297843e-2 1.145471984072e-2 3.111465343867e-2 1.101562087523e-2 -3.264959166486e-2

View File

@ -1,3 +1,5 @@
# DATE: 2014-11-24 UNITS: real CONTRIBUTOR: Michele Ceriotti michele.ceriotti@gmail.com
2.999985914100e+2 5.937593337000e+0 2.144376751500e+2 5.883055908000e+1 -1.119803766000e+2 -6.793381764000e+1 1.379789732400e+1
5.937593337000e+0 3.781851303000e+2 -5.794518522000e+1 -2.178772681500e+2 -1.649310659100e+2 -6.557113452000e+1 3.833830743000e+1
2.144376751500e+2 -5.794518522000e+1 7.325759985000e+2 2.188507713000e+2 -3.704586531000e+2 -3.385193865000e+1 -4.827706758000e+0

View File

@ -1,3 +1,5 @@
# DATE: 2014-11-24 UNITS: real CONTRIBUTOR: Michele Ceriotti michele.ceriotti@gmail.com
4.247358737218e-3 3.231404593065e-2 -9.715629522215e-3 8.199488441225e-3 7.288427565896e-3 -3.634229949055e-3 -3.294395982200e-3
4.887738278128e-2 5.978602802893e-1 -2.079222967202e-1 1.088740438247e-1 4.666954324786e-2 -1.334147134493e-2 -3.914996645811e-2
4.015863091190e-2 2.079222967202e-1 1.645970119444e-1 8.351952991453e-2 5.114740085468e-2 1.217862237677e-2 -4.506711205974e-2

View File

@ -29,6 +29,7 @@
#include "neigh_list.h"
#include "neigh_request.h"
#include "neighbor.h"
#include "potential_file_reader.h"
#include "region.h"
#include "update.h"
@ -236,49 +237,43 @@ double FixElectronStopping::compute_scalar()
return SeLoss_all;
}
/* ---------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
read electron stopping parameters. only called from MPI rank 0.
format: energy then one column per atom type
read as many lines as available.
energies must be sorted in ascending order.
---------------------------------------------------------------------- */
void FixElectronStopping::read_table(const char *file)
{
char line[MAXLINE];
FILE *fp = utils::open_potential(file,lmp,nullptr);
if (fp == nullptr)
error->one(FLERR,"Cannot open stopping range table {}: {}", file, utils::getsyserror());
const int ncol = atom->ntypes + 1;
int nlines = 0;
PotentialFileReader reader(lmp, file, "electron stopping data table");
int l = 0;
while (true) {
if (fgets(line, MAXLINE, fp) == nullptr) break; // end of file
if (line[0] == '#') continue; // comment
try {
char *line;
double oldvalue = 0.0;
char *pch = strtok(line, " \t\n\r");
if (pch == nullptr) continue; // blank line
while ((line = reader.next_line())) {
if (nlines >= maxlines) grow_table();
ValueTokenizer values(line);
elstop_ranges[0][nlines] = values.next_double();
if (elstop_ranges[0][nlines] <= oldvalue)
throw TokenizerException("energy values must be positive and in ascending order",line);
if (l >= maxlines) grow_table();
oldvalue = elstop_ranges[0][nlines];
for (int i = 1; i < ncol; ++i)
elstop_ranges[i][nlines] = values.next_double();
int i = 0;
for ( ; i < ncol && pch != nullptr; i++) {
elstop_ranges[i][l] = utils::numeric(FLERR, pch,false,lmp);
pch = strtok(nullptr, " \t\n\r");
++nlines;
}
if (i != ncol || pch != nullptr) // too short or too long
error->one(FLERR, "fix electron/stopping: Invalid table line");
if (l >= 1 && elstop_ranges[0][l] <= elstop_ranges[0][l-1])
error->one(FLERR,
"fix electron/stopping: Energies must be in ascending order");
l++;
} catch (std::exception &e) {
error->one(FLERR, "Problem parsing electron stopping data: {}", e.what());
}
table_entries = l;
if (table_entries == 0)
if (nlines == 0)
error->one(FLERR, "Did not find any data in electron/stopping table file");
fclose(fp);
table_entries = nlines;
}
/* ---------------------------------------------------------------------- */

View File

@ -14,7 +14,7 @@
/* ----------------------------------------------------------------------
Contributing authors: Michele Ceriotti (EPFL), Joe Morrone (Stony Brook),
Axel Kohylmeyer (Temple U)
Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#include "fix_gle.h"
@ -24,6 +24,7 @@
#include "error.h"
#include "force.h"
#include "memory.h"
#include "potential_file_reader.h"
#include "random_mars.h"
#include "respa.h"
#include "update.h"
@ -221,46 +222,17 @@ FixGLE::FixGLE(LAMMPS *lmp, int narg, char **arg) :
int seed = utils::inumeric(FLERR,arg[6],false,lmp);
// LOADING A matrix
FILE *fgle = nullptr;
char *fname = arg[7];
memset(A, ns1sq, sizeof(double));
if (comm->me == 0) {
fgle = utils::open_potential(fname,lmp,nullptr);
if (fgle == nullptr)
error->one(FLERR,"Cannot open A-matrix file {}: {}",fname, utils::getsyserror());
utils::logmesg(lmp,"Reading A-matrix from {}\n", fname);
}
// read each line of the file, skipping blank lines or leading '#'
char line[MAXLINE],*ptr;
int n,nwords,ndone=0,eof=0;
while (true) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fgle);
if (ptr == nullptr) {
eof = 1;
fclose(fgle);
} else n = strlen(line) + 1;
PotentialFileReader reader(lmp,fname,"fix gle A matrix");
try {
reader.next_dvector(A, ns1sq);
} catch (std::exception &e) {
error->one(FLERR,"Error reading A-matrix: {}", e.what());
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (nwords == 0) continue;
ptr = strtok(line," \t\n\r\f");
do {
A[ndone] = atof(ptr);
ptr = strtok(nullptr," \t\n\r\f");
ndone++;
} while ((ptr != nullptr) && (ndone < ns1sq));
}
MPI_Bcast(A,ns1sq,MPI_DOUBLE,0,world);
fnoneq=0; gle_every=1; gle_step=0;
for (int iarg=8; iarg<narg; iarg+=2) {
@ -289,44 +261,20 @@ FixGLE::FixGLE(LAMMPS *lmp, int narg, char **arg) :
C[i]=kT;
} else {
// LOADING C matrix
memset(C, ns1sq, sizeof(double));
if (comm->me == 0) {
fgle = utils::open_potential(fname,lmp,nullptr);
if (fgle == nullptr)
error->one(FLERR,"Cannot open C-matrix file {}: {}",fname, utils::getsyserror());
utils::logmesg(lmp,"Reading C-matrix from {}\n", fname);
}
// read each line of the file, skipping blank lines or leading '#'
ndone = eof = 0;
const double cfac = force->boltz / force->mvv2e;
while (true) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fgle);
if (ptr == nullptr) {
eof = 1;
fclose(fgle);
} else n = strlen(line) + 1;
PotentialFileReader reader(lmp,fname,"fix gle C matrix");
try {
reader.next_dvector(C, ns1sq);
} catch (std::exception &e) {
error->one(FLERR,"Error reading C-matrix: {}", e.what());
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (nwords == 0) continue;
ptr = strtok(line," \t\n\r\f");
do {
C[ndone] = cfac*atof(ptr);
ptr = strtok(nullptr," \t\n\r\f");
ndone++;
} while ((ptr != nullptr) && (ndone < ns1sq));
}
MPI_Bcast(C,ns1sq,MPI_DOUBLE,0,world);
const double cfac = force->boltz / force->mvv2e;
for (int i=0; i < ns1sq; ++i) C[i] *= cfac;
}
#ifdef GLE_DEBUG
@ -366,12 +314,12 @@ FixGLE::FixGLE(LAMMPS *lmp, int narg, char **arg) :
FixGLE::~FixGLE()
{
delete random;
delete [] A;
delete [] C;
delete [] S;
delete [] T;
delete [] TT;
delete [] ST;
delete[] A;
delete[] C;
delete[] S;
delete[] T;
delete[] TT;
delete[] ST;
memory->destroy(sqrt_m);
memory->destroy(gle_s);

View File

@ -31,6 +31,7 @@
#include "neigh_list.h"
#include "neigh_request.h"
#include "neighbor.h"
#include "potential_file_reader.h"
#include <cmath>
#include <cstring>
@ -368,7 +369,7 @@ void PairEDIP::compute(int eflag, int vflag)
directorCos_ik_z = invR_ik * dr_ik[2];
cosTeta = directorCos_ij_x * directorCos_ik_x + directorCos_ij_y * directorCos_ik_y +
directorCos_ij_z * directorCos_ik_z;
directorCos_ij_z * directorCos_ik_z;
cosTetaDiff = cosTeta + tauFunction;
cosTetaDiffCosTetaDiff = cosTetaDiff * cosTetaDiff;
@ -376,33 +377,33 @@ void PairEDIP::compute(int eflag, int vflag)
expMinusQFunctionCosTetaDiffCosTetaDiff = exp(-qFunctionCosTetaDiffCosTetaDiff);
potentia3B_factor = lambda *
((1.0 - expMinusQFunctionCosTetaDiffCosTetaDiff) +
eta * qFunctionCosTetaDiffCosTetaDiff);
((1.0 - expMinusQFunctionCosTetaDiffCosTetaDiff) +
eta * qFunctionCosTetaDiffCosTetaDiff);
exp3B_ik = preExp3B_ij[neighbor_k];
exp3BDerived_ik = preExp3BDerived_ij[neighbor_k];
forceMod3B_factor1_ij = -exp3BDerived_ij * exp3B_ik * potentia3B_factor;
forceMod3B_factor2 = 2.0 * lambda * exp3B_ij * exp3B_ik * qFunction * cosTetaDiff *
(eta + expMinusQFunctionCosTetaDiffCosTetaDiff);
(eta + expMinusQFunctionCosTetaDiffCosTetaDiff);
forceMod3B_factor2_ij = forceMod3B_factor2 * invR_ij;
f_ij[0] = forceMod3B_factor1_ij * directorCos_ij_x +
forceMod3B_factor2_ij * (cosTeta * directorCos_ij_x - directorCos_ik_x);
forceMod3B_factor2_ij * (cosTeta * directorCos_ij_x - directorCos_ik_x);
f_ij[1] = forceMod3B_factor1_ij * directorCos_ij_y +
forceMod3B_factor2_ij * (cosTeta * directorCos_ij_y - directorCos_ik_y);
forceMod3B_factor2_ij * (cosTeta * directorCos_ij_y - directorCos_ik_y);
f_ij[2] = forceMod3B_factor1_ij * directorCos_ij_z +
forceMod3B_factor2_ij * (cosTeta * directorCos_ij_z - directorCos_ik_z);
forceMod3B_factor2_ij * (cosTeta * directorCos_ij_z - directorCos_ik_z);
forceMod3B_factor1_ik = -exp3BDerived_ik * exp3B_ij * potentia3B_factor;
forceMod3B_factor2_ik = forceMod3B_factor2 * invR_ik;
f_ik[0] = forceMod3B_factor1_ik * directorCos_ik_x +
forceMod3B_factor2_ik * (cosTeta * directorCos_ik_x - directorCos_ij_x);
forceMod3B_factor2_ik * (cosTeta * directorCos_ik_x - directorCos_ij_x);
f_ik[1] = forceMod3B_factor1_ik * directorCos_ik_y +
forceMod3B_factor2_ik * (cosTeta * directorCos_ik_y - directorCos_ij_y);
forceMod3B_factor2_ik * (cosTeta * directorCos_ik_y - directorCos_ij_y);
f_ik[2] = forceMod3B_factor1_ik * directorCos_ik_z +
forceMod3B_factor2_ik * (cosTeta * directorCos_ik_z - directorCos_ij_z);
forceMod3B_factor2_ik * (cosTeta * directorCos_ik_z - directorCos_ij_z);
forceModCoord += (forceMod3B_factor2 * (tauFunctionDerived - 0.5 * mu * cosTetaDiff));
@ -765,136 +766,92 @@ double PairEDIP::init_one(int i, int j)
void PairEDIP::read_file(char *file)
{
int params_per_line = 20;
char **words = new char *[params_per_line + 1];
memory->sfree(params);
params = nullptr;
nparams = maxparam = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = utils::open_potential(file, lmp, nullptr);
if (fp == nullptr)
error->one(FLERR, "Cannot open EDIP potential file {}: {}", file, utils::getsyserror());
}
PotentialFileReader reader(lmp, file, "edip");
char *line;
// read each set of params from potential file
// one set of params can span multiple lines
// store params if all 3 element tags are in element list
while ((line = reader.next_line(NPARAMS_PER_LINE))) {
try {
ValueTokenizer values(line);
std::string iname = values.next_string();
std::string jname = values.next_string();
std::string kname = values.next_string();
int n, nwords, ielement, jelement, kelement;
char line[MAXLINE], *ptr;
int eof = 0;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next entry in file
int ielement, jelement, kelement;
while (true) {
if (comm->me == 0) {
ptr = fgets(line, MAXLINE, fp);
if (ptr == nullptr) {
eof = 1;
fclose(fp);
} else
n = strlen(line) + 1;
}
MPI_Bcast(&eof, 1, MPI_INT, 0, world);
if (eof) break;
MPI_Bcast(&n, 1, MPI_INT, 0, world);
MPI_Bcast(line, n, MPI_CHAR, 0, world);
for (ielement = 0; ielement < nelements; ielement++)
if (iname == elements[ielement]) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (jname == elements[jelement]) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (kname == elements[kelement]) break;
if (kelement == nelements) continue;
// strip comment, skip line if blank
// load up parameter settings and error check their values
if ((ptr = strchr(line, '#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (nwords == 0) continue;
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
// concatenate additional lines until have params_per_line words
// make certain all addional allocated storage is initialized
// to avoid false positives when checking with valgrind
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n], MAXLINE - n, fp);
if (ptr == nullptr) {
eof = 1;
fclose(fp);
} else
n = strlen(line) + 1;
memset(params + nparams, 0, DELTA*sizeof(Param));
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].A = values.next_double();
params[nparams].B = values.next_double();
params[nparams].cutoffA = values.next_double();
params[nparams].cutoffC = values.next_double();
params[nparams].alpha = values.next_double();
params[nparams].beta = values.next_double();
params[nparams].eta = values.next_double();
params[nparams].gamma = values.next_double();
params[nparams].lambda = values.next_double();
params[nparams].mu = values.next_double();
params[nparams].rho = values.next_double();
params[nparams].sigma = values.next_double();
params[nparams].Q0 = values.next_double();
params[nparams].u1 = values.next_double();
params[nparams].u2 = values.next_double();
params[nparams].u3 = values.next_double();
params[nparams].u4 = values.next_double();
} catch (std::exception &e) {
error->one(FLERR, "Error reading EDIP potential file: {}", e.what());
}
MPI_Bcast(&eof, 1, MPI_INT, 0, world);
if (eof) break;
MPI_Bcast(&n, 1, MPI_INT, 0, world);
MPI_Bcast(line, n, MPI_CHAR, 0, world);
if ((ptr = strchr(line, '#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (params[nparams].A < 0.0 || params[nparams].B < 0.0 || params[nparams].cutoffA < 0.0 ||
params[nparams].cutoffC < 0.0 || params[nparams].alpha < 0.0 ||
params[nparams].beta < 0.0 || params[nparams].eta < 0.0 || params[nparams].gamma < 0.0 ||
params[nparams].lambda < 0.0 || params[nparams].mu < 0.0 || params[nparams].rho < 0.0 ||
params[nparams].sigma < 0.0)
error->all(FLERR, "Illegal EDIP parameter");
nparams++;
}
if (nwords != params_per_line) error->all(FLERR, "Incorrect format in EDIP potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line, " \t\n\r\f");
while ((words[nwords++] = strtok(nullptr, " \t\n\r\f"))) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next entry in file
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0], elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1], elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2], elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params, maxparam * sizeof(Param), "pair:params");
// make certain all addional allocated storage is initialized
// to avoid false positives when checking with valgrind
memset(params + nparams, 0, DELTA * sizeof(Param));
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].A = atof(words[3]);
params[nparams].B = atof(words[4]);
params[nparams].cutoffA = atof(words[5]);
params[nparams].cutoffC = atof(words[6]);
params[nparams].alpha = atof(words[7]);
params[nparams].beta = atof(words[8]);
params[nparams].eta = atof(words[9]);
params[nparams].gamm = atof(words[10]);
params[nparams].lambda = atof(words[11]);
params[nparams].mu = atof(words[12]);
params[nparams].rho = atof(words[13]);
params[nparams].sigma = atof(words[14]);
params[nparams].Q0 = atof(words[15]);
params[nparams].u1 = atof(words[16]);
params[nparams].u2 = atof(words[17]);
params[nparams].u3 = atof(words[18]);
params[nparams].u4 = atof(words[19]);
if (params[nparams].A < 0.0 || params[nparams].B < 0.0 || params[nparams].cutoffA < 0.0 ||
params[nparams].cutoffC < 0.0 || params[nparams].alpha < 0.0 ||
params[nparams].beta < 0.0 || params[nparams].eta < 0.0 || params[nparams].gamm < 0.0 ||
params[nparams].lambda < 0.0 || params[nparams].mu < 0.0 || params[nparams].rho < 0.0 ||
params[nparams].sigma < 0.0)
error->all(FLERR, "Illegal EDIP parameter");
nparams++;
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
delete[] words;
if (comm->me != 0)
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param), "pair:params");
MPI_Bcast(params, maxparam*sizeof(Param), MPI_BYTE, 0, world);
}
/* ---------------------------------------------------------------------- */
@ -946,7 +903,7 @@ void PairEDIP::setup_params()
cutoffC = params[0].cutoffC;
sigma = params[0].sigma;
lambda = params[0].lambda;
gamm = params[0].gamm;
gamm = params[0].gamma;
eta = params[0].eta;
Q0 = params[0].Q0;
mu = params[0].mu;

View File

@ -34,14 +34,23 @@ class PairEDIP : public Pair {
double init_one(int, int);
void init_style();
static constexpr int NPARAMS_PER_LINE = 20;
protected:
struct Param {
double A, B;
double cutoffA, cutoffC, cutsq;
double alpha, beta;
double eta, gamm, lambda, mu, rho, sigma, Q0;
double u1, u2, u3, u4;
int ielement, jelement, kelement;
double A, B; // coefficients for pair interaction I-J
double cutoffA; // cut-off distance for pair interaction I-J
double cutoffC; // lower cut-off distance for calculating Z_I
double alpha; // coefficient for calculating Z_I
double beta; // attractive term for pair I-J
double sigma; // cut-off coefficient for pair I-J
double rho; // pair I-J
double gamma; // coefficient for three-body interaction I-J-K
double eta, lambda; // coefficients for function h(l,Z)
double mu, Q0; // coefficients for function Q(Z)
double u1, u2, u3, u4; // coefficients for function tau(Z)
double cutsq;
int ielement, jelement, kelement, dummy; // dummy added for better alignment
};
double *preInvR_ij;

View File

@ -30,6 +30,7 @@
#include "neigh_list.h"
#include "neigh_request.h"
#include "neighbor.h"
#include "potential_file_reader.h"
#include <cmath>
#include <cstring>
@ -118,8 +119,8 @@ void PairEDIPMulti::compute(int eflag, int vflag)
double costheta;
double dpairZ,dtripleZ;
// eflag != 0 means compute energy contributions in this step
// vflag != 0 means compute virial contributions in this step
// eflag != 0 means compute energy contributions in this step
// vflag != 0 means compute virial contributions in this step
evdwl = 0.0;
ev_init(eflag,vflag);
@ -155,39 +156,40 @@ void PairEDIPMulti::compute(int eflag, int vflag)
// pre-loop to compute environment coordination f(Z)
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
j = jlist[jj];
j &= NEIGHMASK;
double delx, dely, delz, r_ij;
double delx, dely, delz, r_ij;
delx = x[j][0] - xtmp;
dely = x[j][1] - ytmp;
delz = x[j][2] - ztmp;
r_ij = delx * delx + dely * dely + delz * delz;
delx = x[j][0] - xtmp;
dely = x[j][1] - ytmp;
delz = x[j][2] - ztmp;
r_ij = delx * delx + dely * dely + delz * delz;
jtype = map[type[j]];
ijparam = elem3param[itype][jtype][jtype];
if (r_ij > params[ijparam].cutsq) continue;
jtype = map[type[j]];
const Param &param = params[elem3param[itype][jtype][jtype]];
r_ij = sqrt(r_ij);
if (r_ij > param.cutsq) continue;
// zeta and its derivative dZ/dr
r_ij = sqrt(r_ij);
if (r_ij < params[ijparam].cutoffC) zeta_i += 1.0;
else {
double f, fdr;
edip_fc(r_ij, &params[ijparam], f, fdr);
zeta_i += f;
dzetair = -fdr / r_ij;
// zeta and its derivative dZ/dr
preForceCoord_counter=numForceCoordPairs*5;
preForceCoord[preForceCoord_counter+0]=dzetair;
preForceCoord[preForceCoord_counter+1]=delx;
preForceCoord[preForceCoord_counter+2]=dely;
preForceCoord[preForceCoord_counter+3]=delz;
preForceCoord[preForceCoord_counter+4]=j;
numForceCoordPairs++;
}
if (r_ij < param.cutoffC) zeta_i += 1.0;
else {
double f, fdr;
edip_fc(r_ij, param, f, fdr);
zeta_i += f;
dzetair = -fdr / r_ij;
preForceCoord_counter=numForceCoordPairs*5;
preForceCoord[preForceCoord_counter+0]=dzetair;
preForceCoord[preForceCoord_counter+1]=delx;
preForceCoord[preForceCoord_counter+2]=dely;
preForceCoord[preForceCoord_counter+3]=delz;
preForceCoord[preForceCoord_counter+4]=j;
numForceCoordPairs++;
}
}
// two-body interactions
@ -217,7 +219,7 @@ void PairEDIPMulti::compute(int eflag, int vflag)
// already considered in constructing the potential
double fdr, fdZ;
edip_pair(r_ij, zeta_i, &params[ijparam], evdwl, fdr, fdZ);
edip_pair(r_ij, zeta_i, params[ijparam], evdwl, fdr, fdZ);
fpair = -fdr / r_ij;
dpairZ += fdZ;
@ -234,102 +236,102 @@ void PairEDIPMulti::compute(int eflag, int vflag)
// three-body Forces
for (kk = jj + 1; kk < jnum; kk++) {
double dr_ik[3], r_ik, f_ik[3];
double dr_ik[3], r_ik, f_ik[3];
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
ikparam = elem3param[itype][ktype][ktype];
ijkparam = elem3param[itype][jtype][ktype];
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
ikparam = elem3param[itype][ktype][ktype];
ijkparam = elem3param[itype][jtype][ktype];
dr_ik[0] = x[k][0] - xtmp;
dr_ik[1] = x[k][1] - ytmp;
dr_ik[2] = x[k][2] - ztmp;
r_ik = dr_ik[0]*dr_ik[0] + dr_ik[1]*dr_ik[1] + dr_ik[2]*dr_ik[2];
dr_ik[0] = x[k][0] - xtmp;
dr_ik[1] = x[k][1] - ytmp;
dr_ik[2] = x[k][2] - ztmp;
r_ik = dr_ik[0]*dr_ik[0] + dr_ik[1]*dr_ik[1] + dr_ik[2]*dr_ik[2];
if (r_ik > params[ikparam].cutsq) continue;
if (r_ik > params[ikparam].cutsq) continue;
r_ik = sqrt(r_ik);
r_ik = sqrt(r_ik);
costheta=dot3(dr_ij, dr_ik) / r_ij / r_ik;
costheta=dot3(dr_ij, dr_ik) / r_ij / r_ik;
double v1, v2, v3, v4, v5, v6, v7;
double v1, v2, v3, v4, v5, v6, v7;
edip_fcut3(r_ij, &params[ijparam], v1, v2);
edip_fcut3(r_ik, &params[ikparam], v3, v4);
edip_h(costheta, zeta_i, &params[ijkparam], v5, v6, v7);
edip_fcut3(r_ij, params[ijparam], v1, v2);
edip_fcut3(r_ik, params[ikparam], v3, v4);
edip_h(costheta, zeta_i, params[ijkparam], v5, v6, v7);
// potential energy and forces
evdwl = v1 * v3 * v5;
dtripleZ += v1 * v3 * v7;
// potential energy and forces
evdwl = v1 * v3 * v5;
dtripleZ += v1 * v3 * v7;
double dri[3], drj[3], drk[3];
double dhl, dfr;
double dri[3], drj[3], drk[3];
double dhl, dfr;
dhl = v1 * v3 * v6;
dhl = v1 * v3 * v6;
costheta_d(dr_ij, r_ij, dr_ik, r_ik, dri, drj, drk);
costheta_d(dr_ij, r_ij, dr_ik, r_ik, dri, drj, drk);
f_ij[0] = -dhl * drj[0];
f_ij[1] = -dhl * drj[1];
f_ij[2] = -dhl * drj[2];
f_ik[0] = -dhl * drk[0];
f_ik[1] = -dhl * drk[1];
f_ik[2] = -dhl * drk[2];
f_ij[0] = -dhl * drj[0];
f_ij[1] = -dhl * drj[1];
f_ij[2] = -dhl * drj[2];
f_ik[0] = -dhl * drk[0];
f_ik[1] = -dhl * drk[1];
f_ik[2] = -dhl * drk[2];
dfr = v2 * v3 * v5;
fpair = -dfr / r_ij;
dfr = v2 * v3 * v5;
fpair = -dfr / r_ij;
f_ij[0] += fpair * dr_ij[0];
f_ij[1] += fpair * dr_ij[1];
f_ij[2] += fpair * dr_ij[2];
f_ij[0] += fpair * dr_ij[0];
f_ij[1] += fpair * dr_ij[1];
f_ij[2] += fpair * dr_ij[2];
dfr = v1 * v4 * v5;
fpair = -dfr / r_ik;
dfr = v1 * v4 * v5;
fpair = -dfr / r_ik;
f_ik[0] += fpair * dr_ik[0];
f_ik[1] += fpair * dr_ik[1];
f_ik[2] += fpair * dr_ik[2];
f_ik[0] += fpair * dr_ik[0];
f_ik[1] += fpair * dr_ik[1];
f_ik[2] += fpair * dr_ik[2];
f[j][0] += f_ij[0];
f[j][1] += f_ij[1];
f[j][2] += f_ij[2];
f[j][0] += f_ij[0];
f[j][1] += f_ij[1];
f[j][2] += f_ij[2];
f[k][0] += f_ik[0];
f[k][1] += f_ik[1];
f[k][2] += f_ik[2];
f[k][0] += f_ik[0];
f[k][1] += f_ik[1];
f[k][2] += f_ik[2];
f[i][0] -= f_ij[0] + f_ik[0];
f[i][1] -= f_ij[1] + f_ik[1];
f[i][2] -= f_ij[2] + f_ik[2];
f[i][0] -= f_ij[0] + f_ik[0];
f[i][1] -= f_ij[1] + f_ik[1];
f[i][2] -= f_ij[2] + f_ik[2];
if (evflag) ev_tally3(i,j,k,evdwl,0.0,f_ij,f_ik,dr_ij,dr_ik);
if (evflag) ev_tally3(i,j,k,evdwl,0.0,f_ij,f_ik,dr_ij,dr_ik);
}
}
// forces due to environment coordination f(Z)
for (int idx = 0; idx < numForceCoordPairs; idx++) {
double delx, dely, delz;
double delx, dely, delz;
preForceCoord_counter = idx * 5;
dzetair = preForceCoord[preForceCoord_counter+0];
delx = preForceCoord[preForceCoord_counter+1];
dely = preForceCoord[preForceCoord_counter+2];
delz = preForceCoord[preForceCoord_counter+3];
j = static_cast<int> (preForceCoord[preForceCoord_counter+4]);
preForceCoord_counter = idx * 5;
dzetair = preForceCoord[preForceCoord_counter+0];
delx = preForceCoord[preForceCoord_counter+1];
dely = preForceCoord[preForceCoord_counter+2];
delz = preForceCoord[preForceCoord_counter+3];
j = static_cast<int> (preForceCoord[preForceCoord_counter+4]);
dzetair *= (dpairZ + dtripleZ);
dzetair *= (dpairZ + dtripleZ);
f[j][0] += dzetair * delx;
f[j][1] += dzetair * dely;
f[j][2] += dzetair * delz;
f[j][0] += dzetair * delx;
f[j][1] += dzetair * dely;
f[j][2] += dzetair * delz;
f[i][0] -= dzetair * delx;
f[i][1] -= dzetair * dely;
f[i][2] -= dzetair * delz;
f[i][0] -= dzetair * delx;
f[i][1] -= dzetair * dely;
f[i][2] -= dzetair * delz;
evdwl = 0.0;
if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0, dzetair, -delx, -dely, -delz);
evdwl = 0.0;
if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0, dzetair, -delx, -dely, -delz);
}
}
@ -342,13 +344,13 @@ double sqr(double x)
}
//pair Vij, partial derivatives dVij(r,Z)/dr and dVij(r,Z)/dZ
void PairEDIPMulti::edip_pair(double r, double z, Param *param, double &eng,
void PairEDIPMulti::edip_pair(double r, double z, const Param &param, double &eng,
double &fdr, double &fZ)
{
double A = param->A;
double B = param->B;
double rho = param->rho;
double beta = param->beta;
double A = param.A;
double B = param.B;
double rho = param.rho;
double beta = param.beta;
double v1,v2,v3,v4;
v1 = pow(B / r, rho);
@ -361,11 +363,11 @@ void PairEDIPMulti::edip_pair(double r, double z, Param *param, double &eng,
}
//function fc(r) in calculating coordination Z and derivative fc'(r)
void PairEDIPMulti::edip_fc(double r, Param *param, double &f, double &fdr)
void PairEDIPMulti::edip_fc(double r, const Param &param, double &f, double &fdr)
{
double a = param->cutoffA;
double c = param->cutoffC;
double alpha = param->alpha;
double a = param.cutoffA;
double c = param.cutoffC;
double alpha = param.alpha;
double x;
double v1, v2;
@ -392,10 +394,10 @@ void PairEDIPMulti::edip_fc(double r, Param *param, double &f, double &fdr)
}
//cut-off function for Vij and its derivative fcut2'(r)
void PairEDIPMulti::edip_fcut2(double r, Param *param, double &f, double &fdr)
void PairEDIPMulti::edip_fcut2(double r, const Param &param, double &f, double &fdr)
{
double sigma = param->sigma;
double a = param->cutoffA;
double sigma = param.sigma;
double a = param.cutoffA;
double v1;
if (r > a - 1E-6)
@ -411,12 +413,12 @@ void PairEDIPMulti::edip_fcut2(double r, Param *param, double &f, double &fdr)
}
//function tau(Z) and its derivative tau'(Z)
void PairEDIPMulti::edip_tau(double z, Param *param, double &f, double &fdZ)
void PairEDIPMulti::edip_tau(double z, const Param &param, double &f, double &fdZ)
{
double u1 = param->u1;
double u2 = param->u2;
double u3 = param->u3;
double u4 = param->u4;
double u1 = param.u1;
double u2 = param.u2;
double u3 = param.u3;
double u4 = param.u4;
double v1, v2;
v1 = exp(-u4 * z);
@ -427,13 +429,13 @@ void PairEDIPMulti::edip_tau(double z, Param *param, double &f, double &fdZ)
}
//function h(l,Z) and its partial derivatives dh(l,Z)/dl and dh(l,Z)/dZ
void PairEDIPMulti::edip_h(double l, double z, Param *param, double &f,
void PairEDIPMulti::edip_h(double l, double z, const Param &param, double &f,
double &fdl, double &fdZ)
{
double lambda = param->lambda;
double eta = param->eta;
double Q0 = param->Q0;
double mu = param->mu;
double lambda = param.lambda;
double eta = param.eta;
double Q0 = param.Q0;
double mu = param.mu;
double Q, QdZ, Tau, TaudZ;
double u2, du2l, du2Z;
double v1, v2, v3;
@ -464,10 +466,10 @@ void PairEDIPMulti::edip_h(double l, double z, Param *param, double &f,
}
//cut-off function for Vijk and its derivative fcut3'(r)
void PairEDIPMulti::edip_fcut3(double r, Param *param, double &f, double &fdr)
void PairEDIPMulti::edip_fcut3(double r, const Param &param, double &f, double &fdr)
{
double gamma = param->gamma;
double a = param->cutoffA;
double gamma = param.gamma;
double a = param.cutoffA;
double v1;
if (r > a - 1E-6)
@ -578,137 +580,92 @@ double PairEDIPMulti::init_one(int i, int j)
void PairEDIPMulti::read_file(char *file)
{
int params_per_line = 20;
char **words = new char*[params_per_line+1];
memory->sfree(params);
params = nullptr;
nparams = maxparam = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = utils::open_potential(file,lmp,nullptr);
if (fp == nullptr)
error->one(FLERR,"Cannot open EDIP potential file {}: {}",file,utils::getsyserror());
}
PotentialFileReader reader(lmp, file, "edip");
char *line;
// read each set of params from potential file
// one set of params can span multiple lines
// store params if all 3 element tags are in element list
while ((line = reader.next_line(NPARAMS_PER_LINE))) {
try {
ValueTokenizer values(line);
std::string iname = values.next_string();
std::string jname = values.next_string();
std::string kname = values.next_string();
int n,nwords,ielement,jelement,kelement;
char line[MAXLINE],*ptr;
int eof = 0;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next entry in file
int ielement, jelement, kelement;
while (true) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == nullptr) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
for (ielement = 0; ielement < nelements; ielement++)
if (iname == elements[ielement]) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (jname == elements[jelement]) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (kname == elements[kelement]) break;
if (kelement == nelements) continue;
// strip comment, skip line if blank
// load up parameter settings and error check their values
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (nwords == 0) continue;
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
// concatenate additional lines until have params_per_line words
// make certain all addional allocated storage is initialized
// to avoid false positives when checking with valgrind
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == nullptr) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
memset(params + nparams, 0, DELTA*sizeof(Param));
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].A = values.next_double();
params[nparams].B = values.next_double();
params[nparams].cutoffA = values.next_double();
params[nparams].cutoffC = values.next_double();
params[nparams].alpha = values.next_double();
params[nparams].beta = values.next_double();
params[nparams].eta = values.next_double();
params[nparams].gamma = values.next_double();
params[nparams].lambda = values.next_double();
params[nparams].mu = values.next_double();
params[nparams].rho = values.next_double();
params[nparams].sigma = values.next_double();
params[nparams].Q0 = values.next_double();
params[nparams].u1 = values.next_double();
params[nparams].u2 = values.next_double();
params[nparams].u3 = values.next_double();
params[nparams].u4 = values.next_double();
} catch (std::exception &e) {
error->one(FLERR, "Error reading EDIP potential file: {}", e.what());
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (params[nparams].A < 0.0 || params[nparams].B < 0.0 || params[nparams].cutoffA < 0.0 ||
params[nparams].cutoffC < 0.0 || params[nparams].alpha < 0.0 ||
params[nparams].beta < 0.0 || params[nparams].eta < 0.0 || params[nparams].gamma < 0.0 ||
params[nparams].lambda < 0.0 || params[nparams].mu < 0.0 || params[nparams].rho < 0.0 ||
params[nparams].sigma < 0.0)
error->all(FLERR, "Illegal EDIP parameter");
nparams++;
}
if (nwords != params_per_line)
error->all(FLERR,"Incorrect format in EDIP potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line," \t\n\r\f");
while ((words[nwords++] = strtok(nullptr," \t\n\r\f"))) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next entry in file
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0],elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1],elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2],elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
// make certain all addional allocated storage is initialized
// to avoid false positives when checking with valgrind
memset(params + nparams, 0, DELTA*sizeof(Param));
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].A = atof(words[3]);
params[nparams].B = atof(words[4]);
params[nparams].cutoffA = atof(words[5]);
params[nparams].cutoffC = atof(words[6]);
params[nparams].alpha = atof(words[7]);
params[nparams].beta = atof(words[8]);
params[nparams].eta = atof(words[9]);
params[nparams].gamma = atof(words[10]);
params[nparams].lambda = atof(words[11]);
params[nparams].mu = atof(words[12]);
params[nparams].rho = atof(words[13]);
params[nparams].sigma = atof(words[14]);
params[nparams].Q0 = atof(words[15]);
params[nparams].u1 = atof(words[16]);
params[nparams].u2 = atof(words[17]);
params[nparams].u3 = atof(words[18]);
params[nparams].u4 = atof(words[19]);
if (params[nparams].A < 0.0 || params[nparams].B < 0.0 ||
params[nparams].cutoffA < 0.0 || params[nparams].cutoffC < 0.0 ||
params[nparams].alpha < 0.0 || params[nparams].beta < 0.0 ||
params[nparams].eta < 0.0 || params[nparams].gamma < 0.0 ||
params[nparams].lambda < 0.0 || params[nparams].mu < 0.0 ||
params[nparams].rho < 0.0 || params[nparams].sigma < 0.0)
error->all(FLERR,"Illegal EDIP parameter");
nparams++;
}
MPI_Bcast(&nparams, 1, MPI_INT, 0, world);
MPI_Bcast(&maxparam, 1, MPI_INT, 0, world);
delete [] words;
if (comm->me != 0)
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param), "pair:params");
MPI_Bcast(params, maxparam*sizeof(Param), MPI_BYTE, 0, world);
}
/* ---------------------------------------------------------------------- */
@ -753,5 +710,4 @@ void PairEDIPMulti::setup()
rtmp = sqrt(params[m].cutsq);
if (rtmp > cutmax) cutmax = rtmp;
}
}

View File

@ -34,6 +34,8 @@ class PairEDIPMulti : public Pair {
double init_one(int, int);
void init_style();
static constexpr int NPARAMS_PER_LINE = 20;
protected:
struct Param {
double A, B; // coefficients for pair interaction I-J
@ -48,7 +50,7 @@ class PairEDIPMulti : public Pair {
double mu, Q0; // coefficients for function Q(Z)
double u1, u2, u3, u4; // coefficients for function tau(Z)
double cutsq;
int ielement, jelement, kelement;
int ielement, jelement, kelement, dummy; // dummy added for better alignment
};
double *preForceCoord;
@ -63,12 +65,12 @@ class PairEDIPMulti : public Pair {
void read_file(char *);
void setup();
void edip_pair(double, double, Param *, double &, double &, double &);
void edip_fc(double, Param *, double &, double &);
void edip_fcut2(double, Param *, double &, double &);
void edip_tau(double, Param *, double &, double &);
void edip_h(double, double, Param *, double &, double &, double &);
void edip_fcut3(double, Param *, double &, double &);
void edip_pair(double, double, const Param &, double &, double &, double &);
void edip_fc(double, const Param &, double &, double &);
void edip_fcut2(double, const Param &, double &, double &);
void edip_tau(double, const Param &, double &, double &);
void edip_h(double, double, const Param &, double &, double &, double &);
void edip_fcut3(double, const Param &, double &, double &);
};
} // namespace LAMMPS_NS

View File

@ -431,8 +431,7 @@ void PairTersoff::read_file(char *file)
// transparently convert units for supported conversions
int unit_convert = reader.get_unit_convert();
double conversion_factor = utils::get_conversion_factor(utils::ENERGY,
unit_convert);
double conversion_factor = utils::get_conversion_factor(utils::ENERGY,unit_convert);
while ((line = reader.next_line(NPARAMS_PER_LINE))) {
try {
ValueTokenizer values(line);

View File

@ -18,19 +18,28 @@
#include "pair_list.h"
#include <cstring>
#include <cmath>
#include "atom.h"
#include "comm.h"
#include "error.h"
#include "force.h"
#include "memory.h"
#include "error.h"
#include "text_file_reader.h"
#include "tokenizer.h"
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
using namespace LAMMPS_NS;
static const char * const stylename[] = {
"none", "harmonic", "morse", "lj126", nullptr
enum { NONE = 0, HARM, MORSE, LJ126 };
static std::map<std::string, int> stylename = {
{ "none", NONE },
{ "harmonic", HARM },
{ "morse", MORSE },
{ "lj126", LJ126 }
};
// fast power function for integer exponent > 0
@ -55,7 +64,6 @@ PairList::PairList(LAMMPS *lmp) : Pair(lmp)
restartinfo = 0;
respa_enable = 0;
cut_global = 0.0;
style = nullptr;
params = nullptr;
check_flag = 1;
}
@ -66,7 +74,6 @@ PairList::~PairList()
{
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(style);
memory->destroy(params);
}
@ -90,7 +97,7 @@ void PairList::compute(int eflag, int vflag)
int pc = 0;
for (int n=0; n < npairs; ++n) {
const list_parm_t &par = params[n];
const list_param &par = params[n];
i = atom->map(par.id1);
j = atom->map(par.id2);
@ -122,34 +129,34 @@ void PairList::compute(int eflag, int vflag)
if (rsq < par.cutsq) {
const double r2inv = 1.0/rsq;
if (style[n] == HARM) {
if (par.style == HARM) {
const double r = sqrt(rsq);
const double dr = par.parm.harm.r0 - r;
fpair = 2.0*par.parm.harm.k*dr/r;
const double dr = par.param.harm.r0 - r;
fpair = 2.0*par.param.harm.k*dr/r;
if (eflag_either)
epair = par.parm.harm.k*dr*dr - par.offset;
epair = par.param.harm.k*dr*dr - par.offset;
} else if (style[n] == MORSE) {
} else if (par.style == MORSE) {
const double r = sqrt(rsq);
const double dr = par.parm.morse.r0 - r;
const double dexp = exp(par.parm.morse.alpha * dr);
fpair = 2.0*par.parm.morse.d0*par.parm.morse.alpha
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;
if (eflag_either)
epair = par.parm.morse.d0 * (dexp*dexp - 2.0*dexp) - par.offset;
epair = par.param.morse.d0 * (dexp*dexp - 2.0*dexp) - par.offset;
} else if (style[n] == LJ126) {
} else if (par.style == LJ126) {
const double r6inv = r2inv*r2inv*r2inv;
const double sig6 = mypow(par.parm.lj126.sigma,6);
fpair = 24.0*par.parm.lj126.epsilon*r6inv
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.parm.lj126.epsilon*r6inv
epair = 4.0*par.param.lj126.epsilon*r6inv
* (sig6*sig6*r6inv - sig6) - par.offset;
}
@ -210,130 +217,73 @@ void PairList::settings(int narg, char **arg)
if (strcmp(arg[2],"check") == 0) check_flag = 1;
}
FILE *fp = utils::open_potential(arg[0],lmp,nullptr);
char line[1024];
if (fp == nullptr)
error->all(FLERR,"Cannot open pair list file");
std::vector<int> mystyles;
std::vector<list_param> myparams;
// count lines in file for upper limit of storage needed
int num = 1;
while (fgets(line,1024,fp)) ++num;
rewind(fp);
memory->create(style,num,"pair_list:style");
memory->create(params,num,"pair_list:params");
// now read and parse pair list file for real
npairs = 0;
char *ptr;
tagint id1, id2;
int nharm=0, nmorse=0, nlj126=0;
while (fgets(line,1024,fp)) {
ptr = strtok(line," \t\n\r\f");
// skip empty lines
if (!ptr) continue;
// skip comment lines starting with #
if (*ptr == '#') continue;
// get atom ids of pair
id1 = ATOTAGINT(ptr);
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted pair list file");
id2 = ATOTAGINT(ptr);
// get potential type
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted pair list file");
style[npairs] = NONE;
list_parm_t &par = params[npairs];
par.id1 = id1;
par.id2 = id2;
// harmonic potential
if (strcmp(ptr,stylename[HARM]) == 0) {
style[npairs] = HARM;
ptr = strtok(nullptr," \t\n\r\f");
if ((ptr == nullptr) || (*ptr == '#'))
error->all(FLERR,"Incorrectly formatted harmonic pair parameters");
par.parm.harm.k = utils::numeric(FLERR,ptr,false,lmp);
ptr = strtok(nullptr," \t\n\r\f");
if ((ptr == nullptr) || (*ptr == '#'))
error->all(FLERR,"Incorrectly formatted harmonic pair parameters");
par.parm.harm.r0 = utils::numeric(FLERR,ptr,false,lmp);
++nharm;
// morse potential
} else if (strcmp(ptr,stylename[MORSE]) == 0) {
style[npairs] = MORSE;
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted morse pair parameters");
par.parm.morse.d0 = utils::numeric(FLERR,ptr,false,lmp);
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted morse pair parameters");
par.parm.morse.alpha = utils::numeric(FLERR,ptr,false,lmp);
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted morse pair parameters");
par.parm.morse.r0 = utils::numeric(FLERR,ptr,false,lmp);
++nmorse;
} else if (strcmp(ptr,stylename[LJ126]) == 0) {
// 12-6 lj potential
style[npairs] = LJ126;
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted 12-6 LJ pair parameters");
par.parm.lj126.epsilon = utils::numeric(FLERR,ptr,false,lmp);
ptr = strtok(nullptr," \t\n\r\f");
if (!ptr)
error->all(FLERR,"Incorrectly formatted 12-6 LJ pair parameters");
par.parm.lj126.sigma = utils::numeric(FLERR,ptr,false,lmp);
++nlj126;
} else {
error->all(FLERR,"Unknown pair list potential style");
}
// optional cutoff parameter. if not specified use global value
ptr = strtok(nullptr," \t\n\r\f");
if ((ptr != nullptr) && (*ptr != '#')) {
double cut = utils::numeric(FLERR,ptr,false,lmp);
par.cutsq = cut*cut;
} else {
par.cutsq = cut_global*cut_global;
}
// count complete entry
++npairs;
}
fclose(fp);
// informative output
// read and parse potential file only on MPI rank 0.
if (comm->me == 0) {
if (screen)
fprintf(screen,"Read %d (%d/%d/%d) interacting pairs from %s\n",
npairs, nharm, nmorse, nlj126, arg[0]);
if (logfile)
fprintf(logfile,"Read %d (%d/%d/%d) interacting pairs from %s\n",
npairs, nharm, nmorse, nlj126, arg[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;
try {
char *line;
while ((line = reader.next_line())) {
ValueTokenizer values(line);
list_param oneparam;
oneparam.id1 = values.next_tagint();
oneparam.id2 = values.next_tagint();
oneparam.style = stylename[values.next_string()];
++npairs;
switch (oneparam.style) {
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 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;
}
if (values.has_next())
oneparam.cutsq = values.next_double();
else
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());
}
utils::logmesg(lmp, "Read {} ({}/{}/{}) interacting pair lines from {}. "
"{} skipped entries.\n", npairs, nharm, nmorse, nlj126, arg[0], nskipped);
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);
}
/* ----------------------------------------------------------------------
@ -374,21 +324,21 @@ void PairList::init_style()
if (offset_flag) {
for (int n=0; n < npairs; ++n) {
list_parm_t &par = params[n];
list_param &par = params[n];
if (style[n] == HARM) {
const double dr = sqrt(par.cutsq) - par.parm.harm.r0;
par.offset = par.parm.harm.k*dr*dr;
if (par.style == HARM) {
const double dr = sqrt(par.cutsq) - par.param.harm.r0;
par.offset = par.param.harm.k*dr*dr;
} else if (style[n] == MORSE) {
const double dr = par.parm.morse.r0 - sqrt(par.cutsq);
const double dexp = exp(par.parm.morse.alpha * dr);
par.offset = par.parm.morse.d0 * (dexp*dexp - 2.0*dexp);
} 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);
} else if (style[n] == LJ126) {
} else if (par.style == LJ126) {
const double r6inv = par.cutsq*par.cutsq*par.cutsq;
const double sig6 = mypow(par.parm.lj126.sigma,6);
par.offset = 4.0*par.parm.lj126.epsilon*r6inv * (sig6*sig6*r6inv - sig6);
const double sig6 = mypow(par.param.lj126.sigma,6);
par.offset = 4.0*par.param.lj126.epsilon*r6inv * (sig6*sig6*r6inv - sig6);
}
}
}
@ -411,7 +361,7 @@ double PairList::init_one(int, int)
double PairList::memory_usage()
{
double bytes = (double)npairs * sizeof(int);
bytes += (double)npairs * sizeof(list_parm_t);
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 *));

View File

@ -39,8 +39,6 @@ class PairList : public Pair {
protected:
void allocate();
enum { NONE = 0, HARM, MORSE, LJ126 };
// potential specific parameters
struct harm_p {
double k, r0;
@ -52,23 +50,23 @@ class PairList : public Pair {
double epsilon, sigma;
};
union parm_u {
struct harm_p harm;
struct morse_p morse;
struct lj126_p lj126;
union param_u {
harm_p harm;
morse_p morse;
lj126_p lj126;
};
typedef struct {
struct list_param {
int style; // potential style indicator
tagint id1, id2; // global atom ids
double cutsq; // cutoff**2 for this pair
double offset; // energy offset
union parm_u parm; // parameters for style
} list_parm_t;
union param_u param; // parameters for style
};
protected:
double cut_global; // global cutoff distance
int *style; // list of styles for pair interactions
list_parm_t *params; // lisf of pair interaction parameters
list_param *params; // lisf of pair interaction parameters
int npairs; // # of atom pairs in global list
int check_flag; // 1 if checking for missing pairs
};

View File

@ -37,6 +37,7 @@
#include "force.h"
#include "math_const.h"
#include "memory.h"
#include "potential_file_reader.h"
#include "respa.h"
#include "tokenizer.h"
#include "update.h"
@ -634,150 +635,23 @@ double FixCMAP::compute_scalar()
void FixCMAP::read_grid_map(char *cmapfile)
{
char linebuf[MAXLINE];
char *chunk,*line;
int i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, j5, j6, counter;
FILE *fp = nullptr;
if (comm->me == 0) {
fp = utils::open_potential(cmapfile,lmp,nullptr);
if (fp == nullptr)
error->one(FLERR,"Cannot open fix cmap file {}: {}",
cmapfile, utils::getsyserror());
try {
memset(&cmapgrid[0][0][0], 6*CMAPDIM*CMAPDIM, sizeof(double));
PotentialFileReader reader(lmp, cmapfile, "cmap grid");
}
// there are six maps in this order.
// alanine, alanine-proline, proline, proline-proline, glycine, glycine-proline.
// read as one big blob of numbers while ignoring comments
for (int ix1 = 0; ix1 < 6; ix1++)
for (int ix2 = 0; ix2 < CMAPDIM; ix2++)
for (int ix3 = 0; ix3 < CMAPDIM; ix3++)
cmapgrid[ix1][ix2][ix3] = 0.0;
reader.next_dvector(&cmapgrid[0][0][0],6*CMAPDIM*CMAPDIM);
counter = 0;
i1 = i2 = i3 = i4 = i5 = i6 = 0;
j1 = j2 = j3 = j4 = j5 = j6 = 0;
int done = 0;
while (!done) {
// only read on rank 0 and broadcast to all other ranks
if (comm->me == 0)
done = (fgets(linebuf,MAXLINE,fp) == nullptr);
MPI_Bcast(&done,1,MPI_INT,0,world);
if (done) continue;
MPI_Bcast(linebuf,MAXLINE,MPI_CHAR,0,world);
// remove leading whitespace
line = linebuf;
while (line && (*line == ' ' || *line == '\t' || *line == '\r')) ++line;
// skip if empty line or comment
if (!line || *line =='\n' || *line == '\0' || *line == '#') continue;
// read in the cmap grid point values
// NOTE: The order to read the 6 grid maps is HARD-CODED, thus errors
// will occur if content of the file "cmap.data" is altered
//
// Reading order of the maps:
// 1. Alanine map
// 2. Alanine before proline map
// 3. Proline map
// 4. Two adjacent prolines map
// 5. Glycine map
// 6. Glycine before proline map
chunk = strtok(line, " \r\n");
while (chunk != nullptr) {
// alanine map
if (counter < CMAPDIM*CMAPDIM) {
cmapgrid[0][i1][j1] = atof(chunk);
chunk = strtok(nullptr, " \r\n");
j1++;
if (j1 == CMAPDIM) {
j1 = 0;
i1++;
}
counter++;
}
// alanine-proline map
else if (counter >= CMAPDIM*CMAPDIM &&
counter < 2*CMAPDIM*CMAPDIM) {
cmapgrid[1][i2][j2]= atof(chunk);
chunk = strtok(nullptr, " \r\n");
j2++;
if (j2 == CMAPDIM) {
j2 = 0;
i2++;
}
counter++;
}
// proline map
else if (counter >= 2*CMAPDIM*CMAPDIM &&
counter < 3*CMAPDIM*CMAPDIM) {
cmapgrid[2][i3][j3] = atof(chunk);
chunk = strtok(nullptr, " \r\n");
j3++;
if (j3 == CMAPDIM) {
j3 = 0;
i3++;
}
counter++;
}
// 2 adjacent prolines map
else if (counter >= 3*CMAPDIM*CMAPDIM &&
counter < 4*CMAPDIM*CMAPDIM) {
cmapgrid[3][i4][j4] = atof(chunk);
chunk = strtok(nullptr, " \r\n");
j4++;
if (j4 == CMAPDIM) {
j4 = 0;
i4++;
}
counter++;
}
// glycine map
else if (counter >= 4*CMAPDIM*CMAPDIM &&
counter < 5*CMAPDIM*CMAPDIM) {
cmapgrid[4][i5][j5] = atof(chunk);
chunk = strtok(nullptr, " \r\n");
j5++;
if (j5 == CMAPDIM) {
j5 = 0;
i5++;
}
counter++;
}
// glycine-proline map
else if (counter >= 5*CMAPDIM*CMAPDIM &&
counter < 6*CMAPDIM*CMAPDIM) {
cmapgrid[5][i6][j6] = atof(chunk);
chunk = strtok(nullptr, " \r\n");
j6++;
if (j6 == CMAPDIM) {
j6 = 0;
i6++;
}
counter++;
}
else break;
} catch (std::exception &e) {
error->one(FLERR,"Error reading CMAP potential file: {}", e.what());
}
}
if (comm->me == 0) fclose(fp);
MPI_Bcast(&cmapgrid[0][0][0],6*CMAPDIM*CMAPDIM,MPI_DOUBLE,0,world);
}
/* ---------------------------------------------------------------------- */