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 ... set style ID keyword values ...
* style = *atom* or *type* or *mol* or *group* or *region* * 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 * one or more keyword/value pairs may be appended
* keyword = *type* or *type/fraction* or *type/ratio* or *type/subset* * 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 or *mol* or *x* or *y* or *z* or *vx* or *vy* or *vz* or *charge* or
@ -28,22 +37,22 @@ Syntax
.. parsed-literal:: .. parsed-literal::
*type* value = atom type *type* value = numeric atom type or type label
value can be an atom-style variable (see below) value can be an atom-style variable (see below)
*type/fraction* values = type fraction seed *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 fraction = approximate fraction of selected atoms to set to new atom type
seed = random # seed (positive integer) seed = random # seed (positive integer)
*type/ratio* values = type fraction seed *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 fraction = exact fraction of selected atoms to set to new atom type
seed = random # seed (positive integer) seed = random # seed (positive integer)
*type/subset* values = type Nsubset seed *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 Nsubset = exact number of selected atoms to set to new atom type
seed = random # seed (positive integer) seed = random # seed (positive integer)
*mol* value = molecule ID *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) *x*,\ *y*,\ *z* value = atom coordinate (distance units)
value can be an atom-style variable (see below) value can be an atom-style variable (see below)
*vx*,\ *vy*,\ *vz* value = atom velocity (velocity units) *vx*,\ *vy*,\ *vz* value = atom velocity (velocity units)
@ -107,10 +116,10 @@ Syntax
*image* nx ny nz *image* nx ny nz
nx,ny,nz = which periodic image of the simulation box the atom is in 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) any of nx,ny,nz can be an atom-style variable (see below)
*bond* value = bond type for all bonds between selected atoms *bond* value = numeric bond type or bond type label, for all bonds between selected atoms
*angle* value = angle type for all angles between selected atoms *angle* value = numeric angle type or angle type label, for all angles between selected atoms
*dihedral* value = dihedral type for all dihedrals between selected atoms *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms
*improper* value = improper type for all impropers 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) *sph/e* value = energy of SPH particles (need units)
value can be an atom-style variable (see below) value can be an atom-style variable (see below)
*sph/cv* value = heat capacity of SPH particles (need units) *sph/cv* value = heat capacity of SPH particles (need units)
@ -145,15 +154,19 @@ Examples
.. code-block:: LAMMPS .. code-block:: LAMMPS
set group solvent type 2 set group solvent type 2
set group solvent type C
set group solvent type/fraction 2 0.5 12393 set group solvent type/fraction 2 0.5 12393
set group solvent type/fraction C 0.5 12393
set group edge bond 4 set group edge bond 4
set region half charge 0.5 set region half charge 0.5
set type 3 charge 0.5 set type 3 charge 0.5
set type H charge 0.5
set type 1*3 charge 0.5 set type 1*3 charge 0.5
set atom * charge v_atomfile set atom * charge v_atomfile
set atom 100*200 x 0.5 y 1.0 set atom 100*200 x 0.5 y 1.0
set atom 100 vx 0.0 vy 0.0 vz -1.0 set atom 100 vx 0.0 vy 0.0 vz -1.0
set atom 1492 type 3 set atom 1492 type 3
set atom 1492 type H
set atom * i_myVal 5 set atom * i_myVal 5
set atom * d2_Sxyz[1] 6.4 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 This section describes how to select which atoms to change
the properties of, via the *style* and *ID* arguments. the properties of, via the *style* and *ID* arguments.
The style *atom* selects all the atoms in a range of atom IDs. The .. versionchanged:: 28Mar2023
style *type* selects all the atoms in a range of types. The style
*mol* selects all the atoms in a range of molecule IDs. 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 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 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 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. its integer portion, e.g. a value of 2.6 would become 2.
Keyword *type* sets the atom type for all selected atoms. The .. versionchanged:: 28Mar2023
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.
Keyword *type/fraction* sets the atom type for a fraction of the Support for type labels was added for setting atom, bond, angle,
selected atoms. The actual number of atoms changed is not guaranteed 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 to be exactly the specified fraction (0 <= *fraction* <= 1), but
should be statistically close. Random numbers are used in such a way should be statistically close. Random numbers are used in such a way
that a particular atom is changed or not changed, regardless of how 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 diagnostic or your own analysis relies on the image flags to unwrap a
molecule which straddles the periodic box. molecule which straddles the periodic box.
Keywords *bond*, *angle*, *dihedral*, and *improper*, set the bond type Keywords *bond*, *angle*, *dihedral*, and *improper*, set the bond
(angle type, etc) of all bonds (angles, etc) of selected atoms to the type (angle type, etc) of all bonds (angles, etc) of selected atoms to
specified value from 1 to nbondtypes (nangletypes, etc). All atoms in a the specified value. The value can be a numeric type from 1 to
particular bond (angle, etc) must be selected atoms in order for the nbondtypes (nangletypes, etc). Or it can be a type label (bond type
change to be made. The value of nbondtype (nangletypes, etc) was set by label, angle type lable, etc). See the :doc:`Howto type labels
the *bond types* (\ *angle types*, etc) field in the header of the data <Howto_type_labels>` doc page for the allowed syntax of type labels
file read by the :doc:`read_data <read_data>` command. These keywords and a general discussion of how type labels can be used. All atoms in
do not allow use of an atom-style variable. 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, Keywords *sph/e*, *sph/cv*, and *sph/rho* set the energy, heat capacity,
and density of smoothed particle hydrodynamics (SPH) particles. See 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); 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); 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; 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)) 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); const double value = utils::numeric(FLERR, arg[1], false, lmp);
if (value <= 0.0) 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++) { for (int itype = lo; itype <= hi; itype++) {
mass[itype] = value; mass[itype] = value;

View File

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

View File

@ -206,6 +206,16 @@ TEST_F(SetTest, StylesTypes)
sum += (atom->type[i] == 2) ? 1 : 0; sum += (atom->type[i] == 2) ? 1 : 0;
ASSERT_EQ(sum, 4); 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(); BEGIN_HIDE_OUTPUT();
command("set group all type 1"); command("set group all type 1");
command("set group all type/ratio 2 0.5 5784536"); 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; sum += (atom->type[i] == 2) ? 1 : 0;
ASSERT_EQ(sum, 4); 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: 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: 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");); 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[6], -1);
ASSERT_EQ(atom->q[7], -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(); BEGIN_HIDE_OUTPUT();
command("variable xpos atom 0.5-x"); command("variable xpos atom 0.5-x");
command("variable ypos atom y*0.5"); command("variable ypos atom y*0.5");