Merge conflicts

This commit is contained in:
jtclemm
2024-06-24 14:09:33 -06:00
2229 changed files with 152287 additions and 82970 deletions

View File

@ -48,9 +48,9 @@
using namespace LAMMPS_NS;
using namespace MathConst;
#define DELTA 1
#define EPSILON 1.0e-6
#define MAXLINE 256
static constexpr int DELTA = 1;
static constexpr double EPSILON = 1.0e-6;
static constexpr double EPS_ZCOORD = 1.0e-12;
/* ----------------------------------------------------------------------
one instance per AtomVec style in style_atom.h
@ -242,6 +242,7 @@ Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp), atom_style(nullptr), avec(nullptr), a
darray = nullptr;
icols = dcols = nullptr;
ivname = dvname = ianame = daname = nullptr;
ivghost = dvghost = iaghost = daghost = nullptr;
// initialize atom style and array existence flags
@ -341,6 +342,10 @@ Atom::~Atom()
memory->sfree(darray);
memory->sfree(icols);
memory->sfree(dcols);
memory->destroy(ivghost);
memory->destroy(dvghost);
memory->destroy(iaghost);
memory->destroy(daghost);
// delete user-defined molecules
@ -633,7 +638,7 @@ void Atom::set_atomflag_defaults()
// identical list as 2nd customization in atom.h
labelmapflag = 0;
sphere_flag = ellipsoid_flag = line_flag = tri_flag = body_flag = 0;
ellipsoid_flag = line_flag = tri_flag = body_flag = 0;
quat_flag = 0;
peri_flag = electron_flag = 0;
wavepacket_flag = sph_flag = 0;
@ -1050,12 +1055,13 @@ void Atom::deallocate_topology()
/* ----------------------------------------------------------------------
unpack N lines from Atom section of data file
call style-specific routine to parse line
call atom-style specific method to parse each line
triclinic_general = 1 if data file defines a general triclinic box
------------------------------------------------------------------------- */
void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
int type_offset, int shiftflag, double *shift,
int labelflag, int *ilabel)
int labelflag, int *ilabel, int triclinic_general)
{
int xptr,iptr;
imageint imagedata;
@ -1066,6 +1072,7 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
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 {}", location);
*next = '\0';
@ -1079,13 +1086,16 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
}
if ((nwords != avec->size_data_atom) && (nwords != avec->size_data_atom + 3))
error->all(FLERR,"Incorrect format in {}: {}", location, utils::trim(buf));
error->all(FLERR,"Incorrect format in {}: {}{}", location,
utils::trim(buf), utils::errorurl(2));
*next = '\n';
// set bounds for my proc
// if periodic and I am lo/hi proc, adjust bounds by EPSILON
// ensures all data atoms will be owned even with round-off
int dimension = domain->dimension;
int triclinic = domain->triclinic;
double epsilon[3];
@ -1156,18 +1166,27 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
*next = '\0';
auto values = Tokenizer(buf).as_vector();
int nvalues = values.size();
if ((nvalues == 0) || (utils::strmatch(values[0],"^#.*"))) {
// skip over empty or comment lines
// skip comment lines
if ((nvalues == 0) || (utils::strmatch(values[0],"^#.*"))) {
// check that line has correct # of words
} else if ((nvalues < nwords) ||
((nvalues > nwords) && (!utils::strmatch(values[nwords],"^#")))) {
error->all(FLERR, "Incorrect format in {}: {}", location, utils::trim(buf));
error->all(FLERR, "Incorrect format in {}: {}{}", location,
utils::trim(buf), utils::errorurl(2));
// extract the atom coords and image flags (if they exist)
} else {
int imx = 0, imy = 0, imz = 0;
if (imageflag) {
imx = utils::inumeric(FLERR,values[iptr],false,lmp);
imy = utils::inumeric(FLERR,values[iptr+1],false,lmp);
imz = utils::inumeric(FLERR,values[iptr+2],false,lmp);
if ((domain->dimension == 2) && (imz != 0))
if ((dimension == 2) && (imz != 0))
error->all(FLERR,"Z-direction image flag must be 0 for 2d-systems");
if ((!domain->xperiodic) && (imx != 0)) { reset_image_flag[0] = true; imx = 0; }
if ((!domain->yperiodic) && (imy != 0)) { reset_image_flag[1] = true; imy = 0; }
@ -1180,13 +1199,35 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
xdata[0] = utils::numeric(FLERR,values[xptr],false,lmp);
xdata[1] = utils::numeric(FLERR,values[xptr+1],false,lmp);
xdata[2] = utils::numeric(FLERR,values[xptr+2],false,lmp);
// for 2d simulation:
// check if z coord is within EPS_ZCOORD of zero and set to zero
if (dimension == 2) {
if (fabs(xdata[2]) > EPS_ZCOORD)
error->all(FLERR,"Read_data atom z coord is non-zero for 2d simulation");
xdata[2] = 0.0;
}
// convert atom coords from general to restricted triclinic
// so can decide which proc owns the atom
if (triclinic_general) domain->general_to_restricted_coords(xdata);
// apply shift if requested by read_data command
if (shiftflag) {
xdata[0] += shift[0];
xdata[1] += shift[1];
xdata[2] += shift[2];
}
// map atom into simulation box for periodic dimensions
domain->remap(xdata,imagedata);
// determine if this proc owns the atom
if (triclinic) {
domain->x2lamda(xdata,lamda);
coord = lamda;
@ -1195,6 +1236,9 @@ 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]) {
// atom-style specific method parses single line
avec->data_atom(xdata,imagedata,values,typestr);
typestr = utils::utf8_subst(typestr);
if (id_offset) tag[nlocal-1] += id_offset;
@ -1234,8 +1278,8 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
/* ----------------------------------------------------------------------
unpack N lines from Velocity section of data file
check that atom IDs are > 0 and <= map_tag_max
call style-specific routine to parse line
------------------------------------------------------------------------- */
call style-specific routine to parse line-
------------------------------------------------------------------------ */
void Atom::data_vels(int n, char *buf, tagint id_offset)
{
@ -1254,7 +1298,8 @@ void Atom::data_vels(int n, char *buf, tagint id_offset)
if (values.size() == 0) {
// skip over empty or comment lines
} else if ((int)values.size() != avec->size_data_vel) {
error->all(FLERR, "Incorrect velocity format in data file: {}", utils::trim(buf));
error->all(FLERR, "Incorrect format in Velocities section of data file: {}{}",
utils::trim(buf), utils::errorurl(2));
} else {
tagint tagdata = utils::tnumeric(FLERR,values[0],false,lmp) + id_offset;
if (tagdata <= 0 || tagdata > map_tag_max)
@ -1298,7 +1343,9 @@ void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset,
// 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));
if (nwords != 4)
error->all(FLERR, "Incorrect format in {}: {}{}", location,
utils::trim(buf), utils::errorurl(2));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
@ -1389,7 +1436,9 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset,
// 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));
if (nwords != 5)
error->all(FLERR, "Incorrect format in {}: {}{}", location,
utils::trim(buf), utils::errorurl(2));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
@ -1496,7 +1545,9 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset,
// 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));
if (nwords != 6)
error->all(FLERR, "Incorrect format in {}: {}{}", location,
utils::trim(buf), utils::errorurl(2));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
@ -1622,7 +1673,9 @@ void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset,
// 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));
if (nwords != 6)
error->all(FLERR, "Incorrect format in {}: {}{}", location,
utils::trim(buf), utils::errorurl(2));
typestr = utils::utf8_subst(values[1]);
atom1 = utils::tnumeric(FLERR, values[2], false, lmp);
atom2 = utils::tnumeric(FLERR, values[3], false, lmp);
@ -1738,7 +1791,8 @@ void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus, tagint id_offset)
if (values.size() == 0) {
// skip over empty or comment lines
} else if ((int)values.size() != avec_bonus->size_data_bonus) {
error->all(FLERR, "Incorrect bonus data format in data file: {}", utils::trim(buf));
error->all(FLERR, "Incorrect format in Bonus section of data file: {}{}",
utils::trim(buf), utils::errorurl(2));
} else {
tagint tagdata = utils::tnumeric(FLERR,values[0],false,lmp) + id_offset;
if (tagdata <= 0 || tagdata > map_tag_max)
@ -1955,18 +2009,14 @@ void Atom::set_mass(const char *file, int line, int /*narg*/, char **arg)
if (mass == nullptr)
error->all(file,line, "Cannot set per-type atom mass for atom style {}", atom_style);
char *typestr = utils::expand_type(file, line, arg[0], Atom::ATOM, lmp);
const std::string str = typestr ? typestr : arg[0];
delete[] typestr;
int lo, hi;
utils::bounds(file, line, str, 1, ntypes, lo, hi, error);
utils::bounds_typelabel(file, line, arg[0], 1, ntypes, lo, hi, error, lmp, Atom::ATOM);
if ((lo < 1) || (hi > ntypes))
error->all(file, line, "Invalid atom type {} for atom mass", str);
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 {} for type {}", value, str);
error->all(file, line, "Invalid atom mass value {} for type {}", value, arg[0]);
for (int itype = lo; itype <= hi; itype++) {
mass[itype] = value;
@ -2624,6 +2674,18 @@ void Atom::update_callback(int ifix)
if (extra_border[i] > ifix) extra_border[i]--;
}
/** \brief Find a custom per-atom property with given name
\verbatim embed:rst
This function returns the list index of a custom per-atom property
with the name "name", also returning by reference its data type and
number of values per atom.
\endverbatim
* \param name Name of the property (w/o a "i_" or "d_" or "i2_" or "d2_" prefix)
* \param &flag Returns data type of property: 0 for int, 1 for double
* \param &cols Returns number of values: 0 for a single value, 1 or more for a vector of values
* \return index of property in the respective list of properties
*/
/* ----------------------------------------------------------------------
find custom per-atom vector with name
return index if found, -1 if not found
@ -2667,6 +2729,33 @@ int Atom::find_custom(const char *name, int &flag, int &cols)
return -1;
}
/** \brief Find a custom per-atom property with given name and retrieve ghost property
\verbatim embed:rst
This function returns the list index of a custom per-atom property
with the name "name", also returning by reference its data type,
number of values per atom, and if it is communicated to ghost particles.
Classes rarely need to check on ghost communication and so `find_custom`
is typically preferred to this function. See :doc:`pair amoeba <pair_amoeba>`
for an example where checking ghost communication is necessary.
\endverbatim
* \param name Name of the property (w/o a "i_" or "d_" or "i2_" or "d2_" prefix)
* \param &flag Returns data type of property: 0 for int, 1 for double
* \param &cols Returns number of values: 0 for a single value, 1 or more for a vector of values
* \param &ghost Returns whether property is communicated to ghost atoms: 0 for no, 1 for yes
* \return index of property in the respective list of properties
*/
int Atom::find_custom_ghost(const char *name, int &flag, int &cols, int &ghost)
{
int i = find_custom(name, flag, cols);
if (i == -1) return i;
if ((flag == 0) && (cols == 0)) ghost = ivghost[i];
else if ((flag == 1) && (cols == 0)) ghost = dvghost[i];
else if ((flag == 0) && (cols == 1)) ghost = iaghost[i];
else if ((flag == 1) && (cols == 1)) ghost = daghost[i];
return i;
}
/** \brief Add a custom per-atom property with the given name and type and size
\verbatim embed:rst
@ -2677,9 +2766,10 @@ This function is called, e.g. from :doc:`fix property/atom <fix_property_atom>`.
* \param name Name of the property (w/o a "i_" or "d_" or "i2_" or "d2_" prefix)
* \param flag Data type of property: 0 for int, 1 for double
* \param cols Number of values: 0 for a single value, 1 or more for a vector of values
* \param ghost Whether property is communicated to ghost atoms: 0 for no, 1 for yes
* \return index of property in the respective list of properties
*/
int Atom::add_custom(const char *name, int flag, int cols)
int Atom::add_custom(const char *name, int flag, int cols, int ghost)
{
int index = -1;
@ -2688,6 +2778,8 @@ int Atom::add_custom(const char *name, int flag, int cols)
nivector++;
ivname = (char **) memory->srealloc(ivname,nivector*sizeof(char *),"atom:ivname");
ivname[index] = utils::strdup(name);
ivghost = (int *) memory->srealloc(ivghost,nivector*sizeof(int),"atom:ivghost");
ivghost[index] = ghost;
ivector = (int **) memory->srealloc(ivector,nivector*sizeof(int *),"atom:ivector");
memory->create(ivector[index],nmax,"atom:ivector");
@ -2696,6 +2788,8 @@ int Atom::add_custom(const char *name, int flag, int cols)
ndvector++;
dvname = (char **) memory->srealloc(dvname,ndvector*sizeof(char *),"atom:dvname");
dvname[index] = utils::strdup(name);
dvghost = (int *) memory->srealloc(dvghost,ndvector*sizeof(int),"atom:dvghost");
dvghost[index] = ghost;
dvector = (double **) memory->srealloc(dvector,ndvector*sizeof(double *),"atom:dvector");
memory->create(dvector[index],nmax,"atom:dvector");
@ -2704,6 +2798,8 @@ int Atom::add_custom(const char *name, int flag, int cols)
niarray++;
ianame = (char **) memory->srealloc(ianame,niarray*sizeof(char *),"atom:ianame");
ianame[index] = utils::strdup(name);
iaghost = (int *) memory->srealloc(iaghost,niarray*sizeof(int),"atom:iaghost");
iaghost[index] = ghost;
iarray = (int ***) memory->srealloc(iarray,niarray*sizeof(int **),"atom:iarray");
memory->create(iarray[index],nmax,cols,"atom:iarray");
icols = (int *) memory->srealloc(icols,niarray*sizeof(int),"atom:icols");
@ -2714,6 +2810,8 @@ int Atom::add_custom(const char *name, int flag, int cols)
ndarray++;
daname = (char **) memory->srealloc(daname,ndarray*sizeof(char *),"atom:daname");
daname[index] = utils::strdup(name);
daghost = (int *) memory->srealloc(daghost,ndarray*sizeof(int),"atom:daghost");
daghost[index] = ghost;
darray = (double ***) memory->srealloc(darray,ndarray*sizeof(double **),"atom:darray");
memory->create(darray[index],nmax,cols,"atom:darray");
dcols = (int *) memory->srealloc(dcols,ndarray*sizeof(int),"atom:dcols");
@ -2722,6 +2820,7 @@ int Atom::add_custom(const char *name, int flag, int cols)
if (index < 0)
error->all(FLERR,"Invalid call to Atom::add_custom()");
return index;
}