Merge branch 'develop' into amoeba-gpu

This commit is contained in:
Trung Nguyen
2022-10-01 00:38:24 -05:00
1805 changed files with 403466 additions and 63446 deletions

View File

@ -24,6 +24,7 @@
#include "force.h"
#include "group.h"
#include "input.h"
#include "label_map.h"
#include "math_const.h"
#include "memory.h"
#include "modify.h"
@ -48,14 +49,15 @@ using namespace MathConst;
#define DELTA 1
#define EPSILON 1.0e-6
#define MAXLINE 256
/* ----------------------------------------------------------------------
one instance per AtomVec style in style_atom.h
------------------------------------------------------------------------- */
template <typename T> static AtomVec *avec_creator(LAMMPS *lmp)
template <typename T> static AtomVec *avec_creator(LAMMPS *_lmp)
{
return new T(lmp);
return new T(_lmp);
}
/* ---------------------------------------------------------------------- */
@ -85,9 +87,9 @@ are updated by the AtomVec class as needed.
* instances of classes derived from the AtomVec base
* class, which correspond to the selected atom style.
*
* \param lmp pointer to the base LAMMPS class */
* \param _lmp pointer to the base LAMMPS class */
Atom::Atom(LAMMPS *lmp) : Pointers(lmp)
Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp)
{
natoms = 0;
nlocal = nghost = nmax = 0;
@ -222,6 +224,11 @@ Atom::Atom(LAMMPS *lmp) : Pointers(lmp)
nmolecule = 0;
molecules = nullptr;
// type labels
lmap = nullptr;
types_style = NUMERIC;
// custom atom arrays
nivector = ndvector = niarray = ndarray = 0;
@ -339,6 +346,10 @@ Atom::~Atom()
for (int i = 0; i < nmolecule; i++) delete molecules[i];
memory->sfree(molecules);
// delete label map
delete lmap;
// delete per-type arrays
delete[] mass;
@ -480,7 +491,7 @@ void Atom::peratom_create()
// EFF package
add_peratom("spin",&spin,INT,0);
add_peratom("espin",&spin,INT,0);
add_peratom("eradius",&eradius,DOUBLE,0);
add_peratom("ervel",&ervel,DOUBLE,0);
add_peratom("erforce",&erforce,DOUBLE,0,1); // set per-thread flag
@ -616,6 +627,7 @@ void Atom::set_atomflag_defaults()
// 3rd customization section: customize by adding new flag
// identical list as 2nd customization in atom.h
labelmapflag = 0;
sphere_flag = ellipsoid_flag = line_flag = tri_flag = body_flag = 0;
quat_flag = 0;
peri_flag = electron_flag = 0;
@ -760,6 +772,23 @@ void Atom::setup()
if (sortfreq > 0) setup_sort_bins();
}
/* ---------------------------------------------------------------------- */
std::string Atom::get_style()
{
std::string retval = atom_style;
if (retval == "hybrid") {
auto avec_hybrid = dynamic_cast<AtomVecHybrid *>(avec);
if (avec_hybrid) {
for (int i = 0; i < avec_hybrid->nstyles; i++) {
retval += ' ';
retval += avec_hybrid->keywords[i];
}
}
}
return retval;
}
/* ----------------------------------------------------------------------
return ptr to AtomVec class if matches style or to matching hybrid sub-class
return nullptr if no match
@ -769,7 +798,7 @@ AtomVec *Atom::style_match(const char *style)
{
if (strcmp(atom_style,style) == 0) return avec;
else if (strcmp(atom_style,"hybrid") == 0) {
auto avec_hybrid = dynamic_cast<AtomVecHybrid *>( avec);
auto avec_hybrid = dynamic_cast<AtomVecHybrid *>(avec);
for (int i = 0; i < avec_hybrid->nstyles; i++)
if (strcmp(avec_hybrid->keywords[i],style) == 0)
return avec_hybrid->styles[i];
@ -1017,24 +1046,34 @@ void Atom::deallocate_topology()
------------------------------------------------------------------------- */
void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
int type_offset, int shiftflag, double *shift)
int type_offset, int shiftflag, double *shift,
int labelflag, int *ilabel)
{
int xptr,iptr;
imageint imagedata;
double xdata[3],lamda[3];
double *coord;
char *next;
std::string typestr;
auto location = "Atoms section of data file";
// use the first line to detect and validate the number of words/tokens per line
next = strchr(buf,'\n');
if (!next) error->all(FLERR, "Missing data in Atoms section of data file");
if (!next) error->all(FLERR, "Missing data in {}", location);
*next = '\0';
int nwords = utils::trim_and_count_words(buf);
*next = '\n';
auto values = Tokenizer(buf).as_vector();
int nwords = values.size();
for (std::size_t i = 0; i < values.size(); ++i) {
if (utils::strmatch(values[i], "^#")) {
nwords = i;
break;
}
}
if ((nwords != avec->size_data_atom) && (nwords != avec->size_data_atom + 3))
error->all(FLERR,"Incorrect atom format in data file: {}", utils::trim(buf));
error->all(FLERR,"Incorrect format in {}: {}", location, utils::trim(buf));
*next = '\n';
// set bounds for my proc
// if periodic and I am lo/hi proc, adjust bounds by EPSILON
// insures all data atoms will be owned even with round-off
@ -1105,13 +1144,15 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
if (!next) error->all(FLERR, "Missing data in Atoms section of data file");
if (!next) error->all(FLERR, "Missing data in {}", location);
*next = '\0';
auto values = Tokenizer(utils::trim_comment(buf)).as_vector();
if (values.size() == 0) {
auto values = Tokenizer(buf).as_vector();
int nvalues = values.size();
if ((nvalues == 0) || (utils::strmatch(values[0],"^#.*"))) {
// skip over empty or comment lines
} else if ((int)values.size() != nwords) {
error->all(FLERR, "Incorrect atom format in data file: {}", utils::trim(buf));
} else if ((nvalues < nwords) ||
((nvalues > nwords) && (!utils::strmatch(values[nwords],"^#")))) {
error->all(FLERR, "Incorrect format in {}: {}", location, utils::trim(buf));
} else {
int imx = 0, imy = 0, imz = 0;
if (imageflag) {
@ -1146,14 +1187,36 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2]) {
avec->data_atom(xdata,imagedata,values);
avec->data_atom(xdata,imagedata,values,typestr);
typestr = utils::utf8_subst(typestr);
if (id_offset) tag[nlocal-1] += id_offset;
if (mol_offset) molecule[nlocal-1] += mol_offset;
if (type_offset) {
type[nlocal-1] += type_offset;
if (type[nlocal-1] > ntypes)
error->one(FLERR,"Invalid atom type in Atoms section of data file");
switch (utils::is_type(typestr)) {
case 0: { // numeric
int itype = utils::inumeric(FLERR, typestr, true, lmp) + type_offset;
if ((itype < 1) || (itype > ntypes))
error->one(FLERR, "Invalid atom type {} in {}: {}", itype, location,
utils::trim(buf));
type[nlocal - 1] = itype;
if (labelflag) type[nlocal - 1] = ilabel[itype - 1];
break;
}
case 1: { // type label
if (!labelmapflag)
error->one(FLERR, "Invalid line in {}: {}", location, utils::trim(buf));
type[nlocal - 1] = lmap->find(typestr, Atom::ATOM);
if (type[nlocal - 1] == -1)
error->one(FLERR, "Invalid line in {}: {}", location, utils::trim(buf));
break;
}
default: // invalid
error->one(FLERR, "Invalid line in {}: {}", location, utils::trim(buf));
break;
}
if (type[nlocal-1] <= 0 || type[nlocal-1] > ntypes)
error->one(FLERR,"Invalid atom type {} in {}", location, typestr);
}
}
buf = next + 1;
@ -1202,41 +1265,64 @@ void Atom::data_vels(int n, char *buf, tagint id_offset)
------------------------------------------------------------------------- */
void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset,
int type_offset)
int type_offset, int labelflag, int *ilabel)
{
int m,itype;
tagint atom1,atom2;
char *next;
std::string typestr;
int newton_bond = force->newton_bond;
auto location = "Bonds section of data file";
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
if (!next) error->all(FLERR, "Missing data in Bonds section of data file");
if (!next) error->all(FLERR, "Missing data in {}", location);
*next = '\0';
ValueTokenizer values(utils::trim_comment(buf));
// skip over empty of comment lines
if (values.has_next()) {
try {
values.next_int();
itype = values.next_int();
atom1 = values.next_tagint();
atom2 = values.next_tagint();
if (values.has_next()) throw TokenizerException("Too many tokens","");
} catch (TokenizerException &e) {
error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf));
auto values = Tokenizer(buf).as_vector();
int nwords = values.size();
for (std::size_t ii = 0; ii < values.size(); ++ii) {
if (utils::strmatch(values[ii], "^#")) {
nwords = ii;
break;
}
}
// skip over empty or comment lines
// Bonds line is: number(ignored), bond type, atomID 1, atomID 2
if (nwords > 0) {
if (nwords != 4) error->all(FLERR, "Incorrect format in {}: {}", location, utils::trim(buf));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
if (id_offset) {
atom1 += id_offset;
atom2 += id_offset;
}
itype += type_offset;
switch (utils::is_type(typestr)) {
case 0: { // numeric
itype = utils::inumeric(FLERR, typestr, false, lmp) + type_offset;
if ((itype < 1) || (itype > nbondtypes))
error->all(FLERR, "Invalid bond type {} in {}: {}", itype, location, utils::trim(buf));
if (labelflag) itype = ilabel[itype - 1];
break;
}
case 1: { // type label
if (!atom->labelmapflag) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
itype = lmap->find(typestr, Atom::BOND);
if (itype == -1) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
default: // invalid
error->one(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
if ((atom1 <= 0) || (atom1 > map_tag_max) ||
(atom2 <= 0) || (atom2 > map_tag_max) || (atom1 == atom2))
error->one(FLERR,"Invalid atom ID in {}: {}", location, utils::trim(buf));
if (itype <= 0 || itype > nbondtypes)
error->one(FLERR,"Invalid bond type in {}: {}", location, utils::trim(buf));
error->all(FLERR,"Invalid atom ID in {}: {}", location, utils::trim(buf));
if ((itype <= 0) || (itype > nbondtypes))
error->all(FLERR,"Invalid bond type {} in {}: {}", itype, location, utils::trim(buf));
if ((m = map(atom1)) >= 0) {
if (count) count[m]++;
else {
@ -1270,37 +1356,60 @@ void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset,
------------------------------------------------------------------------- */
void Atom::data_angles(int n, char *buf, int *count, tagint id_offset,
int type_offset)
int type_offset, int labelflag, int *ilabel)
{
int m,itype;
tagint atom1,atom2,atom3;
char *next;
std::string typestr;
int newton_bond = force->newton_bond;
auto location = "Angles section of data file";
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
if (!next) error->all(FLERR, "Missing data in Angles section of data file");
if (!next) error->all(FLERR, "Missing data in {}", location);
*next = '\0';
ValueTokenizer values(utils::trim_comment(buf));
// skip over empty or comment lines
if (values.has_next()) {
try {
values.next_int();
itype = values.next_int();
atom1 = values.next_tagint();
atom2 = values.next_tagint();
atom3 = values.next_tagint();
if (values.has_next()) throw TokenizerException("Too many tokens","");
} catch (TokenizerException &e) {
error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf));
auto values = Tokenizer(buf).as_vector();
int nwords = values.size();
for (std::size_t ii = 0; ii < values.size(); ++ii) {
if (utils::strmatch(values[ii], "^#")) {
nwords = ii;
break;
}
}
// skip over empty or comment lines
// Angles line is: number(ignored), angle type, atomID 1, atomID 2, atomID 3
if (nwords > 0) {
if (nwords != 5) error->all(FLERR, "Incorrect format in {}: {}", location, utils::trim(buf));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
atom3 = utils::tnumeric(FLERR, values[4], false, lmp);
if (id_offset) {
atom1 += id_offset;
atom2 += id_offset;
atom3 += id_offset;
}
itype += type_offset;
switch (utils::is_type(typestr)) {
case 0: { // numeric
itype = utils::inumeric(FLERR, typestr, false, lmp) + type_offset;
if ((itype < 1) || (itype > nangletypes))
error->all(FLERR, "Invalid angle type {} in {}: {}", itype, location, utils::trim(buf));
if (labelflag) itype = ilabel[itype - 1];
break;
}
case 1: { // type label
if (!atom->labelmapflag) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
itype = lmap->find(typestr, Atom::ANGLE);
if (itype == -1) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
default: // invalid
error->one(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
if ((atom1 <= 0) || (atom1 > map_tag_max) ||
(atom2 <= 0) || (atom2 > map_tag_max) ||
@ -1308,7 +1417,7 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset,
(atom1 == atom2) || (atom1 == atom3) || (atom2 == atom3))
error->one(FLERR,"Invalid atom ID in {}: {}", location, utils::trim(buf));
if (itype <= 0 || itype > nangletypes)
error->one(FLERR,"Invalid angle type in {}: {}", location, utils::trim(buf));
error->one(FLERR,"Invalid angle type {} in {}: {}", itype, location, utils::trim(buf));
if ((m = map(atom2)) >= 0) {
if (count) count[m]++;
else {
@ -1354,39 +1463,63 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset,
------------------------------------------------------------------------- */
void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset,
int type_offset)
int type_offset, int labelflag, int *ilabel)
{
int m,itype;
tagint atom1,atom2,atom3,atom4;
char *next;
std::string typestr;
int newton_bond = force->newton_bond;
auto location = "Dihedrals section of data file";
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
if (!next) error->all(FLERR, "Missing data in Dihedrals section of data file");
if (!next) error->all(FLERR, "Missing data in {}", location);
*next = '\0';
ValueTokenizer values(utils::trim_comment(buf));
// skip over empty or comment lines
if (values.has_next()) {
try {
values.next_int();
itype = values.next_int();
atom1 = values.next_tagint();
atom2 = values.next_tagint();
atom3 = values.next_tagint();
atom4 = values.next_tagint();
if (values.has_next()) throw TokenizerException("Too many tokens","");
} catch (TokenizerException &e) {
error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf));
auto values = Tokenizer(buf).as_vector();
int nwords = values.size();
for (std::size_t ii = 0; ii < values.size(); ++ii) {
if (utils::strmatch(values[ii], "^#")) {
nwords = ii;
break;
}
}
// skip over empty or comment lines
// Dihedrals line is: number(ignored), bond type, atomID 1, atomID 2, atomID 3, atomID 4
if (nwords > 0) {
if (nwords != 6) error->all(FLERR, "Incorrect format in {}: {}", location, utils::trim(buf));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
atom3 = utils::tnumeric(FLERR, values[4], false, lmp);
atom4 = utils::tnumeric(FLERR, values[5], false, lmp);
if (id_offset) {
atom1 += id_offset;
atom2 += id_offset;
atom3 += id_offset;
atom4 += id_offset;
}
itype += type_offset;
switch (utils::is_type(typestr)) {
case 0: { // numeric
itype = utils::inumeric(FLERR, typestr, false, lmp) + type_offset;
if ((itype < 1) || (itype > ndihedraltypes))
error->all(FLERR, "Invalid dihedral type {} in {}: {}", itype, location,
utils::trim(buf));
if (labelflag) itype = ilabel[itype - 1];
break;
}
case 1: { // type label
if (!atom->labelmapflag) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
itype = lmap->find(typestr, Atom::DIHEDRAL);
if (itype == -1) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
default: // invalid
error->one(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
if ((atom1 <= 0) || (atom1 > map_tag_max) ||
(atom2 <= 0) || (atom2 > map_tag_max) ||
@ -1396,7 +1529,7 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset,
(atom2 == atom3) || (atom2 == atom4) || (atom3 == atom4))
error->one(FLERR, "Invalid atom ID in {}: {}", location, utils::trim(buf));
if (itype <= 0 || itype > ndihedraltypes)
error->one(FLERR, "Invalid dihedral type in {}: {}", location, utils::trim(buf));
error->one(FLERR, "Invalid dihedral type {} in {}: {}", itype, location, utils::trim(buf));
if ((m = map(atom2)) >= 0) {
if (count) count[m]++;
else {
@ -1456,39 +1589,63 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset,
------------------------------------------------------------------------- */
void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset,
int type_offset)
int type_offset, int labelflag, int *ilabel)
{
int m,itype;
tagint atom1,atom2,atom3,atom4;
char *next;
std::string typestr;
int newton_bond = force->newton_bond;
auto location = "Impropers section of data file";
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
if (!next) error->all(FLERR, "Missing data in Impropers section of data file");
if (!next) error->all(FLERR, "Missing data in {}", location);
*next = '\0';
ValueTokenizer values(utils::trim_comment(buf));
// skip over empty or comment lines
if (values.has_next()) {
try {
values.next_int();
itype = values.next_int();
atom1 = values.next_tagint();
atom2 = values.next_tagint();
atom3 = values.next_tagint();
atom4 = values.next_tagint();
if (values.has_next()) throw TokenizerException("Too many tokens","");
} catch (TokenizerException &e) {
error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf));
auto values = Tokenizer(buf).as_vector();
int nwords = values.size();
for (std::size_t ii = 0; ii < values.size(); ++ii) {
if (utils::strmatch(values[ii], "^#")) {
nwords = ii;
break;
}
}
// skip over empty or comment lines
// Impropers line is: number(ignored), bond type, atomID 1, atomID 2, atomID 3, atomID 4
if (nwords > 0) {
if (nwords != 6) error->all(FLERR, "Incorrect format in {}: {}", location, utils::trim(buf));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
atom3 = utils::tnumeric(FLERR, values[4], false, lmp);
atom4 = utils::tnumeric(FLERR, values[5], false, lmp);
if (id_offset) {
atom1 += id_offset;
atom2 += id_offset;
atom3 += id_offset;
atom4 += id_offset;
}
itype += type_offset;
switch (utils::is_type(typestr)) {
case 0: { // numeric
itype = utils::inumeric(FLERR, typestr, false, lmp) + type_offset;
if ((itype < 1) || (itype > nimpropertypes))
error->all(FLERR, "Invalid improper type {} in {}: {}", itype, location,
utils::trim(buf));
if (labelflag) itype = ilabel[itype - 1];
break;
}
case 1: { // type label
if (!atom->labelmapflag) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
itype = lmap->find(typestr, Atom::IMPROPER);
if (itype == -1) error->all(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
default: // invalid
error->one(FLERR, "Invalid {}: {}", location, utils::trim(buf));
break;
}
if ((atom1 <= 0) || (atom1 > map_tag_max) ||
(atom2 <= 0) || (atom2 > map_tag_max) ||
@ -1498,7 +1655,7 @@ void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset,
(atom2 == atom3) || (atom2 == atom4) || (atom3 == atom4))
error->one(FLERR, "Invalid atom ID in {}: {}", location, utils::trim(buf));
if (itype <= 0 || itype > nimpropertypes)
error->one(FLERR, "Invalid improper type in {}: {}", location, utils::trim(buf));
error->one(FLERR, "Invalid improper type {} in {}: {}", itype, location, utils::trim(buf));
if ((m = map(atom2)) >= 0) {
if (count) count[m]++;
else {
@ -1702,30 +1859,64 @@ void Atom::allocate_type_arrays()
called from reading of data file
type_offset may be used when reading multiple data files
------------------------------------------------------------------------- */
// clang-format on
void Atom::set_mass(const char *file, int line, const char *str, int type_offset)
void Atom::set_mass(const char *file, int line, const char *str, int type_offset, int labelflag,
int *ilabel)
{
if (mass == nullptr) error->all(file,line,"Cannot set mass for atom style {}", atom_style);
if (mass == nullptr) error->all(file, line, "Cannot set mass for atom style {}", atom_style);
int itype;
double mass_one;
ValueTokenizer values(utils::trim_comment(str));
if (values.has_next()) {
try {
itype = values.next_int() + type_offset;
mass_one = values.next_double();
if (values.has_next()) throw TokenizerException("Too many tokens", "");
auto location = "Masses section of data file";
auto values = Tokenizer(str).as_vector();
int nwords = values.size();
for (std::size_t i = 0; i < values.size(); ++i) {
if (utils::strmatch(values[i], "^#")) {
nwords = i;
break;
}
}
if (nwords != 2) error->all(file, line, "Invalid format in {}: {}", location, str);
auto typestr = utils::utf8_subst(values[0]);
if (itype < 1 || itype > ntypes) throw TokenizerException("Invalid atom type", "");
if (mass_one <= 0.0) throw TokenizerException("Invalid mass value", "");
} catch (TokenizerException &e) {
error->all(file,line,"{} in Masses section of data file: {}", e.what(), utils::trim(str));
switch (utils::is_type(typestr)) {
case 0: { // numeric
itype = utils::inumeric(file, line, typestr, false, lmp);
if ((itype < 1) || (itype > ntypes))
error->all(file, line, "Invalid atom type {} in {}: {}", itype, location, utils::trim(str));
if (labelflag) itype = ilabel[itype - 1];
break;
}
mass[itype] = mass_one;
mass_setflag[itype] = 1;
case 1: { // type label
if (!atom->labelmapflag)
error->all(file, line, "Invalid atom type in {}: {}", location, utils::trim(str));
itype = lmap->find(typestr, Atom::ATOM);
if (itype == -1)
error->all(file, line, "Unknown atom type {} in {}: {}", typestr, location,
utils::trim(str));
break;
}
default: // invalid
itype = -1000000000;
error->one(file, line, "Invalid {}: {}", location, utils::trim(str));
break;
}
itype += type_offset;
mass_one = utils::numeric(file, line, values[1], false, lmp);
if (itype < 1 || itype > ntypes)
error->all(file, line, "Invalid atom type {} in {}: {}", itype, location, utils::trim(str));
if (mass_one <= 0.0)
error->all(file, line, "Invalid mass value {} in {}: {}", mass_one, location, utils::trim(str));
mass[itype] = mass_one;
mass_setflag[itype] = 1;
}
// clang-format off
/* ----------------------------------------------------------------------
set a mass and flag it as set
@ -1750,15 +1941,20 @@ void Atom::set_mass(const char *file, int line, int itype, double value)
void Atom::set_mass(const char *file, int line, int /*narg*/, char **arg)
{
if (mass == nullptr) error->all(file,line, "Cannot set atom mass for atom style {}", atom_style);
if (mass == nullptr)
error->all(file,line, "Cannot set per-type atom mass for atom style {}", atom_style);
int lo,hi;
utils::bounds(file,line,arg[0],1,ntypes,lo,hi,error);
char *typestr = utils::expand_type(file, line, arg[0], Atom::ATOM, lmp);
if (typestr) arg[0] = typestr;
int lo, hi;
utils::bounds(file, line, arg[0], 1, ntypes, lo, hi, error);
if ((lo < 1) || (hi > ntypes))
error->all(file,line,"Invalid type {} for atom mass {}", arg[1]);
error->all(file, line, "Invalid atom type {} for atom mass", arg[0]);
const double value = utils::numeric(FLERR,arg[1],false,lmp);
if (value <= 0.0) error->all(file,line,"Invalid atom mass value {}", value);
const double value = utils::numeric(FLERR, arg[1], false, lmp);
if (value <= 0.0)
error->all(file, line, "Invalid atom mass value {} for type {}", value, arg[0]);
for (int itype = lo; itype <= hi; itype++) {
mass[itype] = value;
@ -1828,7 +2024,7 @@ int Atom::shape_consistency(int itype, double &shapex, double &shapey, double &s
double one[3] = {-1.0, -1.0, -1.0};
double *shape;
auto avec_ellipsoid = dynamic_cast<AtomVecEllipsoid *>( style_match("ellipsoid"));
auto avec_ellipsoid = dynamic_cast<AtomVecEllipsoid *>(style_match("ellipsoid"));
auto bonus = avec_ellipsoid->bonus;
int flag = 0;
@ -1891,15 +2087,26 @@ void Atom::add_molecule(int narg, char **arg)
return -1 if does not exist
------------------------------------------------------------------------- */
int Atom::find_molecule(char *id)
int Atom::find_molecule(const char *id)
{
if (id == nullptr) return -1;
int imol;
for (imol = 0; imol < nmolecule; imol++)
for (int imol = 0; imol < nmolecule; imol++)
if (strcmp(id,molecules[imol]->id) == 0) return imol;
return -1;
}
/* ----------------------------------------------------------------------
return vector of molecules which match template ID
------------------------------------------------------------------------- */
std::vector<Molecule *>Atom::get_molecule_by_id(const std::string &id)
{
std::vector<Molecule *> result;
for (int imol = 0; imol < nmolecule; ++imol)
if (id == molecules[imol]->id) result.push_back(molecules[imol]);
return result;
}
/* ----------------------------------------------------------------------
add info to current atom ilocal from molecule template onemol and its iatom
offset = atom ID preceding IDs of atoms in this molecule
@ -1912,8 +2119,7 @@ void Atom::add_molecule_atom(Molecule *onemol, int iatom, int ilocal, tagint off
if (onemol->radiusflag && radius_flag) radius[ilocal] = onemol->radius[iatom];
if (onemol->rmassflag && rmass_flag) rmass[ilocal] = onemol->rmass[iatom];
else if (rmass_flag)
rmass[ilocal] = 4.0*MY_PI/3.0 *
radius[ilocal]*radius[ilocal]*radius[ilocal];
rmass[ilocal] = 4.0*MY_PI/3.0 * radius[ilocal]*radius[ilocal]*radius[ilocal];
if (onemol->bodyflag) {
body[ilocal] = 0; // as if a body read from data file
onemol->avec_body->data_body(ilocal,onemol->nibody,onemol->ndbody,
@ -1923,10 +2129,8 @@ void Atom::add_molecule_atom(Molecule *onemol, int iatom, int ilocal, tagint off
// initialize custom per-atom properties to zero if present
for (int i = 0; i < nivector; ++i)
ivector[i][ilocal] = 0;
for (int i = 0; i < ndvector; ++i)
dvector[i][ilocal] = 0.0;
for (int i = 0; i < nivector; ++i) ivector[i][ilocal] = 0;
for (int i = 0; i < ndvector; ++i) dvector[i][ilocal] = 0.0;
for (int i = 0; i < niarray; ++i)
for (int j = 0; j < icols[i]; ++j)
iarray[i][ilocal][j] = 0;
@ -1988,6 +2192,18 @@ void Atom::add_molecule_atom(Molecule *onemol, int iatom, int ilocal, tagint off
}
}
/* ----------------------------------------------------------------------
allocate space for type label map
------------------------------------------------------------------------- */
void Atom::add_label_map()
{
if (lmp->kokkos)
error->all(FLERR, "Label maps are currently not supported with Kokkos");
labelmapflag = 1;
lmap = new LabelMap(lmp,ntypes,nbondtypes,nangletypes,ndihedraltypes,nimpropertypes);
}
/* ----------------------------------------------------------------------
reorder owned atoms so those in firstgroup appear first
called by comm->exchange() if atom_modify first group is set
@ -2686,11 +2902,20 @@ void *Atom::extract(const char *name)
if (strcmp(name,"body") == 0) return (void *) body;
if (strcmp(name,"quat") == 0) return (void *) quat;
// PERI PACKAGE
if (strcmp(name,"vfrac") == 0) return (void *) vfrac;
if (strcmp(name,"s0") == 0) return (void *) s0;
if (strcmp(name,"x0") == 0) return (void *) x0;
if (strcmp(name,"spin") == 0) return (void *) spin;
// SPIN PACKAGE
if (strcmp(name,"sp") == 0) return (void *) sp;
// EFF and AWPMD packages
if (strcmp(name,"espin") == 0) return (void *) spin;
if (strcmp(name,"spin") == 0) return (void *) spin; // backward compatibility
if (strcmp(name,"eradius") == 0) return (void *) eradius;
if (strcmp(name,"ervel") == 0) return (void *) ervel;
if (strcmp(name,"erforce") == 0) return (void *) erforce;
@ -2700,6 +2925,7 @@ void *Atom::extract(const char *name)
if (strcmp(name,"vforce") == 0) return (void *) vforce;
if (strcmp(name,"etag") == 0) return (void *) etag;
// SPH package
if (strcmp(name,"rho") == 0) return (void *) rho;
if (strcmp(name,"drho") == 0) return (void *) drho;
if (strcmp(name,"esph") == 0) return (void *) esph;
@ -2813,7 +3039,8 @@ int Atom::extract_datatype(const char *name)
if (strcmp(name,"s0") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"x0") == 0) return LAMMPS_DOUBLE_2D;
if (strcmp(name,"spin") == 0) return LAMMPS_INT;
if (strcmp(name,"espin") == 0) return LAMMPS_INT;
if (strcmp(name,"spin") == 0) return LAMMPS_INT; // backwards compatibility
if (strcmp(name,"eradius") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"ervel") == 0) return LAMMPS_DOUBLE;
if (strcmp(name,"erforce") == 0) return LAMMPS_DOUBLE;