Merge pull request #3698 from yafshar/set-command-type-label

use of type labels in set commands
This commit is contained in:
Axel Kohlmeyer
2023-03-28 16:07:14 -04:00
committed by GitHub
4 changed files with 144 additions and 40 deletions

View File

@ -11,7 +11,16 @@ Syntax
set style ID keyword values ...
* style = *atom* or *type* or *mol* or *group* or *region*
* ID = atom ID range or type range or mol ID range or group ID or region ID
* ID = depends on style
.. parsed-literal::
for style = *atom*, ID = a range of atom IDs
for style = *type*, ID = a range of numeric types or a single type label
for style = *mol*, ID = a range of molecule IDs
for style = *group*, ID = a group ID
for style = *region*, ID = a region ID
* one or more keyword/value pairs may be appended
* keyword = *type* or *type/fraction* or *type/ratio* or *type/subset*
or *mol* or *x* or *y* or *z* or *vx* or *vy* or *vz* or *charge* or
@ -28,22 +37,22 @@ Syntax
.. parsed-literal::
*type* value = atom type
*type* value = numeric atom type or type label
value can be an atom-style variable (see below)
*type/fraction* values = type fraction seed
type = new atom type
type = numeric atom type or type label
fraction = approximate fraction of selected atoms to set to new atom type
seed = random # seed (positive integer)
*type/ratio* values = type fraction seed
type = new atom type
type = numeric atom type or type label
fraction = exact fraction of selected atoms to set to new atom type
seed = random # seed (positive integer)
*type/subset* values = type Nsubset seed
type = new atom type
type = numeric atom type or type label
Nsubset = exact number of selected atoms to set to new atom type
seed = random # seed (positive integer)
*mol* value = molecule ID
value can be an atom-style variable (see below)
value can be an atom-style variable (see below)
*x*,\ *y*,\ *z* value = atom coordinate (distance units)
value can be an atom-style variable (see below)
*vx*,\ *vy*,\ *vz* value = atom velocity (velocity units)
@ -107,10 +116,10 @@ Syntax
*image* nx ny nz
nx,ny,nz = which periodic image of the simulation box the atom is in
any of nx,ny,nz can be an atom-style variable (see below)
*bond* value = bond type for all bonds between selected atoms
*angle* value = angle type for all angles between selected atoms
*dihedral* value = dihedral type for all dihedrals between selected atoms
*improper* value = improper type for all impropers between selected atoms
*bond* value = numeric bond type or bond type label, for all bonds between selected atoms
*angle* value = numeric angle type or angle type label, for all angles between selected atoms
*dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms
*improper* value = numeric improper type or improper type label, for all impropers between selected atoms
*sph/e* value = energy of SPH particles (need units)
value can be an atom-style variable (see below)
*sph/cv* value = heat capacity of SPH particles (need units)
@ -145,15 +154,19 @@ Examples
.. code-block:: LAMMPS
set group solvent type 2
set group solvent type C
set group solvent type/fraction 2 0.5 12393
set group solvent type/fraction C 0.5 12393
set group edge bond 4
set region half charge 0.5
set type 3 charge 0.5
set type H charge 0.5
set type 1*3 charge 0.5
set atom * charge v_atomfile
set atom 100*200 x 0.5 y 1.0
set atom 100 vx 0.0 vy 0.0 vz -1.0
set atom 1492 type 3
set atom 1492 type H
set atom * i_myVal 5
set atom * d2_Sxyz[1] 6.4
@ -183,9 +196,17 @@ properties to reset and what the new values are. Some strings like
This section describes how to select which atoms to change
the properties of, via the *style* and *ID* arguments.
The style *atom* selects all the atoms in a range of atom IDs. The
style *type* selects all the atoms in a range of types. The style
*mol* selects all the atoms in a range of molecule IDs.
.. versionchanged:: 28Mar2023
Support for type labels was added for selecting atoms by type
The style *atom* selects all the atoms in a range of atom IDs.
The style *type* selects all the atoms in a range of types or type
labels. The style *type* selects atoms in one of two ways. A range
of numeric atom types can be specified. Or a single atom type label
can be specified, e.g. "C". The style *mol* selects all the atoms in
a range of molecule IDs.
In each of the range cases, the range can be specified as a single
numeric value, or a wildcard asterisk can be used to specify a range
@ -237,14 +258,23 @@ from a file.
such as the molecule ID, then the floating point value is truncated to
its integer portion, e.g. a value of 2.6 would become 2.
Keyword *type* sets the atom type for all selected atoms. The
specified value must be from 1 to ntypes, where ntypes was set by the
:doc:`create_box <create_box>` command or the *atom types* field in the
header of the data file read by the :doc:`read_data <read_data>`
command.
.. versionchanged:: 28Mar2023
Keyword *type/fraction* sets the atom type for a fraction of the
selected atoms. The actual number of atoms changed is not guaranteed
Support for type labels was added for setting atom, bond, angle,
dihedral, and improper types
Keyword *type* sets the atom type for all selected atoms. A specified
value can be either a numeric atom type or an atom type label. When
using a numeric type, the specified value must be from 1 to ntypes,
where ntypes was set by the :doc:`create_box <create_box>` command or
the *atom types* field in the header of the data file read by the
:doc:`read_data <read_data>` command. When using a type label it must
have been defined previously. See the :doc:`Howto type labels
<Howto_type_labels>` doc page for the allowed syntax of type labels
and a general discussion of how type labels can be used.
Keyword *type/fraction* sets the atom type for a fraction of the selected
atoms. The actual number of atoms changed is not guaranteed
to be exactly the specified fraction (0 <= *fraction* <= 1), but
should be statistically close. Random numbers are used in such a way
that a particular atom is changed or not changed, regardless of how
@ -463,14 +493,18 @@ simulation, but may mess up analysis of the trajectories if a LAMMPS
diagnostic or your own analysis relies on the image flags to unwrap a
molecule which straddles the periodic box.
Keywords *bond*, *angle*, *dihedral*, and *improper*, set the bond type
(angle type, etc) of all bonds (angles, etc) of selected atoms to the
specified value from 1 to nbondtypes (nangletypes, etc). All atoms in a
particular bond (angle, etc) must be selected atoms in order for the
change to be made. The value of nbondtype (nangletypes, etc) was set by
the *bond types* (\ *angle types*, etc) field in the header of the data
file read by the :doc:`read_data <read_data>` command. These keywords
do not allow use of an atom-style variable.
Keywords *bond*, *angle*, *dihedral*, and *improper*, set the bond
type (angle type, etc) of all bonds (angles, etc) of selected atoms to
the specified value. The value can be a numeric type from 1 to
nbondtypes (nangletypes, etc). Or it can be a type label (bond type
label, angle type lable, etc). See the :doc:`Howto type labels
<Howto_type_labels>` doc page for the allowed syntax of type labels
and a general discussion of how type labels can be used. All atoms in
a particular bond (angle, etc) must be selected atoms in order for the
change to be made. The value of nbondtypes (nangletypes, etc) was set
by the *bond types* (\ *angle types*, etc) field in the header of the
data file read by the :doc:`read_data <read_data>` command. These
keywords do not allow use of an atom-style variable.
Keywords *sph/e*, *sph/cv*, and *sph/rho* set the energy, heat capacity,
and density of smoothed particle hydrodynamics (SPH) particles. See

