Merge branch 'master' into plugin-loader

This commit is contained in:
Axel Kohlmeyer
2021-03-11 15:02:33 -05:00
8 changed files with 247 additions and 197 deletions

View File

@ -1,4 +1,4 @@
.TH LAMMPS "10 February 2021" "2021-02-10"
.TH LAMMPS "10 March 2021" "2021-03-10"
.SH NAME
.B LAMMPS
\- Molecular Dynamics Simulator.

View File

@ -88,9 +88,12 @@ that will be used with other potentials.
The name of the SNAP coefficient file usually ends in the
".snapcoeff" extension. It may contain coefficients
for many SNAP elements. The only requirement is that it
contain at least those element names appearing in the
LAMMPS mapping list.
for many SNAP elements. The only requirement is that
each of the unique element names appearing in the
LAMMPS pair_coeff command appear exactly once in
the SNAP coefficient file. It is okay if the SNAP coefficient file
contains additional elements not in the pair_coeff command,
except when using *chemflag* (see below).
The name of the SNAP parameter file usually ends in the ".snapparam"
extension. It contains a small number
of parameters that define the overall form of the SNAP potential.
@ -129,7 +132,7 @@ line must contain two integers:
This is followed by one block for each of the *nelem* elements.
The first line of each block contains three entries:
* Element symbol (text string)
* Element name (text string)
* R = Element radius (distance units)
* w = Element weight (dimensionless)
@ -166,8 +169,8 @@ where :math:`\mathbf{B}_i` is the *K*-vector of bispectrum components,
:math:`\boldsymbol{\beta}^{\mu_i}` is the *K*-vector of linear coefficients
for element :math:`\mu_i`, and :math:`\boldsymbol{\alpha}^{\mu_i}`
is the symmetric *K* by *K* matrix of quadratic coefficients.
The SNAP element file should contain *K*\ (\ *K*\ +1)/2 additional coefficients
for each element, the upper-triangular elements of :math:`\boldsymbol{\alpha}^{\mu_i}`.
The SNAP coefficient file should contain *K*\ (\ *K*\ +1)/2 additional coefficients
in each element block, the upper-triangular elements of :math:`\boldsymbol{\alpha}^{\mu_i}`.
If *chemflag* is set to 1, then the energy expression is written in terms of explicit multi-element bispectrum
components indexed on ordered triplets of elements, which has been shown to increase the ability of the SNAP
@ -181,8 +184,12 @@ at the expense of a significant increase in computational cost :ref:`(Cusentino)
where :math:`\mathbf{B}^{\kappa\lambda\mu}_i` is the *K*-vector of bispectrum components
for neighbors of elements :math:`\kappa`, :math:`\lambda`, and :math:`\mu` and
:math:`\boldsymbol{\beta}^{\kappa\lambda\mu}_{\mu_i}` is the corresponding *K*-vector
of linear coefficients for element :math:`\mu_i`. The SNAP element file should contain
a total of :math:`K N_{elem}^3` coefficients for each of the :math:`N_{elem}` elements.
of linear coefficients for element :math:`\mu_i`. The SNAP coefficient file should contain
a total of :math:`K N_{elem}^3` coefficients in each element block,
where :math:`N_{elem}` is the number of elements in the SNAP coefficient file,
which must equal the number of unique elements appearing in the
LAMMPS pair_coeff command, to avoid ambiguity in the
number of coefficients.
The keyword *chunksize* is only applicable when using the
pair style *snap* with the KOKKOS package and is ignored otherwise.

View File

@ -108,7 +108,7 @@ void KimInit::command(int narg, char **arg)
determine_model_type_and_units(model_name, user_units, &model_units, pkim);
write_log_cite(model_name);
write_log_cite(lmp, model_type, model_name);
do_init(model_name, user_units, model_units, pkim);
}
@ -488,7 +488,9 @@ void KimInit::do_variables(const std::string &from, const std::string &to)
/* ---------------------------------------------------------------------- */
void KimInit::write_log_cite(char *model_name)
void KimInit::write_log_cite(class LAMMPS *lmp,
KimInit::model_type_enum model_type,
char *model_name)
{
if (!lmp->citeme) return;
@ -496,50 +498,52 @@ void KimInit::write_log_cite(char *model_name)
std::string re = "[MS][OM]_\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d_\\d\\d\\d";
std::string kim_id = utils::strfind(model_name_str, re);
if (kim_id.empty()) return;
KIM_Collections *collections;
int err = KIM_Collections_Create(&collections);
if (err) return;
auto logID = fmt::format("{}_Collections", comm->me);
KIM_Collections_SetLogID(collections, logID.c_str());
int extent;
if (model_type == MO) {
err = KIM_Collections_CacheListOfItemMetadataFiles(
collections, KIM_COLLECTION_ITEM_TYPE_portableModel,
model_name, &extent);
} else if (model_type == SM) {
err = KIM_Collections_CacheListOfItemMetadataFiles(
collections, KIM_COLLECTION_ITEM_TYPE_simulatorModel,
model_name, &extent);
std::string cite_id;
if (kim_id.empty()) {
cite_id = fmt::format("KIM potential: unpublished, \"{}\"\n",model_name_str);
} else {
error->all(FLERR, "Unknown model type");
}
KIM_Collections *collections;
int err = KIM_Collections_Create(&collections);
if (err) return;
if (err) {
auto logID = fmt::format("{}_Collections", lmp->comm->me);
KIM_Collections_SetLogID(collections, logID.c_str());
int extent;
if (model_type == MO) {
err = KIM_Collections_CacheListOfItemMetadataFiles(
collections, KIM_COLLECTION_ITEM_TYPE_portableModel,
model_name, &extent);
} else if (model_type == SM) {
err = KIM_Collections_CacheListOfItemMetadataFiles(
collections, KIM_COLLECTION_ITEM_TYPE_simulatorModel,
model_name, &extent);
} else {
lmp->error->all(FLERR, "Unknown model type");
}
if (err) {
KIM_Collections_Destroy(&collections);
return;
}
cite_id = fmt::format("OpenKIM potential: https://openkim.org/cite/"
"{}#item-citation\n\n",kim_id);
for (int i = 0; i < extent; ++i) {
char const *fileName;
int availableAsString;
char const *fileString;
err = KIM_Collections_GetItemMetadataFile(
collections, i, &fileName, nullptr, nullptr,
&availableAsString, &fileString);
if (err) continue;
if (utils::strmatch(fileName, "^kimcite") && availableAsString)
cite_id += fileString;
}
KIM_Collections_Destroy(&collections);
return;
}
auto cite_id = fmt::format("OpenKIM potential: https://openkim.org/cite/"
"{}#item-citation\n\n",kim_id);
for (int i = 0; i < extent; ++i) {
char const *fileName;
int availableAsString;
char const *fileString;
err = KIM_Collections_GetItemMetadataFile(
collections, i, &fileName, nullptr, nullptr,
&availableAsString, &fileString);
if (err) continue;
if (utils::strmatch(fileName, "^kimcite") && availableAsString)
cite_id += fileString;
}
lmp->citeme->add(cite_id);
KIM_Collections_Destroy(&collections);
}

View File

@ -70,13 +70,13 @@ class KimInit : protected Pointers {
public:
KimInit(class LAMMPS *lmp) : Pointers(lmp) {};
void command(int, char **);
private:
enum model_type_enum {MO, SM};
static void write_log_cite(class LAMMPS *, model_type_enum, char *);
private:
model_type_enum model_type;
bool unit_conversion_mode;
void determine_model_type_and_units(char *, char *, char **, KIM_Model *&);
void write_log_cite(char *);
void do_init(char *, char *, char *, KIM_Model *&);
void do_variables(const std::string &, const std::string &);
};

View File

@ -55,6 +55,7 @@
Designed for use with the kim-api-2.0.2 (and newer) package
------------------------------------------------------------------------- */
#include "pair_kim.h"
#include "kim_init.h"
#include "atom.h"
#include "citeme.h"
@ -336,6 +337,9 @@ void PairKIM::settings(int narg, char **arg)
// initialize KIM Model
kim_init();
// add citation
KimInit::write_log_cite(lmp, KimInit::MO, kim_modelname);
}
/* ----------------------------------------------------------------------

View File

@ -356,9 +356,9 @@ void MLIAPModelNN::compute_gradients(MLIAPData* data)
delete bnodes[n];
}
delete nodes;
delete dnodes;
delete bnodes;
delete[] nodes;
delete[] dnodes;
delete[] bnodes;
}
}

View File

@ -13,19 +13,19 @@
#include "pair_snap.h"
#include <cmath>
#include <cstring>
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "error.h"
#include "force.h"
#include "memory.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "neighbor.h"
#include "sna.h"
#include "memory.h"
#include "error.h"
#include "tokenizer.h"
#include <cmath>
#include <cstring>
using namespace LAMMPS_NS;
@ -381,17 +381,8 @@ void PairSNAP::settings(int narg, char ** /* arg */)
void PairSNAP::coeff(int narg, char **arg)
{
if (narg < 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
if (nelements) {
for (int i = 0; i < nelements; i++)
delete[] elements[i];
delete[] elements;
memory->destroy(radelem);
memory->destroy(wjelem);
memory->destroy(coeffelem);
}
if (narg != 4 + atom->ntypes) error->all(FLERR,"Incorrect args for pair coefficients");
char* type1 = arg[0];
char* type2 = arg[1];
@ -404,6 +395,47 @@ void PairSNAP::coeff(int narg, char **arg)
if (strcmp(type1,"*") != 0 || strcmp(type2,"*") != 0)
error->all(FLERR,"Incorrect args for pair coefficients");
// clean out old arrays
if (elements) {
for (int i = 0; i < nelements; i++)
delete[] elements[i];
delete[] elements;
memory->destroy(radelem);
memory->destroy(wjelem);
memory->destroy(coeffelem);
}
// nelements = # of unique elements declared
// elements = list of unique element names
// allocate as ntypes >= nelements
elements = new char*[atom->ntypes];
for (int i = 0; i < atom->ntypes; i++) elements[i] = nullptr;
// read args that map atom types to SNAP elements
// map[i] = which element the Ith atom type is, -1 if not mapped
// map[0] is not used
nelements = 0;
for (int i = 1; i <= atom->ntypes; i++) {
char* elemstring = elemtypes[i-1];
if (strcmp(elemstring,"NULL") == 0) {
map[i] = -1;
continue;
}
int j;
for (j = 0; j < nelements; j++)
if (strcmp(elemstring,elements[j]) == 0) break;
map[i] = j;
if (j == nelements) {
int n = strlen(elemstring) + 1;
elements[j] = new char[n];
strcpy(elements[j],elemstring);
nelements++;
}
}
// read snapcoeff and snapparam files
read_files(coefffilename,paramfilename);
@ -423,23 +455,6 @@ void PairSNAP::coeff(int narg, char **arg)
}
}
// read args that map atom types to SNAP elements
// map[i] = which element the Ith atom type is, -1 if not mapped
// map[0] is not used
for (int i = 1; i <= atom->ntypes; i++) {
char* elemname = elemtypes[i-1];
int jelem;
for (jelem = 0; jelem < nelements; jelem++)
if (strcmp(elemname,elements[jelem]) == 0)
break;
if (jelem < nelements)
map[i] = jelem;
else if (strcmp(elemname,"NULL") == 0) map[i] = -1;
else error->all(FLERR,"Incorrect args for pair coefficients");
}
// clear setflag since coeff() called once with I,J = * *
int n = atom->ntypes;
@ -517,17 +532,13 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename)
FILE *fpcoeff;
if (comm->me == 0) {
fpcoeff = utils::open_potential(coefffilename,lmp,nullptr);
if (fpcoeff == nullptr) {
char str[128];
snprintf(str,128,"Cannot open SNAP coefficient file %s",coefffilename);
error->one(FLERR,str);
}
if (fpcoeff == nullptr)
error->one(FLERR,fmt::format("Cannot open SNAP coefficient file {}: ",
coefffilename, utils::getsyserror()));
}
char line[MAXLINE],*ptr;
int eof = 0;
int n;
int nwords = 0;
while (nwords == 0) {
if (comm->me == 0) {
@ -535,113 +546,137 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename)
if (ptr == nullptr) {
eof = 1;
fclose(fpcoeff);
} 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);
MPI_Bcast(line,MAXLINE,MPI_CHAR,0,world);
// strip comment, skip line if blank
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = utils::count_words(line);
nwords = utils::count_words(utils::trim_comment(line));
}
if (nwords != 2)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
// words = ptrs to all words in line
// strip single and double quotes from words
char* words[MAXWORD];
int iword = 0;
words[iword] = strtok(line,"' \t\n\r\f");
iword = 1;
words[iword] = strtok(nullptr,"' \t\n\r\f");
nelements = atoi(words[0]);
ncoeffall = atoi(words[1]);
int nelemtmp = 0;
try {
ValueTokenizer words(utils::trim_comment(line),"\"' \t\n\r\f");
nelemtmp = words.next_int();
ncoeffall = words.next_int();
} catch (TokenizerException &e) {
error->all(FLERR,fmt::format("Incorrect format in SNAP coefficient "
"file: {}", e.what()));
}
// set up element lists
elements = new char*[nelements];
memory->create(radelem,nelements,"pair:radelem");
memory->create(wjelem,nelements,"pair:wjelem");
memory->create(coeffelem,nelements,ncoeffall,"pair:coeffelem");
// Loop over nelements blocks in the SNAP coefficient file
// initialize checklist for all required nelements
for (int ielem = 0; ielem < nelements; ielem++) {
int elementflags[nelements];
for (int jelem = 0; jelem < nelements; jelem++)
elementflags[jelem] = 0;
// loop over nelemtmp blocks in the SNAP coefficient file
for (int ielem = 0; ielem < nelemtmp; ielem++) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fpcoeff);
if (ptr == nullptr) {
eof = 1;
fclose(fpcoeff);
} else n = strlen(line) + 1;
}
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
MPI_Bcast(line,MAXLINE,MPI_CHAR,0,world);
nwords = utils::trim_and_count_words(line);
if (nwords != 3)
std::vector<std::string> words;
try {
words = Tokenizer(utils::trim_comment(line),"\"' \t\n\r\f").as_vector();
} catch (TokenizerException &e) {
// ignore
}
if (words.size() != 3)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
iword = 0;
words[iword] = strtok(line,"' \t\n\r\f");
iword = 1;
words[iword] = strtok(nullptr,"' \t\n\r\f");
iword = 2;
words[iword] = strtok(nullptr,"' \t\n\r\f");
int jelem;
for (jelem = 0; jelem < nelements; jelem++)
if (words[0] == elements[jelem]) break;
char* elemtmp = words[0];
int n = strlen(elemtmp) + 1;
elements[ielem] = new char[n];
strcpy(elements[ielem],elemtmp);
// if this element not needed, skip this block
radelem[ielem] = atof(words[1]);
wjelem[ielem] = atof(words[2]);
if (comm->me == 0) {
if (screen) fprintf(screen,"SNAP Element = %s, Radius %g, Weight %g \n",
elements[ielem], radelem[ielem], wjelem[ielem]);
if (logfile) fprintf(logfile,"SNAP Element = %s, Radius %g, Weight %g \n",
elements[ielem], radelem[ielem], wjelem[ielem]);
if (jelem == nelements) {
if (comm->me == 0) {
for (int icoeff = 0; icoeff < ncoeffall; icoeff++) {
ptr = fgets(line,MAXLINE,fpcoeff);
if (ptr == nullptr) {
eof = 1;
fclose(fpcoeff);
}
}
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
continue;
}
if (elementflags[jelem] == 1)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
else
elementflags[jelem] = 1;
radelem[jelem] = utils::numeric(FLERR,words[1].c_str(),false,lmp);
wjelem[jelem] = utils::numeric(FLERR,words[2].c_str(),false,lmp);
if (comm->me == 0)
utils::logmesg(lmp,fmt::format("SNAP Element = {}, Radius {}, Weight {}\n",
elements[jelem], radelem[jelem], wjelem[jelem]));
for (int icoeff = 0; icoeff < ncoeffall; icoeff++) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fpcoeff);
if (ptr == nullptr) {
eof = 1;
fclose(fpcoeff);
} else n = strlen(line) + 1;
}
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
MPI_Bcast(line,MAXLINE,MPI_CHAR,0,world);
nwords = utils::trim_and_count_words(line);
if (nwords != 1)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
iword = 0;
words[iword] = strtok(line,"' \t\n\r\f");
coeffelem[ielem][icoeff] = atof(words[0]);
try {
ValueTokenizer coeff(utils::trim_comment(line));
if (coeff.count() != 1)
error->all(FLERR,"Incorrect format in SNAP coefficient file");
coeffelem[jelem][icoeff] = coeff.next_double();
} catch (TokenizerException &e) {
error->all(FLERR,fmt::format("Incorrect format in SNAP coefficient "
"file: {}", e.what()));
}
}
}
if (comm->me == 0) fclose(fpcoeff);
for (int jelem = 0; jelem < nelements; jelem++) {
if (elementflags[jelem] == 0)
error->all(FLERR,fmt::format("Element {} not found in SNAP coefficient "
"file", elements[jelem]));
}
// set flags for required keywords
rcutfacflag = 0;
@ -664,11 +699,9 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename)
FILE *fpparam;
if (comm->me == 0) {
fpparam = utils::open_potential(paramfilename,lmp,nullptr);
if (fpparam == nullptr) {
char str[128];
snprintf(str,128,"Cannot open SNAP parameter file %s",paramfilename);
error->one(FLERR,str);
}
if (fpparam == nullptr)
error->one(FLERR,fmt::format("Cannot open SNAP parameter file {}: {}",
paramfilename, utils::getsyserror()));
}
eof = 0;
@ -678,64 +711,66 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename)
if (ptr == nullptr) {
eof = 1;
fclose(fpparam);
} 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);
MPI_Bcast(line,MAXLINE,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;
if (nwords != 2)
error->all(FLERR,"Incorrect format in SNAP parameter file");
// words = ptrs to all words in line
// strip single and double quotes from words
char* keywd = strtok(line,"' \t\n\r\f");
char* keyval = strtok(nullptr,"' \t\n\r\f");
if (comm->me == 0) {
if (screen) fprintf(screen,"SNAP keyword %s %s \n",keywd,keyval);
if (logfile) fprintf(logfile,"SNAP keyword %s %s \n",keywd,keyval);
std::vector<std::string> words;
try {
words = Tokenizer(utils::trim_comment(line),"\"' \t\n\r\f").as_vector();
} catch (TokenizerException &e) {
// ignore
}
if (strcmp(keywd,"rcutfac") == 0) {
rcutfac = atof(keyval);
if (words.size() == 0) continue;
if (words.size() != 2)
error->all(FLERR,"Incorrect format in SNAP parameter file");
auto keywd = words[0];
auto keyval = words[1];
if (comm->me == 0)
utils::logmesg(lmp,fmt::format("SNAP keyword {} {}\n",keywd,keyval));
if (keywd == "rcutfac") {
rcutfac = utils::numeric(FLERR,keyval.c_str(),false,lmp);
rcutfacflag = 1;
} else if (strcmp(keywd,"twojmax") == 0) {
twojmax = atoi(keyval);
} else if (keywd == "twojmax") {
twojmax = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
twojmaxflag = 1;
} else if (strcmp(keywd,"rfac0") == 0)
rfac0 = atof(keyval);
else if (strcmp(keywd,"rmin0") == 0)
rmin0 = atof(keyval);
else if (strcmp(keywd,"switchflag") == 0)
switchflag = atoi(keyval);
else if (strcmp(keywd,"bzeroflag") == 0)
bzeroflag = atoi(keyval);
else if (strcmp(keywd,"quadraticflag") == 0)
quadraticflag = atoi(keyval);
else if (strcmp(keywd,"chemflag") == 0)
chemflag = atoi(keyval);
else if (strcmp(keywd,"bnormflag") == 0)
bnormflag = atoi(keyval);
else if (strcmp(keywd,"wselfallflag") == 0)
wselfallflag = atoi(keyval);
else if (strcmp(keywd,"chunksize") == 0)
chunksize = atoi(keyval);
} else if (keywd == "rfac0")
rfac0 = utils::numeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "rmin0")
rmin0 = utils::numeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "switchflag")
switchflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "bzeroflag")
bzeroflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "quadraticflag")
quadraticflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "chemflag")
chemflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "bnormflag")
bnormflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "wselfallflag")
wselfallflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else if (keywd == "chunksize")
chunksize = utils::inumeric(FLERR,keyval.c_str(),false,lmp);
else
error->all(FLERR,"Incorrect SNAP parameter file");
error->all(FLERR,fmt::format("Unknown parameter '{}' in SNAP "
"parameter file", keywd));
}
if (rcutfacflag == 0 || twojmaxflag == 0)
error->all(FLERR,"Incorrect SNAP parameter file");
if (chemflag && nelemtmp != nelements)
error->all(FLERR,"Incorrect SNAP parameter file");
}
/* ----------------------------------------------------------------------

View File

@ -1 +1 @@
#define LAMMPS_VERSION "10 Feb 2021"
#define LAMMPS_VERSION "10 Mar 2021"