View File

@ -1944,16 +1944,17 @@ void Atom::set_mass(const char *file, int line, int /*narg*/, char **arg)
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);
if (typestr) arg[0] = typestr;
const std::string str = typestr ? typestr : arg[0];
delete[] typestr;
int lo, hi;
utils::bounds(file, line, arg[0], 1, ntypes, lo, hi, error);
utils::bounds(file, line, str, 1, ntypes, lo, hi, error);
if ((lo < 1) || (hi > ntypes))
error->all(file, line, "Invalid atom type {} for atom mass", arg[0]);
error->all(file, line, "Invalid atom type {} for atom mass", str);
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]);
error->all(file, line, "Invalid atom mass value {} for type {}", value, str);
for (int itype = lo; itype <= hi; itype++) {
mass[itype] = value;

View File

@ -93,13 +93,19 @@ void Set::command(int narg, char **arg)
if (strcmp(arg[iarg],"type") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set type", error);
if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1);
else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
else {
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp);
ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
}
set(TYPE);
iarg += 2;
} else if (strcmp(arg[iarg],"type/fraction") == 0) {
if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error);
newtype = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp);
newtype = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
fraction = utils::numeric(FLERR,arg[iarg+2],false,lmp);
ivalue = utils::inumeric(FLERR,arg[iarg+3],false,lmp);
if (newtype <= 0 || newtype > atom->ntypes)
@ -113,7 +119,9 @@ void Set::command(int narg, char **arg)
} else if (strcmp(arg[iarg],"type/ratio") == 0) {
if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error);
newtype = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp);
newtype = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
fraction = utils::numeric(FLERR,arg[iarg+2],false,lmp);
ivalue = utils::inumeric(FLERR,arg[iarg+3],false,lmp);
if (newtype <= 0 || newtype > atom->ntypes)
@ -127,7 +135,9 @@ void Set::command(int narg, char **arg)
} else if (strcmp(arg[iarg],"type/subset") == 0) {
if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error);
newtype = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp);
newtype = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
nsubset = utils::bnumeric(FLERR,arg[iarg+2],false,lmp);
ivalue = utils::inumeric(FLERR,arg[iarg+3],false,lmp);
if (newtype <= 0 || newtype > atom->ntypes)
@ -477,7 +487,9 @@ void Set::command(int narg, char **arg)
} else if (strcmp(arg[iarg],"bond") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error);
ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::BOND,lmp);
ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
if (atom->avec->bonds_allow == 0)
error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style());
if (ivalue <= 0 || ivalue > atom->nbondtypes)
@ -487,7 +499,9 @@ void Set::command(int narg, char **arg)
} else if (strcmp(arg[iarg],"angle") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error);
ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ANGLE,lmp);
ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
if (atom->avec->angles_allow == 0)
error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style());
if (ivalue <= 0 || ivalue > atom->nangletypes)
@ -497,7 +511,9 @@ void Set::command(int narg, char **arg)
} else if (strcmp(arg[iarg],"dihedral") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error);
ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::DIHEDRAL,lmp);
ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
if (atom->avec->dihedrals_allow == 0)
error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style());
if (ivalue <= 0 || ivalue > atom->ndihedraltypes)
@ -507,7 +523,9 @@ void Set::command(int narg, char **arg)
} else if (strcmp(arg[iarg],"improper") == 0) {
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error);
ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::IMPROPER,lmp);
ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp);
delete[] typestr;
if (atom->avec->impropers_allow == 0)
error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style());
if (ivalue <= 0 || ivalue > atom->nimpropertypes)
@ -742,6 +760,10 @@ void Set::selection(int n)
else select[i] = 0;
} else if (style == TYPE_SELECT) {
if (char *typestr = utils::expand_type(FLERR,id,Atom::ATOM,lmp)) {
delete[] id;
id = typestr;
}
utils::bounds(FLERR,id,1,atom->ntypes,nlo,nhi,error);
int *type = atom->type;

View File

@ -206,6 +206,16 @@ TEST_F(SetTest, StylesTypes)
sum += (atom->type[i] == 2) ? 1 : 0;
ASSERT_EQ(sum, 4);
BEGIN_HIDE_OUTPUT();
command("labelmap atom 1 C 2 H");
command("set group all type C");
command("set group all type/fraction H 0.5 453246");
END_HIDE_OUTPUT();
sum = 0;
for (int i = 0; i < 8; ++i)
sum += (atom->type[i] == 2) ? 1 : 0;
ASSERT_EQ(sum, 4);
BEGIN_HIDE_OUTPUT();
command("set group all type 1");
command("set group all type/ratio 2 0.5 5784536");
@ -224,6 +234,15 @@ TEST_F(SetTest, StylesTypes)
sum += (atom->type[i] == 2) ? 1 : 0;
ASSERT_EQ(sum, 4);
BEGIN_HIDE_OUTPUT();
command("set group all type C");
command("set group all type/subset H 5 784536");
END_HIDE_OUTPUT();
sum = 0;
for (int i = 0; i < 8; ++i)
sum += (atom->type[i] == 2) ? 1 : 0;
ASSERT_EQ(sum, 5);
TEST_FAILURE(".*ERROR: Numeric index 9 is out of bounds .1-8.*", command("set type 9 x 0.0"););
TEST_FAILURE(".*ERROR: Invalid range string: 3:10.*", command("set type 3:10 x 0.0"););
TEST_FAILURE(".*ERROR: Could not find set group ID nope.*", command("set group nope x 0.0"););
@ -247,6 +266,34 @@ TEST_F(SetTest, PosVelCharge)
ASSERT_EQ(atom->q[6], -1);
ASSERT_EQ(atom->q[7], -1);
BEGIN_HIDE_OUTPUT();
command("labelmap atom 1 C 2 H");
command("set region right type H");
END_HIDE_OUTPUT();
ASSERT_EQ(atom->type[0], 1);
ASSERT_EQ(atom->type[1], 2);
ASSERT_EQ(atom->type[2], 1);
ASSERT_EQ(atom->type[3], 2);
ASSERT_EQ(atom->type[4], 1);
ASSERT_EQ(atom->type[5], 2);
ASSERT_EQ(atom->type[6], 1);
ASSERT_EQ(atom->type[7], 2);
BEGIN_HIDE_OUTPUT();
command("set type C charge 1.25");
command("set type H charge -1.25");
END_HIDE_OUTPUT();
ASSERT_EQ(atom->q[0], 1.25);
ASSERT_EQ(atom->q[1], -1.25);
ASSERT_EQ(atom->q[2], 1.25);
ASSERT_EQ(atom->q[3], -1.25);
ASSERT_EQ(atom->q[4], 1.25);
ASSERT_EQ(atom->q[5], -1.25);
ASSERT_EQ(atom->q[6], 1.25);
ASSERT_EQ(atom->q[7], -1.25);
BEGIN_HIDE_OUTPUT();
command("variable xpos atom 0.5-x");
command("variable ypos atom y*0.5");