From 36afc91dfa27c6e5b8ebbd64976a58c80cba2a6a Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Sat, 25 Nov 2023 15:20:28 -0700 Subject: [PATCH 01/26] draft version of refactored set command as set2 --- doc/src/set2.rst | 656 +++++++++++++ src/set2.cpp | 2327 ++++++++++++++++++++++++++++++++++++++++++++++ src/set2.h | 186 ++++ 3 files changed, 3169 insertions(+) create mode 100644 doc/src/set2.rst create mode 100644 src/set2.cpp create mode 100644 src/set2.h diff --git a/doc/src/set2.rst b/doc/src/set2.rst new file mode 100644 index 0000000000..92e6eaf65d --- /dev/null +++ b/doc/src/set2.rst @@ -0,0 +1,656 @@ +.. index:: set + +set command +=========== + +Syntax +"""""" + +.. code-block:: LAMMPS + + set style ID keyword values ... + +* style = *atom* or *type* or *mol* or *group* or *region* +* 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 = *angle* or *angmom* or *bond* or *cc* or *charge* or + *density* or *density/disc* or *diameter* or *dihedral* or *dipole* + or *dipole/random* or *dpd/theta* or *edpd/cv* or *edpd/temp* or + *epsilon* or *image* or *improper* or *length* or *mass* or *mol* or + *omega* or *quat* or *quat/random* or *radius/electron* or *shape* or + *smd/contact/radius* or *smd/mass/density* or *sph/cv* or *sph/e* or + *sph/rho* or *spin/atom* or *spin/atom/random* or *spin/electron* or + *temperature* or *theta* or *theta/random* or *tri* or *type* or + *type/fraction* or *type/ratio* or *type/subset* or *volume* or *vx* + or *vy* or *vz* or *x* or *y* or *z* or *i_name* or *d_name* or + *i2_name* or *d2_name* + + .. parsed-literal:: + + *angle* value = numeric angle type or angle type label, for all angles between selected atoms + *angmom* values = Lx Ly Lz + Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units) + any of Lx,Ly,Lz can be an atom-style variable (see below) + *bond* value = numeric bond type or bond type label, for all bonds between selected atoms + *cc* values = index cc + index = index of a chemical species (1 to Nspecies) + cc = chemical concentration of tDPD particles for a species (mole/volume units) + cc can be an atom-style variable (see below) + *charge* value = atomic charge (charge units) + value can be an atom-style variable (see below) + *density* value = particle density for a sphere or ellipsoid (mass/distance\^3 units), or for a triangle (mass/distance\^2 units) or line (mass/distance units) particle + value can be an atom-style variable (see below) + *density/disc* value = particle density for a 2d disc or ellipse (mass/distance\^2 units) + value can be an atom-style variable (see below) + *diameter* value = diameter of spherical particle (distance units) + value can be an atom-style variable (see below) + *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms + *dipole* values = x y z + x,y,z = orientation of dipole moment vector + any of x,y,z can be an atom-style variable (see below) + *dipole/random* values = seed Dlen + seed = random # seed (positive integer) for dipole moment orientations + Dlen = magnitude of dipole moment (dipole units) + *dpd/theta* value = internal temperature of DPD particles (temperature units) + value can be an atom-style variable (see below) + value can be NULL which sets internal temp of each particle to KE temp + *edpd/cv* value = volumetric heat capacity of eDPD particles (energy/temperature/volume units) + value can be an atom-style variable (see below) + *edpd/temp* value = temperature of eDPD particles (temperature units) + value can be an atom-style variable (see below) + *epsilon* value = dielectric constant of the medium where the atoms reside + value can be an atom-style variable (see below) + *image* values = 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) + *improper* value = numeric improper type or improper type label, for all impropers between selected atoms + *length* value = len + len = length of line segment (distance units) + len can be an atom-style variable (see below) + *mass* value = per-atom mass (mass units) + value can be an atom-style variable (see below) + *mol* value = molecule ID + the moleclue ID can be an atom-style variable (see below) + *omega* values = Wx Wy Wz + Wx,Wy,Wz = components of angular velocity vector (radians/time units) + any of Wx,Wy,Wz can be an atom-style variable (see below) + *quat* values = a b c theta + a,b,c = unit vector to rotate particle around via right-hand rule + theta = rotation angle (degrees) + any of a,b,c,theta values can be an atom-style variable (see below) + *quat/random* value = seed + seed = random # seed (positive integer) for quaternion orientations + *radius/electron* value = eradius + eradius = electron radius (or fixed-core radius) (distance units) + value can be an atom-style variable (see below) + *shape* values = Sx Sy Sz + Sx,Sy,Sz = 3 diameters of ellipsoid (distance units) + any of Sx,Sy,Sz can be an atom-style variable (see below) + *smd/contact/radius* value = radius for short range interactions, i.e. contact and friction + value can be an atom-style variable (see below) + *smd/mass/density* value = set particle mass based on volume by providing a mass density + value can be an atom-style variable (see below) + *sph/cv* value = heat capacity of SPH particles (need units) + value can be an atom-style variable (see below) + *sph/e* value = energy of SPH particles (need units) + value can be an atom-style variable (see below) + *sph/rho* value = density of SPH particles (need units) + value can be an atom-style variable (see below) + *spin/atom* values = g x y z + g = magnitude of magnetic spin vector (in Bohr magneton's unit) + x,y,z = orientation of magnetic spin vector + any of x,y,z can be an atom-style variable (see below) + *spin/atom/random* values = seed Dlen + seed = random # seed (positive integer) for magnetic spin orientations + Dlen = magnitude of magnetic spin vector (in Bohr magneton's unit) + *spin/electron* value = espin + espin = electron spin (+1/-1), 0 = nuclei, 2 = fixed-core, 3 = pseudo-cores (i.e. ECP) + value can be an atom-style variable (see below) + *temperature* value = temperature for finite-size particles (temperature units) + value can be an atom-style variable (see below) + *theta* value = angle (degrees) + angle = orientation of line segment with respect to x-axis + value can be an atom-style variable (see below) + *theta/random* value = seed + seed = random # seed (positive integer) for line segment orienations + *tri* value = side + side = side length of equilateral triangle (distance units) + value can be an atom-style variable (see below) + *type* value = numeric atom type or type label + value can be an atom-style variable (see below) + *type/fraction* values = type fraction seed + 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 = 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 = numeric atom type or type label + Nsubset = exact number of selected atoms to set to new atom type + seed = random # seed (positive integer) + *volume* value = particle volume for Peridynamic particle (distance\^3 units) + value can be an atom-style variable (see below) + *vx*,\ *vy*,\ *vz* value = atom velocity (velocity units) + 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) + *i_name* value = custom integer vector with name + value can be an atom-style variable (see below) + *d_name* value = custom floating-point vector with name + value can be an atom-style variable (see below) + *i2_name* value = custom integer array with name + column specified as i2_name[N] where N is 1 to Ncol + value can be an atom-style variable (see below) + *d2_name* value = custom floating-point array with name + column specified as d2_name[N] where N is 1 to Ncol + value can be an atom-style variable (see below) + +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 + +Description +""""""""""" + +Set one or more properties of one or more atoms. Since atom +properties are initially assigned by the :doc:`read_data `, +:doc:`read_restart ` or :doc:`create_atoms ` +commands, this command changes those assignments. This can be useful +for overriding the default values assigned by the +:doc:`create_atoms ` command (e.g. charge = 0.0). It can +be useful for altering pairwise and molecular force interactions, +since force-field coefficients are defined in terms of types. It can +be used to change the labeling of atoms by atom type or molecule ID +when they are output in :doc:`dump ` files. It can also be useful +for debugging purposes; i.e. positioning an atom at a precise location +to compute subsequent forces or energy. + +Note that the *style* and *ID* arguments determine which atoms have +their properties reset. The remaining keywords specify which +properties to reset and what the new values are. Some strings like +*type* or *mol* can be used as a style and/or a keyword. + +---------- + +This section describes how to select which atoms to change +the properties of, via the *style* and *ID* arguments. + +.. 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 +of values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For +example, for the style *type*, if N = the number of atom types, then +an asterisk with no numeric values means all types from 1 to N. A +leading asterisk means all types from 1 to n (inclusive). A trailing +asterisk means all types from n to N (inclusive). A middle asterisk +means all types from m to n (inclusive). For all the styles except +*mol*, the lowest value for the wildcard is 1; for *mol* it is 0. + +The style *group* selects all the atoms in the specified group. The +style *region* selects all the atoms in the specified geometric +region. See the :doc:`group ` and :doc:`region ` commands +for details of how to specify a group or region. + +---------- + +The next section describes the keyword options for which properties to +change, for the selected atoms. + +Note that except where explicitly prohibited below, all of the +keywords allow an :doc:`atom-style or atomfile-style variable +` to be used as the specified value(s). If the value is a +variable, it should be specified as v_name, where name is the +variable name. In this case, the variable will be evaluated, and its +resulting per-atom value used to determine the value assigned to each +selected atom. Note that the per-atom value from the variable will be +ignored for atoms that are not selected via the *style* and *ID* +settings explained above. A simple way to use per-atom values from +the variable to reset a property for all atoms is to use style *atom* +with *ID* = "\*"; this selects all atom IDs. + +Atom-style variables can specify formulas with various mathematical +functions, and include :doc:`thermo_style ` command +keywords for the simulation box parameters and timestep and elapsed +time. They can also include per-atom values, such as atom +coordinates. Thus it is easy to specify a time-dependent or +spatially-dependent set of per-atom values. As explained on the +:doc:`variable ` doc page, atomfile-style variables can be +used in place of atom-style variables, and thus as arguments to the +set command. Atomfile-style variables read their per-atoms values +from a file. + +.. note:: + + Atom-style and atomfile-style variables return floating point + per-atom values. If the values are assigned to an integer variable, + 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. + +---------- + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting angle types + +Keyword *angle* sets the angle type of all angles of selected atoms to +the specified value. The value can be a numeric type from 1 to +nangletypes. Or it can be a angle type label. See the :doc:`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 angle must be selected atoms in order for +the change to be made. The value of nangletypes was set by the *angle +types* field in the header of the data file read by the +:doc:`read_data ` command. This keyword does not allow use +of an atom-style variable. + +Keyword *angmom* sets the angular momentum of selected atoms. The +particles must be ellipsoids as defined by the :doc:`atom_style +ellipsoid ` command or triangles as defined by the +:doc:`atom_style tri ` command. The angular momentum +vector of the particles is set to the 3 specified components. + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting bond types + +Keyword *bond* sets the bond type of all bonds of selected atoms to +the specified value. The value can be a numeric type from 1 to +nbondtypes. Or it can be a bond type label. See the :doc:`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 must be selected atoms in order for the +change to be made. The value of nbondtypes was set by the *bond +types* field in the header of the data file read by the +:doc:`read_data ` command. This keyword does not allow use +of an atom-style variable. + +Keyword *cc* sets the chemical concentration of a tDPD particle for a +specified species as defined by the DPD-MESO package. Currently, only +:doc:`atom_style tdpd ` defines particles with this +attribute. An integer for "index" selects a chemical species (1 to +Nspecies) where Nspecies is set by the atom_style command. The value for +the chemical concentration must be >= 0.0. + +Keyword *charge* set the charge of all selected atoms. The :doc:`atom +style ` being used must support the use of atomic charge. + +Keyword *density* or *density/disc* also sets the mass of all selected +particles, but in a different way. The particles must have a per-atom +mass attribute, as defined by the :doc:`atom_style ` +command. If the atom has a radius attribute (see :doc:`atom_style +sphere `) and its radius is non-zero, its mass is set from +the density and particle volume for 3d systems (the input density is +assumed to be in mass/distance\^3 units). For 2d, the default is for +LAMMPS to model particles with a radius attribute as spheres. However, +if the *density/disc* keyword is used, then they can be modeled as 2d +discs (circles). Their mass is set from the density and particle area +(the input density is assumed to be in mass/distance\^2 units). + +If the atom has a shape attribute (see :doc:`atom_style ellipsoid +`) and its 3 shape parameters are non-zero, then its mass is +set from the density and particle volume (the input density is assumed +to be in mass/distance\^3 units). The *density/disc* keyword has no +effect; it does not (yet) treat 3d ellipsoids as 2d ellipses. + +If the atom has a length attribute (see :doc:`atom_style line +`) and its length is non-zero, then its mass is set from the +density and line segment length (the input density is assumed to be in +mass/distance units). If the atom has an area attribute (see +:doc:`atom_style tri `) and its area is non-zero, then its +mass is set from the density and triangle area (the input density is +assumed to be in mass/distance\^2 units). + +If none of these cases are valid, then the mass is set to the density +value directly (the input density is assumed to be in mass units). + +Keyword *diameter* sets the size of the selected atoms. The particles +must be finite-size spheres as defined by the :doc:`atom_style sphere +` command. The diameter of a particle can be set to 0.0, +which means they will be treated as point particles. Note that this +command does not adjust the particle mass, even if it was defined with +a density, e.g. via the :doc:`read_data ` command. + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting dihedral types + +Keyword *dihedral* sets the dihedral type of all dihedrals of selected +atoms to the specified value. The value can be a numeric type from 1 +to ndihedraltypes. Or it can be a dihedral type label. See the +:doc:`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 dihedral must be selected atoms in +order for the change to be made. The value of ndihedraltypes was set +by the *dihedral types* field in the header of the data file read by +the :doc:`read_data ` command. This keyword does not allow +use of an atom-style variable. + +Keyword *dipole* uses the specified x,y,z values as components of a +vector to set as the orientation of the dipole moment vectors of the +selected atoms. The magnitude of the dipole moment is set by the +length of this orientation vector. + +Keyword *dipole/random* randomizes the orientation of the dipole +moment vectors for the selected atoms and sets the magnitude of each +to the specified *Dlen* value. For 2d systems, the z component of the +orientation is set to 0.0. Random numbers are used in such a way that +the orientation of a particular atom is the same, regardless of how +many processors are being used. This keyword does not allow use of an +atom-style variable. + +Keyword *dpd/theta* sets the internal temperature of a DPD particle as +defined by the DPD-REACT package. If the specified value is a number it +must be >= 0.0. If the specified value is NULL, then the kinetic +temperature Tkin of each particle is computed as 3/2 k Tkin = KE = 1/2 m +v\^2 = 1/2 m (vx\*vx+vy\*vy+vz\*vz). Each particle's internal +temperature is set to Tkin. If the specified value is an atom-style +variable, then the variable is evaluated for each particle. If a value +>= 0.0, the internal temperature is set to that value. If it is < 0.0, +the computation of Tkin is performed and the internal temperature is set +to that value. + +Keywords *edpd/temp* and *edpd/cv* set the temperature and volumetric +heat capacity of an eDPD particle as defined by the DPD-MESO package. +Currently, only :doc:`atom_style edpd ` defines particles +with these attributes. The values for the temperature and heat capacity +must be positive. + +Keyword *epsilon* sets the dielectric constant of a particle, precisely +of the medium where the particle resides as defined by the DIELECTRIC +package. Currently, only :doc:`atom_style dielectric ` +defines particles with this attribute. The value for the dielectric +constant must be >= 0.0. Note that the set command with this keyword +will rescale the particle charge accordingly so that the real charge +(e.g., as read from a data file) stays intact. To change the real +charges, one needs to use the set command with the *charge* +keyword. Care must be taken to ensure that the real and scaled charges, +and dielectric constants are consistent. + +Keyword *image* sets which image of the simulation box the atom is +considered to be in. An image of 0 means it is inside the box as +defined. A value of 2 means add 2 box lengths to get the true value. A +value of -1 means subtract 1 box length to get the true value. LAMMPS +updates these flags as atoms cross periodic boundaries during the +simulation. The flags can be output with atom snapshots via the +:doc:`dump ` command. If a value of NULL is specified for any of +nx,ny,nz, then the current image value for that dimension is unchanged. +For non-periodic dimensions only a value of 0 can be specified. This +command can be useful after a system has been equilibrated and atoms +have diffused one or more box lengths in various directions. This +command can then reset the image values for atoms so that they are +effectively inside the simulation box, e.g if a diffusion coefficient is +about to be measured via the :doc:`compute msd ` command. +Care should be taken not to reset the image flags of two atoms in a bond +to the same value if the bond straddles a periodic boundary (rather they +should be different by +/- 1). This will not affect the dynamics of a +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. + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting improper types + +Keyword *improper* sets the improper type of all impropers of selected +atoms to the specified value. The value can be a numeric type from 1 +to nimpropertypes. Or it can be a improper type label. See the +:doc:`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 improper must be selected atoms in +order for the change to be made. The value of nimpropertypes was set +by the *improper types* field in the header of the data file read by +the :doc:`read_data ` command. This keyword does not allow +use of an atom-style variable. + +Keyword *length* sets the length of selected atoms. The particles +must be line segments as defined by the :doc:`atom_style line +` command. If the specified value is non-zero the line +segment is (re)set to a length = the specified value, centered around +the particle position, with an orientation along the x-axis. If the +specified value is 0.0, the particle will become a point particle. +Note that this command does not adjust the particle mass, even if it +was defined with a density, e.g. via the :doc:`read_data ` +command. + +Keyword *mass* sets the mass of all selected particles. The particles +must have a per-atom mass attribute, as defined by the :doc:`atom_style +` command. See the "mass" command for how to set mass +values on a per-type basis. + +Keyword *mol* sets the molecule ID for all selected atoms. The +:doc:`atom style ` being used must support the use of +molecule IDs. + +Keyword *omega* sets the angular velocity of selected atoms. The +particles must be spheres as defined by the :doc:`atom_style sphere +` command. The angular velocity vector of the particles is +set to the 3 specified components. + +Keyword *quat* uses the specified values to create a quaternion +(4-vector) that represents the orientation of the selected atoms. The +particles must define a quaternion for their orientation +(e.g. ellipsoids, triangles, body particles) as defined by the +:doc:`atom_style ` command. Note that particles defined by +:doc:`atom_style ellipsoid ` have 3 shape parameters. The 3 +values must be non-zero for each particle set by this command. They +are used to specify the aspect ratios of an ellipsoidal particle, +which is oriented by default with its x-axis along the simulation +box's x-axis, and similarly for y and z. If this body is rotated (via +the right-hand rule) by an angle theta around a unit rotation vector +(a,b,c), then the quaternion that represents its new orientation is +given by (cos(theta/2), a\*sin(theta/2), b\*sin(theta/2), +c\*sin(theta/2)). The theta and a,b,c values are the arguments to the +*quat* keyword. LAMMPS normalizes the quaternion in case (a,b,c) was +not specified as a unit vector. For 2d systems, the a,b,c values are +ignored, since a rotation vector of (0,0,1) is the only valid choice. + +Keyword *quat/random* randomizes the orientation of the quaternion for +the selected atoms. The particles must define a quaternion for their +orientation (e.g. ellipsoids, triangles, body particles) as defined by +the :doc:`atom_style ` command. Random numbers are used in +such a way that the orientation of a particular atom is the same, +regardless of how many processors are being used. For 2d systems, +only orientations in the xy plane are generated. As with keyword +*quat*, for ellipsoidal particles, the 3 shape values must be non-zero +for each particle set by this command. This keyword does not allow +use of an atom-style variable. + +.. versionadded:: 15Sep2022 + +Keyword *radius/electron* uses the specified value to set the radius of +electrons or fixed cores. + +Keyword *shape* sets the size and shape of the selected atoms. The +particles must be ellipsoids as defined by the :doc:`atom_style +ellipsoid ` command. The *Sx*, *Sy*, *Sz* settings +are the 3 diameters of the ellipsoid in each direction. All 3 can be +set to the same value, which means the ellipsoid is effectively a +sphere. They can also all be set to 0.0 which means the particle will +be treated as a point particle. Note that this command does not +adjust the particle mass, even if it was defined with a density, +e.g. via the :doc:`read_data ` command. + +Keyword *smd/contact/radius* only applies to simulations with the Smooth +Mach Dynamics package MACHDYN. Itsets an interaction radius for +computing short-range interactions, e.g. repulsive forces to prevent +different individual physical bodies from penetrating each other. Note +that the SPH smoothing kernel diameter used for computing long range, +nonlocal interactions, is set using the *diameter* keyword. + +Keyword *smd/mass/density* sets the mass of all selected particles, but +it is only applicable to the Smooth Mach Dynamics package MACHDYN. It +assumes that the particle volume has already been correctly set and +calculates particle mass from the provided mass density value. + +Keywords *sph/e*, *sph/cv*, and *sph/rho* set the energy, heat capacity, +and density of smoothed particle hydrodynamics (SPH) particles. See +`this PDF guide `_ to using SPH in LAMMPS. + +.. versionchanged:: 15Sep2022 + +Keyword *spin/atom* uses the specified g value to set the magnitude of the +magnetic spin vectors, and the x,y,z values as components of a vector +to set as the orientation of the magnetic spin vectors of the selected +atoms. This keyword was previously called *spin*. + +.. versionchanged:: 15Sep2022 + +Keyword *spin/atom/random* randomizes the orientation of the magnetic +spin vectors for the selected atoms and sets the magnitude of each to +the specified *Dlen* value. This keyword does not allow use of an +atom-style variable. This keyword was previously called +*spin/random*. + +.. versionadded:: 15Sep2022 + +Keyword *spin/electron* sets the spin of an electron (+/- 1) or indicates +nuclei (=0), fixed-cores (=2), or pseudo-cores (= 3). + +Keyword *temperature* sets the temperature of a finite-size particle. +Currently, only the GRANULAR package supports this attribute. The +temperature must be added using an instance of +:doc:`fix property/atom ` The values for the +temperature must be positive. + +Keyword *theta* sets the orientation of selected atoms. The particles +must be line segments as defined by the :doc:`atom_style line +` command. The specified value is used to set the +orientation angle of the line segments with respect to the x axis. + +Keyword *theta/random* randomizes the orientation of theta for the +selected atoms. The particles must be line segments as defined by the +:doc:`atom_style line ` command. Random numbers are used in +such a way that the orientation of a particular atom is the same, +regardless of how many processors are being used. This keyword does +not allow use of an atom-style variable. + +Keyword *tri* sets the size of selected atoms. The particles must be +triangles as defined by the :doc:`atom_style tri ` command. +If the specified value is non-zero the triangle is (re)set to be an +equilateral triangle in the xy plane with side length = the specified +value, with a centroid at the particle position, with its base +parallel to the x axis, and the y-axis running from the center of the +base to the top point of the triangle. If the specified value is 0.0, +the particle will become a point particle. Note that this command +does not adjust the particle mass, even if it was defined with a +density, e.g. via the :doc:`read_data ` command. + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting atom 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 ` command or +the *atom types* field in the header of the data file read by the +:doc:`read_data ` command. When using a type label it must +have been defined previously. See the :doc:`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 +many processors are being used. This keyword does not allow use of an +atom-style variable. + +Keywords *type/ratio* and *type/subset* also set the atom type for a +fraction of the selected atoms. The actual number of atoms changed +will be exactly the requested number. For *type/ratio* the specified +fraction (0 <= *fraction* <= 1) determines the number. For +*type/subset*, the specified *Nsubset* is the number. An iterative +algorithm is used which ensures the correct number of atoms are +selected, in a perfectly random fashion. Which atoms are selected +will change with the number of processors used. These keywords do not +allow use of an atom-style variable. + +Keyword *volume* sets the volume of all selected particles. Currently, +only the :doc:`atom_style peri ` command defines particles +with a volume attribute. Note that this command does not adjust the +particle mass. + +Keywords *vx*, *vy*, and *vz* set the velocities of all selected +atoms. + +Keywords *x*, *y*, *z* set the coordinates of all selected atoms. + +Keywords *i_name*, *d_name*, *i2_name*, *d2_name* refer to custom +per-atom integer and floating-point vectors or arrays that have been +added via the :doc:`fix property/atom ` command. +When that command is used specific names are given to each attribute +which are the "name" portion of these keywords. For arrays *i2_name* +and *d2_name*, the column of the array to set must also be included +following the name in brackets: e.g. d2_xyz[2] or i2_mySpin[3]. + +Restrictions +"""""""""""" + +You cannot set an atom attribute (e.g. *mol* or *q* or *volume*\ ) if +the :doc:`atom_style ` does not have that attribute. + +This command requires inter-processor communication to coordinate the +setting of bond types (angle types, etc). This means that your system +must be ready to perform a simulation before using one of these +keywords (force fields set, atom mass set, etc). This is not +necessary for other keywords. + +Using the *region* style with the bond (angle, etc) keywords can give +unpredictable results if there are bonds (angles, etc) that straddle +periodic boundaries. This is because the region may only extend up to +the boundary and partner atoms in the bond (angle, etc) may have +coordinates outside the simulation box if they are ghost atoms. + +Related commands +"""""""""""""""" + +:doc:`create_box `, :doc:`create_atoms `, +:doc:`read_data ` + +Default +""""""" + +none diff --git a/src/set2.cpp b/src/set2.cpp new file mode 100644 index 0000000000..6055f83ad0 --- /dev/null +++ b/src/set2.cpp @@ -0,0 +1,2327 @@ +// clang-format off +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "set2.h" + +#include "arg_info.h" +#include "atom.h" +#include "atom_vec.h" +#include "atom_vec_body.h" +#include "atom_vec_ellipsoid.h" +#include "atom_vec_line.h" +#include "atom_vec_tri.h" +#include "comm.h" +#include "domain.h" +#include "error.h" +#include "force.h" +#include "group.h" +#include "input.h" +#include "math_const.h" +#include "math_extra.h" +#include "memory.h" +#include "modify.h" +#include "random_mars.h" +#include "random_park.h" +#include "region.h" +#include "variable.h" + +#include +#include + +using namespace LAMMPS_NS; +using namespace MathConst; + +enum{SET,FIXSET}; + +enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; + +enum{TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET, + MOLECULE,X,Y,Z,VX,VY,VZ,CHARGE,MASS,SHAPE,LENGTH,TRI, + DIPOLE,DIPOLE_RANDOM,SPIN_ATOM,SPIN_RANDOM,SPIN_ELECTRON,RADIUS_ELECTRON, + QUAT,QUAT_RANDOM,THETA,THETA_RANDOM,ANGMOM,OMEGA,TEMPERATURE, + DIAMETER,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER, + SPH_E,SPH_CV,SPH_RHO,EDPD_TEMP,EDPD_CV,CC,SMD_MASS_DENSITY, + SMD_CONTACT_RADIUS,DPDTHETA,EPSILON,IVEC,DVEC,IARRAY,DARRAY}; + +#define BIG INT_MAX +#define DELTA 4 + +/* ---------------------------------------------------------------------- */ + +void Set2::command(int narg, char **arg) +{ + if (domain->box_exist == 0) + error->all(FLERR,"Set command before simulation box is defined"); + if (atom->natoms == 0) + error->all(FLERR,"Set command on system without atoms"); + + select = nullptr; + + process_args(SET,narg-3,&arg[3]); + + if (comm->me == 0) utils::logmesg(lmp,"Setting atom values ...\n"); + + selection(atom->nlocal); + + // loop over list of actions to reset attributes + + invoke_actions(); + + // statistics + // for CC option, include species index + + int origarg; + + int count,allcount; + MPI_Allreduce(&count,&allcount,1,MPI_INT,MPI_SUM,world); + + if (comm->me == 0) { + if (strcmp(arg[origarg],"cc") == 0) + utils::logmesg(lmp," {} settings made for {} index {}\n", + allcount,arg[origarg],arg[origarg+1]); + else + utils::logmesg(lmp," {} settings made for {}\n", + allcount,arg[origarg]); + } + + // clean up + + memory->destroy(select); +} + +/* ---------------------------------------------------------------------- + set an owned atom property randomly + set seed based on atom coordinates + make atom result independent of what proc owns it +------------------------------------------------------------------------- */ + +void Set2::process_args(int caller_flag, int narg, char **arg) +{ + caller = caller_flag; + + if (narg < 3) error->all(FLERR,"Illegal set command"); + + // style and ID info + + id = utils::strdup(arg[1]); + + if (strcmp(arg[0],"atom") == 0) { + style = ATOM_SELECT; + if (atom->tag_enable == 0) + error->all(FLERR,"Cannot use set atom with no atom IDs defined"); + utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); + + } else if (strcmp(arg[0],"mol") == 0) { + style = MOL_SELECT; + if (atom->molecule_flag == 0) + error->all(FLERR,"Cannot use set mol with no molecule IDs defined"); + utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); + + } else if (strcmp(arg[0],"type") == 0) { + 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); + + } else if (strcmp(arg[0],"group") == 0) { + style = GROUP_SELECT; + int igroup = group->find(id); + if (igroup == -1) error->all(FLERR,"Could not find set group ID {}", id); + groupbit = group->bitmask[igroup]; + + } else if (strcmp(arg[0],"region") == 0) { + style = REGION_SELECT; + region = domain->get_region_by_id(id); + if (!region) error->all(FLERR,"Set region {} does not exist", id); + + } else error->all(FLERR,"Unknown set command style: {}", arg[0]); + + delete [] id; + + // loop over keyword/value pairs to create list of actions + // one action = keyword/value pair + + naction = maxaction = 0; + actions = nullptr; + + int iarg = 2; + while (iarg < narg) { + if (naction == maxaction) { + maxaction += DELTA; + actions = (Action *) memory->srealloc(actions,maxaction*sizeof(Action),"set:actions"); + invoke_choice = (FnPtrPack *) + memory->srealloc(invoke_choice,maxaction*sizeof(FnPtrPack),"set:invoke_choice"); + } + + if (strcmp(arg[iarg],"angle") == 0) { + process_angle(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_angle; + } else if (strcmp(arg[iarg],"angmom") == 0) { + process_angmom(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_angmom; + } else if (strcmp(arg[iarg],"bond") == 0) { + process_bond(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_bond; + } else if (strcmp(arg[iarg],"cc") == 0) { + process_cc(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_cc; + } else if (strcmp(arg[iarg],"charge") == 0) { + process_charge(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_charge; + } else if (strcmp(arg[iarg],"density") == 0 ||(strcmp(arg[iarg],"density/disc") == 0)) { + process_density(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_density; + } else if (strcmp(arg[iarg],"diameter") == 0) { + process_diameter(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_diameter; + } else if (strcmp(arg[iarg],"dihedral") == 0) { + process_dihedral(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_dihedral; + } else if (strcmp(arg[iarg],"dipole") == 0) { + process_dipole(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_dipole; + } else if (strcmp(arg[iarg],"dipole/random") == 0) { + process_dipole_random(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_dipole_random; + } else if (strcmp(arg[iarg],"dpd/theta") == 0) { + process_dpd_theta(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_dpd_theta; + } else if (strcmp(arg[iarg],"edpd/cv") == 0) { + process_edpd_cv(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_edpd_cv; + } else if (strcmp(arg[iarg],"edpd/temp") == 0) { + process_edpd_temp(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_edpd_temp; + } else if (strcmp(arg[iarg],"epsilon") == 0) { + process_epsilon(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_epsilon; + } else if (strcmp(arg[iarg],"image") == 0) { + process_image(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_image; + } else if (strcmp(arg[iarg],"improper") == 0) { + process_improper(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_improper; + } else if (strcmp(arg[iarg],"length") == 0) { + process_length(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_length; + } else if (strcmp(arg[iarg],"mass") == 0) { + process_mass(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_mass; + } else if (strcmp(arg[iarg],"mol") == 0) { + process_mol(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_mol; + } else if (strcmp(arg[iarg],"omega") == 0) { + process_omega(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_omega; + } else if (strcmp(arg[iarg],"quat") == 0) { + process_quat(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_quat; + } else if (strcmp(arg[iarg],"quat/random") == 0) { + process_quat_random(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_quat_random; + } else if (strcmp(arg[iarg],"radius/electron") == 0) { + process_radius_election(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_radius_election; + } else if (strcmp(arg[iarg],"shape") == 0) { + process_shape(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_shape; + } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { + process_smd_contact_radius(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_smd_contact_radius; + } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { + process_smd_mass_density(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_density; + } else if (strcmp(arg[iarg],"sph/cv") == 0) { + process_sph_cv(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_sph_cv; + } else if (strcmp(arg[iarg],"sph/e") == 0) { + process_sph_e(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_sph_e; + } else if (strcmp(arg[iarg],"sph/rho") == 0) { + process_sph_rho(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_sph_rho; + } else if ((strcmp(arg[iarg],"spin/atom") == 0) || (strcmp(arg[iarg],"spin") == 0)) { + process_spin_atom(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_spin_atom; + } else if ((strcmp(arg[iarg],"spin/atom/random") == 0) || (strcmp(arg[iarg],"spin/random") == 0)) { + process_spin_atom_random(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_spin_atom_random; + } else if (strcmp(arg[iarg],"spin/electron") == 0) { + process_spin_electron(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_spin_electron; + } else if (strcmp(arg[iarg],"temperature") == 0) { + process_temperature(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_temperature; + } else if (strcmp(arg[iarg],"theta") == 0) { + process_theta(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_theta; + } else if (strcmp(arg[iarg],"theta/random") == 0) { + process_theta_random(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_theta_random; + } else if (strcmp(arg[iarg],"tri") == 0) { + process_tri(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_tri; + } else if (strcmp(arg[iarg],"type") == 0) { + process_type(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_type; + } else if (strcmp(arg[iarg],"type/fraction") == 0) { + process_type_fraction(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_type_fraction; + } else if (strcmp(arg[iarg],"type/ratio") == 0) { + process_type_ratio(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_type_ratio; + } else if (strcmp(arg[iarg],"type/subset") == 0) { + process_type_subset(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_type_subset; + } else if (strcmp(arg[iarg],"volume") == 0) { + process_volume(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_volume; + } else if (strcmp(arg[iarg],"vx") == 0) { + process_vx(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_vx; + } else if (strcmp(arg[iarg],"vy") == 0) { + process_vy(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_vy; + } else if (strcmp(arg[iarg],"vz") == 0) { + process_vz(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_vz; + } else if (strcmp(arg[iarg],"x") == 0) { + process_x(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_x; + } else if (strcmp(arg[iarg],"y") == 0) { + process_y(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_y; + } else if (strcmp(arg[iarg],"z") == 0) { + process_z(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_z; + + } else if (utils::strmatch(arg[iarg],"^[id]2?_")) { + process_custom(iarg,narg,arg); + invoke_choice[naction++] = &Set2::invoke_custom; + + } else { + error->all(FLERR,"Illegal set command keyword"); + } + } +} + +/* ---------------------------------------------------------------------- + loop over list of actions + perform each on all selected atoms via call to invoke_choice() method +------------------------------------------------------------------------- */ + +void Set2::invoke_actions() +{ + for (int i = 0; i < naction; i++) { + + // overwrite dvalue, ivalue, xyzw value if variables defined + // else the input script scalar value remains in place + + if (varflag) { + if (varflag1) { + dvalue = xvalue = vec1[i]; + ivalue = static_cast (dvalue); + } + if (varflag2) yvalue = vec2[i]; + if (varflag3) zvalue = vec3[i]; + if (varflag4) wvalue = vec4[i]; + } + + (this->*invoke_choice[i])(); + } +} + +/* ---------------------------------------------------------------------- + select atoms according to ATOM, MOLECULE, TYPE, GROUP, REGION style + n = nlocal or nlocal+nghost depending on keyword +------------------------------------------------------------------------- */ + +void Set2::selection(int n) +{ + memory->destroy(select); + memory->create(select,n,"set:select"); + + if (style == ATOM_SELECT) { + tagint *tag = atom->tag; + for (int i = 0; i < n; i++) + if (tag[i] >= nlobig && tag[i] <= nhibig) select[i] = 1; + else select[i] = 0; + + } else if (style == MOL_SELECT) { + tagint *molecule = atom->molecule; + for (int i = 0; i < n; i++) + if (molecule[i] >= nlobig && molecule[i] <= nhibig) select[i] = 1; + else select[i] = 0; + + } else if (style == TYPE_SELECT) { + int *type = atom->type; + for (int i = 0; i < n; i++) + if (type[i] >= nlo && type[i] <= nhi) select[i] = 1; + else select[i] = 0; + + } else if (style == GROUP_SELECT) { + int *mask = atom->mask; + for (int i = 0; i < n; i++) + if (mask[i] & groupbit) select[i] = 1; + else select[i] = 0; + + } else if (style == REGION_SELECT) { + region->prematch(); + double **x = atom->x; + for (int i = 0; i < n; i++) + if (region->match(x[i][0],x[i][1],x[i][2])) select[i] = 1; + else select[i] = 0; + } +} + +/* ---------------------------------------------------------------------- + set owned atom properties directly + either scalar or per-atom values from atom-style variable(s) +------------------------------------------------------------------------- */ + +void Set2::set(int keyword) +{ + // evaluate atom-style variable(s) if necessary + + vec1 = vec2 = vec3 = vec4 = nullptr; + + if (varflag) { + int nlocal = atom->nlocal; + if (varflag1) { + memory->create(vec1,nlocal,"set:vec1"); + input->variable->compute_atom(ivar1,0,vec1,1,0); + } + if (varflag2) { + memory->create(vec2,nlocal,"set:vec2"); + input->variable->compute_atom(ivar2,0,vec2,1,0); + } + if (varflag3) { + memory->create(vec3,nlocal,"set:vec3"); + input->variable->compute_atom(ivar3,0,vec3,1,0); + } + if (varflag4) { + memory->create(vec4,nlocal,"set:vec4"); + input->variable->compute_atom(ivar4,0,vec4,1,0); + } + } + + // check if properties of atoms in rigid bodies are updated + // that are cached as per-body data + + switch (keyword) { + case X: + case Y: + case Z: + case MOLECULE: + case MASS: + case ANGMOM: + case SHAPE: + case DIAMETER: + case DENSITY: + case TEMPERATURE: + case QUAT: + case IMAGE: + if (modify->check_rigid_list_overlap(select)) + error->warning(FLERR,"Changing a property of atoms in rigid bodies " + "that has no effect unless rigid bodies are re-initialized"); + break; + default: // assume no conflict for all other properties + break; + } + + // clear up per-atom memory if allocated + + memory->destroy(vec1); + memory->destroy(vec2); + memory->destroy(vec3); + memory->destroy(vec4); +} + +/* ---------------------------------------------------------------------- + set an owned atom property randomly + set seed based on atom coordinates + make atom result independent of what proc owns it +------------------------------------------------------------------------- */ + +void Set2::setrandom(int keyword) +{ + int i; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_line = dynamic_cast(atom->style_match("line")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + auto avec_body = dynamic_cast(atom->style_match("body")); + + double **x = atom->x; + int seed = ivalue; + + auto ranpark = new RanPark(lmp,1); + auto ranmars = new RanMars(lmp,seed + comm->me); + + // set approx fraction of atom types to newtype + + if (keyword == TYPE_FRACTION) { + int nlocal = atom->nlocal; + + for (i = 0; i < nlocal; i++) + if (select[i]) { + ranpark->reset(seed,x[i]); + if (ranpark->uniform() > fraction) continue; + atom->type[i] = newtype; + count++; + } + + // set exact count of atom types to newtype + // for TYPE_RATIO, exact = fraction out of total eligible + // for TYPE_SUBSET, exact = nsubset out of total eligible + + } else if (keyword == TYPE_RATIO || keyword == TYPE_SUBSET) { + int nlocal = atom->nlocal; + + // count = number of eligible atoms I own + + count = 0; + for (i = 0; i < nlocal; i++) + if (select[i]) count++; + + // convert specified fraction to nsubset + + bigint bcount = count; + bigint allcount; + MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); + + if (keyword == TYPE_RATIO) { + nsubset = static_cast (fraction * allcount); + } else if (keyword == TYPE_SUBSET) { + if (nsubset > allcount) + error->all(FLERR,"Set type/subset value exceeds eligible atoms"); + } + + // make selection + + int *flag = memory->create(flag,count,"set:flag"); + int *work = memory->create(work,count,"set:work"); + + ranmars->select_subset(nsubset,count,flag,work); + + // change types of selected atoms + // flag vector from select_subset() is only for eligible atoms + + count = 0; + int eligible = 0; + for (i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (flag[eligible]) { + atom->type[i] = newtype; + count++; + } + eligible++; + } + + // clean up + + memory->destroy(flag); + memory->destroy(work); + + // set dipole moments to random orientations in 3d or 2d + // dipole length is determined by dipole type array + + } else if (keyword == DIPOLE_RANDOM) { + double **mu = atom->mu; + int nlocal = atom->nlocal; + + double msq,scale; + + if (domain->dimension == 3) { + for (i = 0; i < nlocal; i++) + if (select[i]) { + ranpark->reset(seed,x[i]); + mu[i][0] = ranpark->uniform() - 0.5; + mu[i][1] = ranpark->uniform() - 0.5; + mu[i][2] = ranpark->uniform() - 0.5; + msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]; + scale = dvalue/sqrt(msq); + mu[i][0] *= scale; + mu[i][1] *= scale; + mu[i][2] *= scale; + mu[i][3] = dvalue; + count++; + } + + } else { + for (i = 0; i < nlocal; i++) + if (select[i]) { + ranpark->reset(seed,x[i]); + mu[i][0] = ranpark->uniform() - 0.5; + mu[i][1] = ranpark->uniform() - 0.5; + mu[i][2] = 0.0; + msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1]; + scale = dvalue/sqrt(msq); + mu[i][0] *= scale; + mu[i][1] *= scale; + mu[i][3] = dvalue; + count++; + } + } + + + // set spin moments to random orientations in 3d or 2d + // spin length is fixed to unity + + } else if (keyword == SPIN_RANDOM) { + double **sp = atom->sp; + int nlocal = atom->nlocal; + + double sp_sq,scale; + + if (domain->dimension == 3) { + for (i = 0; i < nlocal; i++) + if (select[i]) { + ranpark->reset(seed,x[i]); + sp[i][0] = ranpark->uniform() - 0.5; + sp[i][1] = ranpark->uniform() - 0.5; + sp[i][2] = ranpark->uniform() - 0.5; + sp_sq = sp[i][0]*sp[i][0] + sp[i][1]*sp[i][1] + sp[i][2]*sp[i][2]; + scale = 1.0/sqrt(sp_sq); + sp[i][0] *= scale; + sp[i][1] *= scale; + sp[i][2] *= scale; + sp[i][3] = dvalue; + count++; + } + + } else { + for (i = 0; i < nlocal; i++) + if (select[i]) { + ranpark->reset(seed,x[i]); + sp[i][0] = ranpark->uniform() - 0.5; + sp[i][1] = ranpark->uniform() - 0.5; + sp[i][2] = 0.0; + sp_sq = sp[i][0]*sp[i][0] + sp[i][1]*sp[i][1]; + scale = 1.0/sqrt(sp_sq); + sp[i][0] *= scale; + sp[i][1] *= scale; + sp[i][3] = dvalue; + count++; + } + } + + // set quaternions to random orientations in 3d and 2d + + } else if (keyword == QUAT_RANDOM) { + int nlocal = atom->nlocal; + double *quat; + double **quat2; + + if (domain->dimension == 3) { + double s,t1,t2,theta1,theta2; + for (i = 0; i < nlocal; i++) + if (select[i]) { + if (avec_ellipsoid && atom->ellipsoid[i] >= 0) + quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; + else if (avec_tri && atom->tri[i] >= 0) + quat = avec_tri->bonus[atom->tri[i]].quat; + else if (avec_body && atom->body[i] >= 0) + quat = avec_body->bonus[atom->body[i]].quat; + else if (atom->quat_flag) + quat2 = atom->quat; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + + ranpark->reset(seed,x[i]); + s = ranpark->uniform(); + t1 = sqrt(1.0-s); + t2 = sqrt(s); + theta1 = 2.0*MY_PI*ranpark->uniform(); + theta2 = 2.0*MY_PI*ranpark->uniform(); + if (atom->quat_flag) { + quat2[i][0] = cos(theta2)*t2; + quat2[i][1] = sin(theta1)*t1; + quat2[i][2] = cos(theta1)*t1; + quat2[i][3] = sin(theta2)*t2; + } else { + quat[0] = cos(theta2)*t2; + quat[1] = sin(theta1)*t1; + quat[2] = cos(theta1)*t1; + quat[3] = sin(theta2)*t2; + } + count++; + } + + } else { + double theta2; + for (i = 0; i < nlocal; i++) + if (select[i]) { + if (avec_ellipsoid && atom->ellipsoid[i] >= 0) + quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; + else if (avec_body && atom->body[i] >= 0) + quat = avec_body->bonus[atom->body[i]].quat; + else if (atom->quat_flag) + quat2 = atom->quat; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + + ranpark->reset(seed,x[i]); + theta2 = MY_PI*ranpark->uniform(); + if (atom->quat_flag) { + quat2[i][0] = cos(theta2); + quat2[i][1] = 0.0; + quat2[i][2] = 0.0; + quat2[i][3] = sin(theta2); + } else { + quat[0] = cos(theta2); + quat[1] = 0.0; + quat[2] = 0.0; + quat[3] = sin(theta2); + } + count++; + } + } + + // set theta to random orientation in 2d + + } else if (keyword == THETA_RANDOM) { + int nlocal = atom->nlocal; + for (i = 0; i < nlocal; i++) { + if (select[i]) { + if (atom->line[i] < 0) + error->one(FLERR,"Cannot set theta for atom that is not a line"); + ranpark->reset(seed,x[i]); + avec_line->bonus[atom->line[i]].theta = MY_2PI*ranpark->uniform(); + count++; + } + } + } + + delete ranpark; + delete ranmars; +} + +/* ---------------------------------------------------------------------- */ + +void Set2::topology(int keyword) +{ + int m,atom1,atom2,atom3,atom4; + + // error check + + if (atom->molecular == Atom::TEMPLATE) + error->all(FLERR,"Cannot set bond topology types for atom style template"); + + // border swap to acquire ghost atom info + // enforce PBC before in case atoms are outside box + // init entire system since comm->exchange is done + // comm::init needs neighbor::init needs pair::init needs kspace::init, etc + + if (comm->me == 0) utils::logmesg(lmp," system init for set ...\n"); + lmp->init(); + + if (domain->triclinic) domain->x2lamda(atom->nlocal); + domain->pbc(); + domain->reset_box(); + comm->setup(); + comm->exchange(); + comm->borders(); + if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); + + // select both owned and ghost atoms + + selection(atom->nlocal + atom->nghost); + + // for BOND, each of 2 atoms must be in group + + if (keyword == BOND) { + int nlocal = atom->nlocal; + for (int i = 0; i < nlocal; i++) + for (m = 0; m < atom->num_bond[i]; m++) { + atom1 = atom->map(atom->bond_atom[i][m]); + if (atom1 == -1) error->one(FLERR,"Bond atom missing in set command"); + if (select[i] && select[atom1]) { + atom->bond_type[i][m] = ivalue; + count++; + } + } + } + + // for ANGLE, each of 3 atoms must be in group + + if (keyword == ANGLE) { + int nlocal = atom->nlocal; + for (int i = 0; i < nlocal; i++) + for (m = 0; m < atom->num_angle[i]; m++) { + atom1 = atom->map(atom->angle_atom1[i][m]); + atom2 = atom->map(atom->angle_atom2[i][m]); + atom3 = atom->map(atom->angle_atom3[i][m]); + if (atom1 == -1 || atom2 == -1 || atom3 == -1) + error->one(FLERR,"Angle atom missing in set command"); + if (select[atom1] && select[atom2] && select[atom3]) { + atom->angle_type[i][m] = ivalue; + count++; + } + } + } + + // for DIHEDRAL, each of 4 atoms must be in group + + if (keyword == DIHEDRAL) { + int nlocal = atom->nlocal; + for (int i = 0; i < nlocal; i++) + for (m = 0; m < atom->num_dihedral[i]; m++) { + atom1 = atom->map(atom->dihedral_atom1[i][m]); + atom2 = atom->map(atom->dihedral_atom2[i][m]); + atom3 = atom->map(atom->dihedral_atom3[i][m]); + atom4 = atom->map(atom->dihedral_atom4[i][m]); + if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) + error->one(FLERR,"Dihedral atom missing in set command"); + if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { + atom->dihedral_type[i][m] = ivalue; + count++; + } + } + } + + // for IMPROPER, each of 4 atoms must be in group + + if (keyword == IMPROPER) { + int nlocal = atom->nlocal; + for (int i = 0; i < nlocal; i++) + for (m = 0; m < atom->num_improper[i]; m++) { + atom1 = atom->map(atom->improper_atom1[i][m]); + atom2 = atom->map(atom->improper_atom2[i][m]); + atom3 = atom->map(atom->improper_atom3[i][m]); + atom4 = atom->map(atom->improper_atom4[i][m]); + if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) + error->one(FLERR,"Improper atom missing in set command"); + if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { + atom->improper_type[i][m] = ivalue; + count++; + } + } + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::varparse(const char *name, int m) +{ + varflag = 1; + int ivar = input->variable->find(name+2); + + if (ivar < 0) + error->all(FLERR,"Variable name {} for set command does not exist", name); + if (!input->variable->atomstyle(ivar)) + error->all(FLERR,"Variable {} for set command is invalid style", name); + + if (m == 1) { + varflag1 = 1; ivar1 = ivar; + } else if (m == 2) { + varflag2 = 1; ivar2 = ivar; + } else if (m == 3) { + varflag3 = 1; ivar3 = ivar; + } else if (m == 4) { + varflag4 = 1; ivar4 = ivar; + } +} + +// ---------------------------------------------------------------------- +// pairs of process/invoke methods for each keyword +// process method reads args, stores parameters in Action instance +// invoke method resets atoms properties using Action instance +// separate two operations so can be called by either set or fix set command +// ---------------------------------------------------------------------- + +void Set2::process_type(int &iarg, int narg, char **arg) +{ + 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 { + 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; + } + iarg += 2; +} + +void Set2::invoke_type() +{ + int nlocal = atom->nlocal; + int *type = atom->type; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) + if (ivalue <= 0 || ivalue > atom->ntypes) + error->one(FLERR,"Invalid value in set command"); + type[i] = ivalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_type_fraction(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); + 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) + error->all(FLERR,"Invalid type value {} in set type/fraction command", newtype); + if (fraction < 0.0 || fraction > 1.0) + error->all(FLERR,"Invalid fraction value {} in set type/fraction command", fraction); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed {} in set type/fraction command", ivalue); + iarg += 4; +} + +void Set2::invoke_type_fraction() +{ + setrandom(TYPE_FRACTION); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_type_ratio(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error); + 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) + error->all(FLERR,"Invalid type value {} in set type/ratio command", newtype); + if (fraction < 0.0 || fraction > 1.0) + error->all(FLERR,"Invalid fraction value {} in set type/ratio command", fraction); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed {} in set type/ratio command", ivalue); + iarg += 4; +} + +void Set2::invoke_type_ratio() +{ + setrandom(TYPE_RATIO); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_type_subset(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error); + 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) + error->all(FLERR,"Invalid type value {} in set type/subset command", newtype); + if (nsubset < 0) + error->all(FLERR,"Invalid subset size {} in set type/subset command", nsubset); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed {} in set type/subset command", ivalue); + iarg += 4; +} + +void Set2::invoke_type_subset() +{ + setrandom(TYPE_SUBSET); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_mol(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->molecule_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_mol() +{ + int nlocal = atom->nlocal; + int *molecule = atom->molecule; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + molecule[i] = ivalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_x(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; +} + +void Set2::invoke_x() +{ + int nlocal = atom->nlocal; + double **x = atom->x; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + x[i][0] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_y(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; +} + +void Set2::invoke_y() +{ + int nlocal = atom->nlocal; + double **x = atom->x; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + x[i][1] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_z(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; +} + +void Set2::invoke_z() +{ + int nlocal = atom->nlocal; + double **x = atom->x; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + x[i][2] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_vx(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vx", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; +} + +void Set2::invoke_vx() +{ + int nlocal = atom->nlocal; + double **v = atom->v; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + v[i][0] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_vy(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vy", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; +} + +void Set2::invoke_vy() +{ + int nlocal = atom->nlocal; + double **v = atom->v; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + v[i][1] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_vz(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vz", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; +} + +void Set2::invoke_vz() +{ + int nlocal = atom->nlocal; + double **v = atom->v; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + v[i][2] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_charge(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->q_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_charge() +{ + int nlocal = atom->nlocal; + double *q = atom->q; + double *q_scaled = atom->q_scaled; + double *epsilon = atom->epsilon; + + // ensure that scaled charges are consistent the new charge value + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + q[i] = dvalue; + if (epsilon) q_scaled[i] = dvalue / epsilon[i]; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_mass(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rmass_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_mass() +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue <= 0.0) error->one(FLERR,"Invalid mass in set command"); + rmass[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_shape(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->ellipsoid_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_shape() +{ + int nlocal = atom->nlocal; + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) + error->one(FLERR,"Invalid shape in set command"); + if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) { + if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) + error->one(FLERR,"Invalid shape in set command"); + } + avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); + } + + // update global ellipsoid count + + bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->nellipsoids,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_length(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_length() +{ + int nlocal = atom->nlocal; + auto avec_line = dynamic_cast(atom->style_match("line")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid length in set command"); + avec_line->set_length(i,dvalue); + } + + // update global line count + + bigint nlocal_bonus = avec_line->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->nlines,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_tri(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->tri_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_tri() +{ + int nlocal = atom->nlocal; + auto avec_tri = dynamic_cast(atom->style_match("tri")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid tri size in set command"); + avec_tri->set_equilateral(i,dvalue); + } + + // update bonus tri count + + bigint nlocal_bonus = avec_tri->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dipole(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->mu_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_dipole() +{ + int nlocal = atom->nlocal; + double **mu = atom->mu; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + mu[i][0] = xvalue; + mu[i][1] = yvalue; + mu[i][2] = zvalue; + mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dipole_random(int &iarg, int narg, char **arg) +{ + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (!atom->mu_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + if (dvalue <= 0.0) + error->all(FLERR,"Invalid dipole length in set command"); + iarg += 3; +} + +void Set2::invoke_dipole_random() +{ + setrandom(DIPOLE_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_spin_atom(int &iarg, int narg, char **arg) +{ + if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin is deprecated. Please use spin/atom instead."); + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else xvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else yvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); + else zvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); + if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) + error->all(FLERR,"At least one spin vector component must be non-zero"); + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (dvalue <= 0.0) + error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + iarg += 5; +} + +void Set2::invoke_spin_atom() +{ + int nlocal = atom->nlocal; + double **sp = atom->sp; + + double norm; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) + error->one(FLERR,"Incorrect value for atomic spin magnitude: {}", dvalue); + norm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); + sp[i][0] = norm*xvalue; + sp[i][1] = norm*yvalue; + sp[i][2] = norm*zvalue; + sp[i][3] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) +{ + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin/random is deprecated. " + "Please use spin/atom/random instead."); + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed {} in set {} command", ivalue, arg[iarg]); + if (dvalue <= 0.0) + error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + iarg += 3; +} + +void Set2::invoke_spin_atom_random() +{ + setrandom(SPIN_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_radius_election(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->eradius_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_radius_election() +{ + int nlocal = atom->nlocal; + double *eradius = atom->eradius; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) + error->one(FLERR,"Incorrect value for electron radius: {}", dvalue); + eradius[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_spin_electron(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->spin_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_spin_electron() +{ + int nlocal = atom->nlocal; + int *spin = atom->spin; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (ivalue < -1 || ivalue > 3) + error->one(FLERR,"Incorrect value for electron spin: {}", ivalue); + atom->spin[i] = ivalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_quat(int &iarg, int narg, char **arg) +{ + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); + else wvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); + if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 5; +} + +void Set2::invoke_quat() +{ + int nlocal = atom->nlocal; + int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; + int *body = atom->body; + double **quat = atom->quat; + int quat_flag = atom->quat_flag; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + auto avec_body = dynamic_cast(atom->style_match("body")); + + int dimension = domain->dimension; + double theta2,sintheta2; + double *quat_one; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_tri && tri[i] >= 0) + quat_one = avec_tri->bonus[tri[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + + // quat rotation vector must be only in z dir for 2d systems + + if (dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + + theta2 = MY_PI2 * wvalue/180.0; + sintheta2 = sin(theta2); + quat_one[0] = cos(theta2); + quat_one[1] = xvalue * sintheta2; + quat_one[2] = yvalue * sintheta2; + quat_one[3] = zvalue * sintheta2; + MathExtra::qnormalize(quat_one); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_quat_random(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 2; +} + +void Set2::invoke_quat_random() +{ + setrandom(QUAT_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_theta(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_theta() +{ + int nlocal = atom->nlocal; + int *line = atom->line; + + auto avec_line = dynamic_cast(atom->style_match("line")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (line[i] < 0) + error->one(FLERR,"Cannot set theta for atom that is not a line"); + avec_line->bonus[atom->line[i]].theta = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_theta_random(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 2; +} + +void Set2::invoke_theta_random() +{ + set(THETA_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_angmom(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->angmom_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_angmom() +{ + int nlocal = atom->nlocal; + double **angmom = atom->angmom; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + angmom[i][0] = xvalue; + angmom[i][1] = yvalue; + angmom[i][2] = zvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_omega(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->omega_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_omega() +{ + int nlocal = atom->nlocal; + double **omega = atom->angmom; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + omega[i][0] = xvalue; + omega[i][1] = yvalue; + omega[i][2] = zvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_diameter(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->radius_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_diameter() +{ + int nlocal = atom->nlocal; + double *radius = atom->radius; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); + radius[i] = 0.5 * dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_density(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rmass_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (dvalue <= 0.0) error->all(FLERR,"Invalid density in set command"); + discflag = 0; + if (strcmp(arg[iarg],"density/disc") == 0) { + discflag = 1; + if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); + } + iarg += 2; +} + +void Set2::invoke_density() +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + double *radius = atom->radius; + int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; + + int radius_flag = atom->radius_flag; + int ellipsoid_flag = atom->ellipsoid_flag; + int line_flag = atom->line_flag; + int tri_flag = atom->tri_flag; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_line = dynamic_cast(atom->style_match("line")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + + // set rmass via density + // if radius > 0.0, treat as sphere or disc + // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) + // if length > 0.0, treat as line + // if area > 0.0, treat as tri + // else set rmass to density directly + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue <= 0.0) error->one(FLERR,"Invalid density in set command"); + if (radius_flag && radius[i] > 0.0) + if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * dvalue; + else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * dvalue; + else if (ellipsoid_flag && ellipsoid[i] >= 0) { + double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; + // enable 2d ellipse (versus 3d ellipsoid) when time integration + // options (fix nve/asphere, fix nh/asphere) are also implemented + // if (discflag) + // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; + // else + rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue; + } else if (line_flag && line[i] >= 0) { + double length = avec_line->bonus[line[i]].length; + rmass[i] = length * dvalue; + } else if (tri_flag && tri[i] >= 0) { + double *c1 = avec_tri->bonus[tri[i]].c1; + double *c2 = avec_tri->bonus[tri[i]].c2; + double *c3 = avec_tri->bonus[tri[i]].c3; + double c2mc1[3],c3mc1[3]; + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c1,c3mc1); + double norm[3]; + MathExtra::cross3(c2mc1,c3mc1,norm); + double area = 0.5 * MathExtra::len3(norm); + rmass[i] = area * dvalue; + } else rmass[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_temperature(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->temperature_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + iarg += 2; +} + +void Set2::invoke_temperature() +{ + int nlocal = atom->nlocal; + double *temperature = atom->temperature; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid temperature in set command"); + temperature[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_volume(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->vfrac_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (dvalue <= 0.0) error->all(FLERR,"Invalid volume in set command"); + iarg += 2; +} + +void Set2::invoke_volume() +{ + int nlocal = atom->nlocal; + double *vfrac = atom->vfrac; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); + vfrac[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_image(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); + ximageflag = yimageflag = zimageflag = 0; + if (strcmp(arg[iarg+1],"NULL") != 0) { + ximageflag = 1; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ximage = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + } + if (strcmp(arg[iarg+2],"NULL") != 0) { + yimageflag = 1; + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yimage = utils::inumeric(FLERR,arg[iarg+2],false,lmp); + } + if (strcmp(arg[iarg+3],"NULL") != 0) { + zimageflag = 1; + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zimage = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + } + if (ximageflag && ximage && !domain->xperiodic) + error->all(FLERR, + "Cannot set non-zero image flag for non-periodic dimension"); + if (yimageflag && yimage && !domain->yperiodic) + error->all(FLERR, + "Cannot set non-zero image flag for non-periodic dimension"); + if (zimageflag && zimage && !domain->zperiodic) + error->all(FLERR, + "Cannot set non-zero image flag for non-periodic dimension"); + iarg += 4; +} + +void Set2::invoke_image() +{ + int nlocal = atom->nlocal; + imageint *image = atom->image; + + int xbox,ybox,zbox; + + // reset any or all of 3 image flags + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + xbox = (image[i] & IMGMASK) - IMGMAX; + ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; + zbox = (image[i] >> IMG2BITS) - IMGMAX; + if (varflag1) ximage = static_cast(xvalue); + if (varflag2) yimage = static_cast(yvalue); + if (varflag3) zimage = static_cast(zvalue); + if (ximageflag) xbox = ximage; + if (yimageflag) ybox = yimage; + if (zimageflag) zbox = zimage; + image[i] = ((imageint) (xbox + IMGMAX) & IMGMASK) | + (((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) | + (((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_bond(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_bond() +{ + topology(BOND); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_angle(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_angle() +{ + topology(ANGLE); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dihedral(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_dihedral() +{ + topology(DIHEDRAL); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_improper(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_improper() +{ + topology(IMPROPER); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_sph_e(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->esph_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_sph_e() +{ + int nlocal = atom->nlocal; + double *esph = atom->esph; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + esph[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_sph_cv(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->cv_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_sph_cv() +{ + int nlocal = atom->nlocal; + double *cv = atom->cv; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + cv[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_sph_rho(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rho_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_sph_rho() +{ + int nlocal = atom->nlocal; + double *rho = atom->rho; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + rho[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_edpd_temp(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_edpd_temp() +{ + int nlocal = atom->nlocal; + double *edpd_temp = atom->edpd_temp; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + edpd_temp[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_edpd_cv(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_edpd_cv() +{ + int nlocal = atom->nlocal; + double *edpd_cv = atom->edpd_cv; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + edpd_cv[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_cc(int &iarg, int narg, char **arg) +{ + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); + // NOTE: seems like error to not set cc_index for all 3 cases + // syntax is iarg+1 is index, iarg+2 is value + // doc page does not talk about NULL as valid value + // check package DPD-MESO package examples for tDPD for use of this command + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + cc_index = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (cc_index < 1) error->all(FLERR,"Illegal set command"); + } + if (!atom->tdpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 3; +} + +void Set2::invoke_cc() +{ + int nlocal = atom->nlocal; + double **cc = atom->cc; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + cc[i][cc_index-1] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_smd_mass_density(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->smd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_smd_mass_density() +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + double *vfrac = atom->vfrac; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + // set mass from volume and supplied mass density + rmass[i] = vfrac[i] * dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->smd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_smd_contact_radius() +{ + int nlocal = atom->nlocal; + double *contact_radius = atom->contact_radius; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + contact_radius[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dpd_theta(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->dpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_dpd_theta() +{ + int nlocal = atom->nlocal; + int *type = atom->type; + double **v = atom->v; + double *mass = atom->mass; + double *rmass = atom->rmass; + double *dpdTheta = atom->dpdTheta; + + double tfactor = force->mvv2e / (domain->dimension * force->boltz); + double onemass; + double vx,vy,vz; + + // VARIABLE option or NULL to set temp to KE of particle + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (dvalue >= 0.0) dpdTheta[i] = dvalue; + else { + if (rmass) onemass = rmass[i]; + else onemass = mass[type[i]]; + vx = v[i][0]; + vy = v[i][1]; + vz = v[i][2]; + dpdTheta[i] = tfactor * onemass * (vx*vx + vy*vy + vz*vz); + } + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_epsilon(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->dielectric_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_epsilon() +{ + int nlocal = atom->nlocal; + double *epsilon = atom->epsilon; + double *q = atom->q; + double *q_scaled = atom->q_scaled; + + // assign local dielectric constant + // also update scaled charge value + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + // NOTE: should it be error if dvalue < 0.0 ? + if (dvalue >= 0.0) { + epsilon[i] = dvalue; + q_scaled[i] = q[i] / dvalue; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_custom(int &iarg, int narg, char **arg) +{ + int flag,cols; + ArgInfo argi(arg[iarg],ArgInfo::DNAME|ArgInfo::INAME); + const char *pname = argi.get_name(); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set", error); + index_custom = atom->find_custom(argi.get_name(),flag,cols); + if (index_custom < 0) + error->all(FLERR,"Set keyword or custom property {} does not exist",pname); + + switch (argi.get_type()) { + + case ArgInfo::INAME: + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (flag != 0) error->all(FLERR,"Set command custom property {} is not integer",pname); + + if (argi.get_dim() == 0) { + if (cols > 0) + error->all(FLERR,"Set command custom integer property {} is not a vector",pname); + custom_flag = IVEC; + } else if (argi.get_dim() == 1) { + if (cols == 0) + error->all(FLERR,"Set command custom integer property {} is not an array",pname); + icol_custom = argi.get_index1(); + if (icol_custom <= 0 || icol_custom > cols) + error->all(FLERR,"Set command per-atom custom integer array {} is accessed " + "out-of-range",pname); + custom_flag = IARRAY; + } else error->all(FLERR,"Illegal set command"); + break; + + case ArgInfo::DNAME: + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (flag != 1) error->all(FLERR,"Custom property {} is not floating-point",argi.get_name()); + + if (argi.get_dim() == 0) { + if (cols > 0) + error->all(FLERR,"Set command custom double property {} is not a vector",pname); + custom_flag = DVEC; + } else if (argi.get_dim() == 1) { + if (cols == 0) + error->all(FLERR,"Set command custom double property {} is not an array",pname); + icol_custom = argi.get_index1(); + if (icol_custom <= 0 || icol_custom > cols) + error->all(FLERR,"Set command per-atom custom double array {} is " + "accessed out-of-range",pname); + custom_flag = DARRAY; + } else error->all(FLERR,"Illegal set command"); + break; + + default: + error->all(FLERR,"Illegal set command"); + break; + } + + iarg += 2; +} + +void Set2::invoke_custom() +{ + int nlocal = atom->nlocal; + + // VARIABLE option + + if (custom_flag == IVEC) { + int *ivector = atom->ivector[index_custom]; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + ivector[i] = ivalue; + } + } else if (custom_flag == DVEC) { + double *dvector = atom->dvector[index_custom]; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + dvector[i] = dvalue; + } + } else if (custom_flag == IARRAY) { + int **iarray = atom->iarray[index_custom]; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + iarray[i][icol_custom-1] = ivalue; + } + } else if (custom_flag == DARRAY) { + double **darray = atom->darray[index_custom]; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + darray[i][icol_custom-1] = dvalue; + } + } +} diff --git a/src/set2.h b/src/set2.h new file mode 100644 index 0000000000..4a303e6cc4 --- /dev/null +++ b/src/set2.h @@ -0,0 +1,186 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef COMMAND_CLASS +// clang-format off +CommandStyle(set2,Set2); +// clang-format on +#else + +#ifndef LMP_SET2_H +#define LMP_SET2_H + +#include "command.h" + +namespace LAMMPS_NS { + +class Set2 : public Command { + public: + Set2(class LAMMPS *lmp) : Command(lmp){}; + void command(int, char **) override; + + private: + int style; + char *id; + int nlo,nhi; + bigint nlobig,nhibig; + int groupbit; + class Region *region; + + int caller; + + struct Action { + + }; + + int naction,maxaction; + Action *actions; + + int *select; + + typedef void (Set2::*FnPtrPack)(); + FnPtrPack *invoke_choice; // list of ptrs to invoke functions + + + int ivalue, newtype, count, index_custom, icol_custom; + int ximage, yimage, zimage, ximageflag, yimageflag, zimageflag; + int cc_index; + bigint nsubset; + double dvalue, xvalue, yvalue, zvalue, wvalue, fraction; + + int varflag, varflag1, varflag2, varflag3, varflag4; + int ivar1, ivar2, ivar3, ivar4; + double *vec1, *vec2, *vec3, *vec4; + + int custom_flag; + int discflag; + + void process_args(int, int, char **); + void invoke_actions(); + + void selection(int); + void set(int); + void setrandom(int); + void topology(int); + void varparse(const char *, int); + + // customize by adding a process method prototype + + void process_angle(int &, int, char **); + void process_angmom(int &, int, char **); + void process_bond(int &, int, char **); + void process_cc(int &, int, char **); + void process_charge(int &, int, char **); + void process_density(int &, int, char **); + void process_diameter(int &, int, char **); + void process_dihedral(int &, int, char **); + void process_dipole(int &, int, char **); + void process_dipole_random(int &, int, char **); + void process_dpd_theta(int &, int, char **); + void process_edpd_cv(int &, int, char **); + void process_edpd_temp(int &, int, char **); + void process_epsilon(int &, int, char **); + void process_image(int &, int, char **); + void process_improper(int &, int, char **); + void process_length(int &, int, char **); + void process_mass(int &, int, char **); + void process_mol(int &, int, char **); + void process_omega(int &, int, char **); + void process_quat(int &, int, char **); + void process_quat_random(int &, int, char **); + void process_radius_election(int &, int, char **); + void process_shape(int &, int, char **); + void process_smd_contact_radius(int &, int, char **); + void process_smd_mass_density(int &, int, char **); + void process_sph_cv(int &, int, char **); + void process_sph_e(int &, int, char **); + void process_sph_rho(int &, int, char **); + void process_spin_atom(int &, int, char **); + void process_spin_atom_random(int &, int, char **); + void process_spin_electron(int &, int, char **); + void process_temperature(int &, int, char **); + void process_theta(int &, int, char **); + void process_theta_random(int &, int, char **); + void process_tri(int &, int, char **); + void process_type(int &, int, char **); + void process_type_fraction(int &, int, char **); + void process_type_ratio(int &, int, char **); + void process_type_subset(int &, int, char **); + void process_volume(int &, int, char **); + void process_vx(int &, int, char **); + void process_vy(int &, int, char **); + void process_vz(int &, int, char **); + void process_x(int &, int, char **); + void process_y(int &, int, char **); + void process_z(int &, int, char **); + + void process_custom(int &, int, char **); + + // customize by adding an invoke method prototype + + void invoke_angle(); + void invoke_angmom(); + void invoke_bond(); + void invoke_cc(); + void invoke_charge(); + void invoke_density(); + void invoke_diameter(); + void invoke_dihedral(); + void invoke_dipole(); + void invoke_dipole_random(); + void invoke_dpd_theta(); + void invoke_edpd_cv(); + void invoke_edpd_temp(); + void invoke_epsilon(); + void invoke_image(); + void invoke_improper(); + void invoke_length(); + void invoke_mass(); + void invoke_mol(); + void invoke_omega(); + void invoke_quat(); + void invoke_quat_random(); + void invoke_radius_election(); + void invoke_shape(); + void invoke_smd_contact_radius(); + void invoke_smd_mass_density(); + void invoke_sph_cv(); + void invoke_sph_e(); + void invoke_sph_rho(); + void invoke_spin_atom(); + void invoke_spin_atom_random(); + void invoke_spin_electron(); + void invoke_temperature(); + void invoke_theta(); + void invoke_theta_random(); + void invoke_tri(); + void invoke_type(); + void invoke_type_fraction(); + void invoke_type_ratio(); + void invoke_type_subset(); + void invoke_volume(); + void invoke_vx(); + void invoke_vy(); + void invoke_vz(); + void invoke_x(); + void invoke_y(); + void invoke_z(); + + void invoke_custom(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif + From ee0a050f6544f1fe797c4c2bd36a1979355408ff Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Sat, 25 Nov 2023 15:46:15 -0700 Subject: [PATCH 02/26] alphabetize methods --- src/set2.cpp | 2310 +++++++++++++++++++++++++------------------------- 1 file changed, 1154 insertions(+), 1156 deletions(-) diff --git a/src/set2.cpp b/src/set2.cpp index 6055f83ad0..7a79768a8a 100644 --- a/src/set2.cpp +++ b/src/set2.cpp @@ -46,13 +46,13 @@ enum{SET,FIXSET}; enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; -enum{TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET, - MOLECULE,X,Y,Z,VX,VY,VZ,CHARGE,MASS,SHAPE,LENGTH,TRI, - DIPOLE,DIPOLE_RANDOM,SPIN_ATOM,SPIN_RANDOM,SPIN_ELECTRON,RADIUS_ELECTRON, - QUAT,QUAT_RANDOM,THETA,THETA_RANDOM,ANGMOM,OMEGA,TEMPERATURE, - DIAMETER,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER, - SPH_E,SPH_CV,SPH_RHO,EDPD_TEMP,EDPD_CV,CC,SMD_MASS_DENSITY, - SMD_CONTACT_RADIUS,DPDTHETA,EPSILON,IVEC,DVEC,IARRAY,DARRAY}; +enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, + DIPOLE_RANDOM,DPDTHETA,EDPD_CV,EDPD_TEMP,EPSILON,IMAGE,IMPROPER,LENGTH, + MASS,MOLECULE,OMEGA,QUAT,QUAT_RANDOM,RADIUS_ELECTRON,SHAPE, + SMD_CONTACT_RADIUS,SMD_MASS_DENSITY,SPH_CV,SPH_E,SPH_RHO, + SPIN_ATOM,SPIN_ELECTRON,SPIN_RANDOM,TEMPERATURE,THETA,THETA_RANDOM, + TRI,TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET,VOLUME,VX,VY,VZ,X,Y,Z, + IVEC,DVEC,IARRAY,DARRAY}; #define BIG INT_MAX #define DELTA 4 @@ -843,6 +843,1127 @@ void Set2::varparse(const char *name, int m) // separate two operations so can be called by either set or fix set command // ---------------------------------------------------------------------- +void Set2::process_angle(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_angle() +{ + topology(ANGLE); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_angmom(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->angmom_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_angmom() +{ + int nlocal = atom->nlocal; + double **angmom = atom->angmom; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + angmom[i][0] = xvalue; + angmom[i][1] = yvalue; + angmom[i][2] = zvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_bond(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_bond() +{ + topology(BOND); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_cc(int &iarg, int narg, char **arg) +{ + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); + // NOTE: seems like error to not set cc_index for all 3 cases + // syntax is iarg+1 is index, iarg+2 is value + // doc page does not talk about NULL as valid value + // check package DPD-MESO package examples for tDPD for use of this command + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + cc_index = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (cc_index < 1) error->all(FLERR,"Illegal set command"); + } + if (!atom->tdpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 3; +} + +void Set2::invoke_cc() +{ + int nlocal = atom->nlocal; + double **cc = atom->cc; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + cc[i][cc_index-1] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_charge(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->q_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_charge() +{ + int nlocal = atom->nlocal; + double *q = atom->q; + double *q_scaled = atom->q_scaled; + double *epsilon = atom->epsilon; + + // ensure that scaled charges are consistent the new charge value + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + q[i] = dvalue; + if (epsilon) q_scaled[i] = dvalue / epsilon[i]; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_density(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rmass_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (dvalue <= 0.0) error->all(FLERR,"Invalid density in set command"); + discflag = 0; + if (strcmp(arg[iarg],"density/disc") == 0) { + discflag = 1; + if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); + } + iarg += 2; +} + +void Set2::invoke_density() +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + double *radius = atom->radius; + int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; + + int radius_flag = atom->radius_flag; + int ellipsoid_flag = atom->ellipsoid_flag; + int line_flag = atom->line_flag; + int tri_flag = atom->tri_flag; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_line = dynamic_cast(atom->style_match("line")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + + // set rmass via density + // if radius > 0.0, treat as sphere or disc + // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) + // if length > 0.0, treat as line + // if area > 0.0, treat as tri + // else set rmass to density directly + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue <= 0.0) error->one(FLERR,"Invalid density in set command"); + if (radius_flag && radius[i] > 0.0) + if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * dvalue; + else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * dvalue; + else if (ellipsoid_flag && ellipsoid[i] >= 0) { + double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; + // enable 2d ellipse (versus 3d ellipsoid) when time integration + // options (fix nve/asphere, fix nh/asphere) are also implemented + // if (discflag) + // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; + // else + rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue; + } else if (line_flag && line[i] >= 0) { + double length = avec_line->bonus[line[i]].length; + rmass[i] = length * dvalue; + } else if (tri_flag && tri[i] >= 0) { + double *c1 = avec_tri->bonus[tri[i]].c1; + double *c2 = avec_tri->bonus[tri[i]].c2; + double *c3 = avec_tri->bonus[tri[i]].c3; + double c2mc1[3],c3mc1[3]; + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c1,c3mc1); + double norm[3]; + MathExtra::cross3(c2mc1,c3mc1,norm); + double area = 0.5 * MathExtra::len3(norm); + rmass[i] = area * dvalue; + } else rmass[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_diameter(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->radius_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_diameter() +{ + int nlocal = atom->nlocal; + double *radius = atom->radius; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); + radius[i] = 0.5 * dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dihedral(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_dihedral() +{ + topology(DIHEDRAL); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dipole(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->mu_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_dipole() +{ + int nlocal = atom->nlocal; + double **mu = atom->mu; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + mu[i][0] = xvalue; + mu[i][1] = yvalue; + mu[i][2] = zvalue; + mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dipole_random(int &iarg, int narg, char **arg) +{ + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (!atom->mu_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + if (dvalue <= 0.0) + error->all(FLERR,"Invalid dipole length in set command"); + iarg += 3; +} + +void Set2::invoke_dipole_random() +{ + setrandom(DIPOLE_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_dpd_theta(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->dpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_dpd_theta() +{ + int nlocal = atom->nlocal; + int *type = atom->type; + double **v = atom->v; + double *mass = atom->mass; + double *rmass = atom->rmass; + double *dpdTheta = atom->dpdTheta; + + double tfactor = force->mvv2e / (domain->dimension * force->boltz); + double onemass; + double vx,vy,vz; + + // VARIABLE option or NULL to set temp to KE of particle + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (dvalue >= 0.0) dpdTheta[i] = dvalue; + else { + if (rmass) onemass = rmass[i]; + else onemass = mass[type[i]]; + vx = v[i][0]; + vy = v[i][1]; + vz = v[i][2]; + dpdTheta[i] = tfactor * onemass * (vx*vx + vy*vy + vz*vz); + } + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_edpd_cv(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_edpd_cv() +{ + int nlocal = atom->nlocal; + double *edpd_cv = atom->edpd_cv; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + edpd_cv[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_edpd_temp(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_edpd_temp() +{ + int nlocal = atom->nlocal; + double *edpd_temp = atom->edpd_temp; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + edpd_temp[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_epsilon(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + } + if (!atom->dielectric_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_epsilon() +{ + int nlocal = atom->nlocal; + double *epsilon = atom->epsilon; + double *q = atom->q; + double *q_scaled = atom->q_scaled; + + // assign local dielectric constant + // also update scaled charge value + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + // NOTE: should it be error if dvalue < 0.0 ? + if (dvalue >= 0.0) { + epsilon[i] = dvalue; + q_scaled[i] = q[i] / dvalue; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_image(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); + ximageflag = yimageflag = zimageflag = 0; + if (strcmp(arg[iarg+1],"NULL") != 0) { + ximageflag = 1; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ximage = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + } + if (strcmp(arg[iarg+2],"NULL") != 0) { + yimageflag = 1; + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yimage = utils::inumeric(FLERR,arg[iarg+2],false,lmp); + } + if (strcmp(arg[iarg+3],"NULL") != 0) { + zimageflag = 1; + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zimage = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + } + if (ximageflag && ximage && !domain->xperiodic) + error->all(FLERR, + "Cannot set non-zero image flag for non-periodic dimension"); + if (yimageflag && yimage && !domain->yperiodic) + error->all(FLERR, + "Cannot set non-zero image flag for non-periodic dimension"); + if (zimageflag && zimage && !domain->zperiodic) + error->all(FLERR, + "Cannot set non-zero image flag for non-periodic dimension"); + iarg += 4; +} + +void Set2::invoke_image() +{ + int nlocal = atom->nlocal; + imageint *image = atom->image; + + int xbox,ybox,zbox; + + // reset any or all of 3 image flags + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + xbox = (image[i] & IMGMASK) - IMGMAX; + ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; + zbox = (image[i] >> IMG2BITS) - IMGMAX; + if (varflag1) ximage = static_cast(xvalue); + if (varflag2) yimage = static_cast(yvalue); + if (varflag3) zimage = static_cast(zvalue); + if (ximageflag) xbox = ximage; + if (yimageflag) ybox = yimage; + if (zimageflag) zbox = zimage; + image[i] = ((imageint) (xbox + IMGMAX) & IMGMASK) | + (((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) | + (((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_improper(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); + 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) + error->all(FLERR,"Invalid value in set command"); + iarg += 2; +} + +void Set2::invoke_improper() +{ + topology(IMPROPER); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_length(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_length() +{ + int nlocal = atom->nlocal; + auto avec_line = dynamic_cast(atom->style_match("line")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid length in set command"); + avec_line->set_length(i,dvalue); + } + + // update global line count + + bigint nlocal_bonus = avec_line->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->nlines,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_mass(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rmass_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_mass() +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue <= 0.0) error->one(FLERR,"Invalid mass in set command"); + rmass[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_mol(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->molecule_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_mol() +{ + int nlocal = atom->nlocal; + int *molecule = atom->molecule; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + molecule[i] = ivalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_omega(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->omega_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_omega() +{ + int nlocal = atom->nlocal; + double **omega = atom->angmom; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + omega[i][0] = xvalue; + omega[i][1] = yvalue; + omega[i][2] = zvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_quat(int &iarg, int narg, char **arg) +{ + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); + else wvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); + if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 5; +} + +void Set2::invoke_quat() +{ + int nlocal = atom->nlocal; + int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; + int *body = atom->body; + double **quat = atom->quat; + int quat_flag = atom->quat_flag; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + auto avec_body = dynamic_cast(atom->style_match("body")); + + int dimension = domain->dimension; + double theta2,sintheta2; + double *quat_one; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_tri && tri[i] >= 0) + quat_one = avec_tri->bonus[tri[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + + // quat rotation vector must be only in z dir for 2d systems + + if (dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + + theta2 = MY_PI2 * wvalue/180.0; + sintheta2 = sin(theta2); + quat_one[0] = cos(theta2); + quat_one[1] = xvalue * sintheta2; + quat_one[2] = yvalue * sintheta2; + quat_one[3] = zvalue * sintheta2; + MathExtra::qnormalize(quat_one); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_quat_random(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 2; +} + +void Set2::invoke_quat_random() +{ + setrandom(QUAT_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_radius_election(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->eradius_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_radius_election() +{ + int nlocal = atom->nlocal; + double *eradius = atom->eradius; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) + error->one(FLERR,"Incorrect value for electron radius: {}", dvalue); + eradius[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_shape(int &iarg, int narg, char **arg) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (!atom->ellipsoid_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 4; +} + +void Set2::invoke_shape() +{ + int nlocal = atom->nlocal; + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) + error->one(FLERR,"Invalid shape in set command"); + if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) { + if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) + error->one(FLERR,"Invalid shape in set command"); + } + avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); + } + + // update global ellipsoid count + + bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->nellipsoids,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->smd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_smd_contact_radius() +{ + int nlocal = atom->nlocal; + double *contact_radius = atom->contact_radius; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + contact_radius[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_smd_mass_density(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->smd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_smd_mass_density() +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + double *vfrac = atom->vfrac; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + // set mass from volume and supplied mass density + rmass[i] = vfrac[i] * dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_sph_cv(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->cv_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_sph_cv() +{ + int nlocal = atom->nlocal; + double *cv = atom->cv; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + cv[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_sph_e(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->esph_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_sph_e() +{ + int nlocal = atom->nlocal; + double *esph = atom->esph; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + esph[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_sph_rho(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->rho_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_sph_rho() +{ + int nlocal = atom->nlocal; + double *rho = atom->rho; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + rho[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_spin_atom(int &iarg, int narg, char **arg) +{ + if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin is deprecated. Please use spin/atom instead."); + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else xvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else yvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); + else zvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); + if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) + error->all(FLERR,"At least one spin vector component must be non-zero"); + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (dvalue <= 0.0) + error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + iarg += 5; +} + +void Set2::invoke_spin_atom() +{ + int nlocal = atom->nlocal; + double **sp = atom->sp; + + double norm; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) + error->one(FLERR,"Incorrect value for atomic spin magnitude: {}", dvalue); + norm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); + sp[i][0] = norm*xvalue; + sp[i][1] = norm*yvalue; + sp[i][2] = norm*zvalue; + sp[i][3] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) +{ + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin/random is deprecated. " + "Please use spin/atom/random instead."); + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed {} in set {} command", ivalue, arg[iarg]); + if (dvalue <= 0.0) + error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + iarg += 3; +} + +void Set2::invoke_spin_atom_random() +{ + setrandom(SPIN_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_spin_electron(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->spin_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_spin_electron() +{ + int nlocal = atom->nlocal; + int *spin = atom->spin; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (ivalue < -1 || ivalue > 3) + error->one(FLERR,"Incorrect value for electron spin: {}", ivalue); + atom->spin[i] = ivalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_temperature(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->temperature_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + iarg += 2; +} + +void Set2::invoke_temperature() +{ + int nlocal = atom->nlocal; + double *temperature = atom->temperature; + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid temperature in set command"); + temperature[i] = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_theta(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_theta() +{ + int nlocal = atom->nlocal; + int *line = atom->line; + + auto avec_line = dynamic_cast(atom->style_match("line")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (line[i] < 0) + error->one(FLERR,"Cannot set theta for atom that is not a line"); + avec_line->bonus[atom->line[i]].theta = dvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_theta_random(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (ivalue <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 2; +} + +void Set2::invoke_theta_random() +{ + set(THETA_RANDOM); +} + +/* ---------------------------------------------------------------------- */ + +void Set2::process_tri(int &iarg, int narg, char **arg) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->tri_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; +} + +void Set2::invoke_tri() +{ + int nlocal = atom->nlocal; + auto avec_tri = dynamic_cast(atom->style_match("tri")); + + // VARIABLE option + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (dvalue < 0.0) error->one(FLERR,"Invalid tri size in set command"); + avec_tri->set_equilateral(i,dvalue); + } + + // update bonus tri count + + bigint nlocal_bonus = avec_tri->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + void Set2::process_type(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set type", error); @@ -945,95 +2066,28 @@ void Set2::invoke_type_subset() /* ---------------------------------------------------------------------- */ -void Set2::process_mol(int &iarg, int narg, char **arg) +void Set2::process_volume(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->molecule_flag) + else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (!atom->vfrac_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (dvalue <= 0.0) error->all(FLERR,"Invalid volume in set command"); iarg += 2; } - -void Set2::invoke_mol() + +void Set2::invoke_volume() { int nlocal = atom->nlocal; - int *molecule = atom->molecule; + double *vfrac = atom->vfrac; // VARIABLE option for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - molecule[i] = ivalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_x(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - iarg += 2; -} - -void Set2::invoke_x() -{ - int nlocal = atom->nlocal; - double **x = atom->x; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - x[i][0] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_y(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - iarg += 2; -} - -void Set2::invoke_y() -{ - int nlocal = atom->nlocal; - double **x = atom->x; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - x[i][1] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_z(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - iarg += 2; -} - -void Set2::invoke_z() -{ - int nlocal = atom->nlocal; - double **x = atom->x; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - x[i][2] = dvalue; + if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); + vfrac[i] = dvalue; } } @@ -1108,1126 +2162,70 @@ void Set2::invoke_vz() /* ---------------------------------------------------------------------- */ -void Set2::process_charge(int &iarg, int narg, char **arg) +void Set2::process_x(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->q_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); iarg += 2; } -void Set2::invoke_charge() +void Set2::invoke_x() { int nlocal = atom->nlocal; - double *q = atom->q; - double *q_scaled = atom->q_scaled; - double *epsilon = atom->epsilon; - - // ensure that scaled charges are consistent the new charge value - + double **x = atom->x; + // VARIABLE option for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - q[i] = dvalue; - if (epsilon) q_scaled[i] = dvalue / epsilon[i]; + x[i][0] = dvalue; } } /* ---------------------------------------------------------------------- */ -void Set2::process_mass(int &iarg, int narg, char **arg) +void Set2::process_y(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rmass_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); iarg += 2; } -void Set2::invoke_mass() +void Set2::invoke_y() { int nlocal = atom->nlocal; - double *rmass = atom->rmass; + double **x = atom->x; // VARIABLE option for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue <= 0.0) error->one(FLERR,"Invalid mass in set command"); - rmass[i] = dvalue; + x[i][1] = dvalue; } } /* ---------------------------------------------------------------------- */ -void Set2::process_shape(int &iarg, int narg, char **arg) +void Set2::process_z(int &iarg, int narg, char **arg) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->ellipsoid_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 4; -} - -void Set2::invoke_shape() -{ - int nlocal = atom->nlocal; - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) - error->one(FLERR,"Invalid shape in set command"); - if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) { - if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) - error->one(FLERR,"Invalid shape in set command"); - } - avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); - } - - // update global ellipsoid count - - bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->nellipsoids,1,MPI_LMP_BIGINT,MPI_SUM,world); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_length(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->line_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); iarg += 2; } -void Set2::invoke_length() +void Set2::invoke_z() { int nlocal = atom->nlocal; - auto avec_line = dynamic_cast(atom->style_match("line")); - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid length in set command"); - avec_line->set_length(i,dvalue); - } - - // update global line count - - bigint nlocal_bonus = avec_line->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->nlines,1,MPI_LMP_BIGINT,MPI_SUM,world); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_tri(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->tri_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_tri() -{ - int nlocal = atom->nlocal; - auto avec_tri = dynamic_cast(atom->style_match("tri")); - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid tri size in set command"); - avec_tri->set_equilateral(i,dvalue); - } - - // update bonus tri count - - bigint nlocal_bonus = avec_tri->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dipole(int &iarg, int narg, char **arg) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->mu_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 4; -} - -void Set2::invoke_dipole() -{ - int nlocal = atom->nlocal; - double **mu = atom->mu; + double **x = atom->x; // VARIABLE option for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - mu[i][0] = xvalue; - mu[i][1] = yvalue; - mu[i][2] = zvalue; - mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]); - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dipole_random(int &iarg, int narg, char **arg) -{ - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (!atom->mu_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - if (dvalue <= 0.0) - error->all(FLERR,"Invalid dipole length in set command"); - iarg += 3; -} - -void Set2::invoke_dipole_random() -{ - setrandom(DIPOLE_RANDOM); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_spin_atom(int &iarg, int narg, char **arg) -{ - if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin is deprecated. Please use spin/atom instead."); - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else xvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else yvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else zvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); - if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) - error->all(FLERR,"At least one spin vector component must be non-zero"); - if (!atom->sp_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (dvalue <= 0.0) - error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); - iarg += 5; -} - -void Set2::invoke_spin_atom() -{ - int nlocal = atom->nlocal; - double **sp = atom->sp; - - double norm; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) - error->one(FLERR,"Incorrect value for atomic spin magnitude: {}", dvalue); - norm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); - sp[i][0] = norm*xvalue; - sp[i][1] = norm*yvalue; - sp[i][2] = norm*zvalue; - sp[i][3] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) -{ - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin/random is deprecated. " - "Please use spin/atom/random instead."); - if (!atom->sp_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed {} in set {} command", ivalue, arg[iarg]); - if (dvalue <= 0.0) - error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); - iarg += 3; -} - -void Set2::invoke_spin_atom_random() -{ - setrandom(SPIN_RANDOM); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_radius_election(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->eradius_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_radius_election() -{ - int nlocal = atom->nlocal; - double *eradius = atom->eradius; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) - error->one(FLERR,"Incorrect value for electron radius: {}", dvalue); - eradius[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_spin_electron(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->spin_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_spin_electron() -{ - int nlocal = atom->nlocal; - int *spin = atom->spin; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (ivalue < -1 || ivalue > 3) - error->one(FLERR,"Incorrect value for electron spin: {}", ivalue); - atom->spin[i] = ivalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_quat(int &iarg, int narg, char **arg) -{ - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else wvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); - if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 5; -} - -void Set2::invoke_quat() -{ - int nlocal = atom->nlocal; - int *ellipsoid = atom->ellipsoid; - int *tri = atom->tri; - int *body = atom->body; - double **quat = atom->quat; - int quat_flag = atom->quat_flag; - - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - auto avec_tri = dynamic_cast(atom->style_match("tri")); - auto avec_body = dynamic_cast(atom->style_match("body")); - - int dimension = domain->dimension; - double theta2,sintheta2; - double *quat_one; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (avec_ellipsoid && ellipsoid[i] >= 0) - quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; - else if (avec_tri && tri[i] >= 0) - quat_one = avec_tri->bonus[tri[i]].quat; - else if (avec_body && body[i] >= 0) - quat_one = avec_body->bonus[body[i]].quat; - else if (quat_flag) - quat_one = quat[i]; - else - error->one(FLERR,"Cannot set quaternion for atom that has none"); - - // quat rotation vector must be only in z dir for 2d systems - - if (dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) - error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); - - theta2 = MY_PI2 * wvalue/180.0; - sintheta2 = sin(theta2); - quat_one[0] = cos(theta2); - quat_one[1] = xvalue * sintheta2; - quat_one[2] = yvalue * sintheta2; - quat_one[3] = zvalue * sintheta2; - MathExtra::qnormalize(quat_one); - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_quat_random(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - iarg += 2; -} - -void Set2::invoke_quat_random() -{ - setrandom(QUAT_RANDOM); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_theta(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->line_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_theta() -{ - int nlocal = atom->nlocal; - int *line = atom->line; - - auto avec_line = dynamic_cast(atom->style_match("line")); - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (line[i] < 0) - error->one(FLERR,"Cannot set theta for atom that is not a line"); - avec_line->bonus[atom->line[i]].theta = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_theta_random(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->line_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - iarg += 2; -} - -void Set2::invoke_theta_random() -{ - set(THETA_RANDOM); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_angmom(int &iarg, int narg, char **arg) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->angmom_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 4; -} - -void Set2::invoke_angmom() -{ - int nlocal = atom->nlocal; - double **angmom = atom->angmom; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - angmom[i][0] = xvalue; - angmom[i][1] = yvalue; - angmom[i][2] = zvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_omega(int &iarg, int narg, char **arg) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->omega_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 4; -} - -void Set2::invoke_omega() -{ - int nlocal = atom->nlocal; - double **omega = atom->angmom; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - omega[i][0] = xvalue; - omega[i][1] = yvalue; - omega[i][2] = zvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_diameter(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->radius_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_diameter() -{ - int nlocal = atom->nlocal; - double *radius = atom->radius; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); - radius[i] = 0.5 * dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_density(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rmass_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (dvalue <= 0.0) error->all(FLERR,"Invalid density in set command"); - discflag = 0; - if (strcmp(arg[iarg],"density/disc") == 0) { - discflag = 1; - if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); - } - iarg += 2; -} - -void Set2::invoke_density() -{ - int nlocal = atom->nlocal; - double *rmass = atom->rmass; - double *radius = atom->radius; - int *ellipsoid = atom->ellipsoid; - int *line = atom->line; - int *tri = atom->tri; - - int radius_flag = atom->radius_flag; - int ellipsoid_flag = atom->ellipsoid_flag; - int line_flag = atom->line_flag; - int tri_flag = atom->tri_flag; - - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - auto avec_line = dynamic_cast(atom->style_match("line")); - auto avec_tri = dynamic_cast(atom->style_match("tri")); - - // set rmass via density - // if radius > 0.0, treat as sphere or disc - // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) - // if length > 0.0, treat as line - // if area > 0.0, treat as tri - // else set rmass to density directly - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue <= 0.0) error->one(FLERR,"Invalid density in set command"); - if (radius_flag && radius[i] > 0.0) - if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * dvalue; - else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * dvalue; - else if (ellipsoid_flag && ellipsoid[i] >= 0) { - double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; - // enable 2d ellipse (versus 3d ellipsoid) when time integration - // options (fix nve/asphere, fix nh/asphere) are also implemented - // if (discflag) - // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; - // else - rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue; - } else if (line_flag && line[i] >= 0) { - double length = avec_line->bonus[line[i]].length; - rmass[i] = length * dvalue; - } else if (tri_flag && tri[i] >= 0) { - double *c1 = avec_tri->bonus[tri[i]].c1; - double *c2 = avec_tri->bonus[tri[i]].c2; - double *c3 = avec_tri->bonus[tri[i]].c3; - double c2mc1[3],c3mc1[3]; - MathExtra::sub3(c2,c1,c2mc1); - MathExtra::sub3(c3,c1,c3mc1); - double norm[3]; - MathExtra::cross3(c2mc1,c3mc1,norm); - double area = 0.5 * MathExtra::len3(norm); - rmass[i] = area * dvalue; - } else rmass[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_temperature(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->temperature_flag) - error->all(FLERR,"Cannot set this attribute for this atom style"); - iarg += 2; -} - -void Set2::invoke_temperature() -{ - int nlocal = atom->nlocal; - double *temperature = atom->temperature; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid temperature in set command"); - temperature[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_volume(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->vfrac_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (dvalue <= 0.0) error->all(FLERR,"Invalid volume in set command"); - iarg += 2; -} - -void Set2::invoke_volume() -{ - int nlocal = atom->nlocal; - double *vfrac = atom->vfrac; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); - vfrac[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_image(int &iarg, int narg, char **arg) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); - ximageflag = yimageflag = zimageflag = 0; - if (strcmp(arg[iarg+1],"NULL") != 0) { - ximageflag = 1; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ximage = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - } - if (strcmp(arg[iarg+2],"NULL") != 0) { - yimageflag = 1; - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yimage = utils::inumeric(FLERR,arg[iarg+2],false,lmp); - } - if (strcmp(arg[iarg+3],"NULL") != 0) { - zimageflag = 1; - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zimage = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - } - if (ximageflag && ximage && !domain->xperiodic) - error->all(FLERR, - "Cannot set non-zero image flag for non-periodic dimension"); - if (yimageflag && yimage && !domain->yperiodic) - error->all(FLERR, - "Cannot set non-zero image flag for non-periodic dimension"); - if (zimageflag && zimage && !domain->zperiodic) - error->all(FLERR, - "Cannot set non-zero image flag for non-periodic dimension"); - iarg += 4; -} - -void Set2::invoke_image() -{ - int nlocal = atom->nlocal; - imageint *image = atom->image; - - int xbox,ybox,zbox; - - // reset any or all of 3 image flags - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - xbox = (image[i] & IMGMASK) - IMGMAX; - ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; - zbox = (image[i] >> IMG2BITS) - IMGMAX; - if (varflag1) ximage = static_cast(xvalue); - if (varflag2) yimage = static_cast(yvalue); - if (varflag3) zimage = static_cast(zvalue); - if (ximageflag) xbox = ximage; - if (yimageflag) ybox = yimage; - if (zimageflag) zbox = zimage; - image[i] = ((imageint) (xbox + IMGMAX) & IMGMASK) | - (((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) | - (((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS); - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_bond(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); - 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) - error->all(FLERR,"Invalid value in set command"); - iarg += 2; -} - -void Set2::invoke_bond() -{ - topology(BOND); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_angle(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); - 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) - error->all(FLERR,"Invalid value in set command"); - iarg += 2; -} - -void Set2::invoke_angle() -{ - topology(ANGLE); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dihedral(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); - 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) - error->all(FLERR,"Invalid value in set command"); - iarg += 2; -} - -void Set2::invoke_dihedral() -{ - topology(DIHEDRAL); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_improper(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); - 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) - error->all(FLERR,"Invalid value in set command"); - iarg += 2; -} - -void Set2::invoke_improper() -{ - topology(IMPROPER); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_sph_e(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->esph_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_sph_e() -{ - int nlocal = atom->nlocal; - double *esph = atom->esph; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - esph[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_sph_cv(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->cv_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_sph_cv() -{ - int nlocal = atom->nlocal; - double *cv = atom->cv; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - cv[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_sph_rho(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rho_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_sph_rho() -{ - int nlocal = atom->nlocal; - double *rho = atom->rho; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - rho[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_edpd_temp(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } - if (!atom->edpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_edpd_temp() -{ - int nlocal = atom->nlocal; - double *edpd_temp = atom->edpd_temp; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - edpd_temp[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_edpd_cv(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } - if (!atom->edpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_edpd_cv() -{ - int nlocal = atom->nlocal; - double *edpd_cv = atom->edpd_cv; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - edpd_cv[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_cc(int &iarg, int narg, char **arg) -{ - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); - // NOTE: seems like error to not set cc_index for all 3 cases - // syntax is iarg+1 is index, iarg+2 is value - // doc page does not talk about NULL as valid value - // check package DPD-MESO package examples for tDPD for use of this command - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - cc_index = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (cc_index < 1) error->all(FLERR,"Illegal set command"); - } - if (!atom->tdpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 3; -} - -void Set2::invoke_cc() -{ - int nlocal = atom->nlocal; - double **cc = atom->cc; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - cc[i][cc_index-1] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_smd_mass_density(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->smd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_smd_mass_density() -{ - int nlocal = atom->nlocal; - double *rmass = atom->rmass; - double *vfrac = atom->vfrac; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - // set mass from volume and supplied mass density - rmass[i] = vfrac[i] * dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->smd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_smd_contact_radius() -{ - int nlocal = atom->nlocal; - double *contact_radius = atom->contact_radius; - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - contact_radius[i] = dvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dpd_theta(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } - if (!atom->dpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_dpd_theta() -{ - int nlocal = atom->nlocal; - int *type = atom->type; - double **v = atom->v; - double *mass = atom->mass; - double *rmass = atom->rmass; - double *dpdTheta = atom->dpdTheta; - - double tfactor = force->mvv2e / (domain->dimension * force->boltz); - double onemass; - double vx,vy,vz; - - // VARIABLE option or NULL to set temp to KE of particle - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (dvalue >= 0.0) dpdTheta[i] = dvalue; - else { - if (rmass) onemass = rmass[i]; - else onemass = mass[type[i]]; - vx = v[i][0]; - vy = v[i][1]; - vz = v[i][2]; - dpdTheta[i] = tfactor * onemass * (vx*vx + vy*vy + vz*vz); - } - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_epsilon(int &iarg, int narg, char **arg) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } - if (!atom->dielectric_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - iarg += 2; -} - -void Set2::invoke_epsilon() -{ - int nlocal = atom->nlocal; - double *epsilon = atom->epsilon; - double *q = atom->q; - double *q_scaled = atom->q_scaled; - - // assign local dielectric constant - // also update scaled charge value - - // VARIABLE option - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - // NOTE: should it be error if dvalue < 0.0 ? - if (dvalue >= 0.0) { - epsilon[i] = dvalue; - q_scaled[i] = q[i] / dvalue; - } + x[i][2] = dvalue; } } From a1fc55b47932a44800241619a26b61b7cbe316a0 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Mon, 27 Nov 2023 10:23:50 -0700 Subject: [PATCH 03/26] more refactoring --- src/set2.cpp | 674 +++++++++++++++++++++++++++++++++++---------------- src/set2.h | 63 +++-- 2 files changed, 505 insertions(+), 232 deletions(-) diff --git a/src/set2.cpp b/src/set2.cpp index 7a79768a8a..aa831e6c7b 100644 --- a/src/set2.cpp +++ b/src/set2.cpp @@ -59,6 +59,16 @@ enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, /* ---------------------------------------------------------------------- */ +Set2::~Set2() +{ + memory->destroy(vec1); + memory->destroy(vec2); + memory->destroy(vec3); + memory->destroy(vec4); +} + +/* ---------------------------------------------------------------------- */ + void Set2::command(int narg, char **arg) { if (domain->box_exist == 0) @@ -156,6 +166,7 @@ void Set2::process_args(int caller_flag, int narg, char **arg) naction = maxaction = 0; actions = nullptr; + Action *action; int iarg = 2; while (iarg < narg) { @@ -166,145 +177,196 @@ void Set2::process_args(int caller_flag, int narg, char **arg) memory->srealloc(invoke_choice,maxaction*sizeof(FnPtrPack),"set:invoke_choice"); } + action = &actions[naction]; + action->varflag = 0; + action->varflag1 = action->varflag2 = action->varflag3 = action->varflag4 = 0; + if (strcmp(arg[iarg],"angle") == 0) { + action->keyword = ANGLE; process_angle(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_angle; } else if (strcmp(arg[iarg],"angmom") == 0) { + action->keyword = ANGLE; process_angmom(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_angmom; } else if (strcmp(arg[iarg],"bond") == 0) { + action->keyword = ANGLE; process_bond(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_bond; } else if (strcmp(arg[iarg],"cc") == 0) { + action->keyword = ANGLE; process_cc(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_cc; } else if (strcmp(arg[iarg],"charge") == 0) { + action->keyword = ANGLE; process_charge(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_charge; } else if (strcmp(arg[iarg],"density") == 0 ||(strcmp(arg[iarg],"density/disc") == 0)) { + action->keyword = ANGLE; process_density(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_density; } else if (strcmp(arg[iarg],"diameter") == 0) { + action->keyword = ANGLE; process_diameter(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_diameter; } else if (strcmp(arg[iarg],"dihedral") == 0) { + action->keyword = ANGLE; process_dihedral(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dihedral; } else if (strcmp(arg[iarg],"dipole") == 0) { + action->keyword = ANGLE; process_dipole(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dipole; } else if (strcmp(arg[iarg],"dipole/random") == 0) { + action->keyword = ANGLE; process_dipole_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dipole_random; } else if (strcmp(arg[iarg],"dpd/theta") == 0) { + action->keyword = ANGLE; process_dpd_theta(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dpd_theta; } else if (strcmp(arg[iarg],"edpd/cv") == 0) { + action->keyword = ANGLE; process_edpd_cv(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_edpd_cv; } else if (strcmp(arg[iarg],"edpd/temp") == 0) { + action->keyword = ANGLE; process_edpd_temp(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_edpd_temp; } else if (strcmp(arg[iarg],"epsilon") == 0) { + action->keyword = ANGLE; process_epsilon(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_epsilon; } else if (strcmp(arg[iarg],"image") == 0) { + action->keyword = ANGLE; process_image(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_image; } else if (strcmp(arg[iarg],"improper") == 0) { + action->keyword = ANGLE; process_improper(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_improper; } else if (strcmp(arg[iarg],"length") == 0) { + action->keyword = ANGLE; process_length(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_length; } else if (strcmp(arg[iarg],"mass") == 0) { + action->keyword = ANGLE; process_mass(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_mass; } else if (strcmp(arg[iarg],"mol") == 0) { + action->keyword = ANGLE; process_mol(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_mol; } else if (strcmp(arg[iarg],"omega") == 0) { + action->keyword = ANGLE; process_omega(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_omega; } else if (strcmp(arg[iarg],"quat") == 0) { + action->keyword = ANGLE; process_quat(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_quat; } else if (strcmp(arg[iarg],"quat/random") == 0) { + action->keyword = ANGLE; process_quat_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_quat_random; } else if (strcmp(arg[iarg],"radius/electron") == 0) { + action->keyword = ANGLE; process_radius_election(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_radius_election; } else if (strcmp(arg[iarg],"shape") == 0) { + action->keyword = ANGLE; process_shape(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_shape; } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { + action->keyword = ANGLE; process_smd_contact_radius(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_smd_contact_radius; } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { + action->keyword = ANGLE; process_smd_mass_density(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_density; } else if (strcmp(arg[iarg],"sph/cv") == 0) { + action->keyword = ANGLE; process_sph_cv(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_sph_cv; } else if (strcmp(arg[iarg],"sph/e") == 0) { + action->keyword = ANGLE; process_sph_e(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_sph_e; } else if (strcmp(arg[iarg],"sph/rho") == 0) { + action->keyword = ANGLE; process_sph_rho(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_sph_rho; } else if ((strcmp(arg[iarg],"spin/atom") == 0) || (strcmp(arg[iarg],"spin") == 0)) { + action->keyword = ANGLE; process_spin_atom(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_spin_atom; } else if ((strcmp(arg[iarg],"spin/atom/random") == 0) || (strcmp(arg[iarg],"spin/random") == 0)) { + action->keyword = ANGLE; process_spin_atom_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_spin_atom_random; } else if (strcmp(arg[iarg],"spin/electron") == 0) { + action->keyword = ANGLE; process_spin_electron(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_spin_electron; } else if (strcmp(arg[iarg],"temperature") == 0) { + action->keyword = ANGLE; process_temperature(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_temperature; } else if (strcmp(arg[iarg],"theta") == 0) { + action->keyword = ANGLE; process_theta(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_theta; } else if (strcmp(arg[iarg],"theta/random") == 0) { + action->keyword = ANGLE; process_theta_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_theta_random; } else if (strcmp(arg[iarg],"tri") == 0) { + action->keyword = ANGLE; process_tri(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_tri; } else if (strcmp(arg[iarg],"type") == 0) { + action->keyword = ANGLE; process_type(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type; } else if (strcmp(arg[iarg],"type/fraction") == 0) { + action->keyword = ANGLE; process_type_fraction(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type_fraction; } else if (strcmp(arg[iarg],"type/ratio") == 0) { + action->keyword = ANGLE; process_type_ratio(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type_ratio; } else if (strcmp(arg[iarg],"type/subset") == 0) { + action->keyword = ANGLE; process_type_subset(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type_subset; } else if (strcmp(arg[iarg],"volume") == 0) { + action->keyword = ANGLE; process_volume(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_volume; } else if (strcmp(arg[iarg],"vx") == 0) { + action->keyword = ANGLE; process_vx(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_vx; } else if (strcmp(arg[iarg],"vy") == 0) { + action->keyword = ANGLE; process_vy(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_vy; } else if (strcmp(arg[iarg],"vz") == 0) { + action->keyword = ANGLE; process_vz(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_vz; } else if (strcmp(arg[iarg],"x") == 0) { + action->keyword = ANGLE; process_x(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_x; } else if (strcmp(arg[iarg],"y") == 0) { + action->keyword = ANGLE; process_y(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_y; } else if (strcmp(arg[iarg],"z") == 0) { + action->keyword = ANGLE; process_z(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_z; @@ -316,6 +378,32 @@ void Set2::process_args(int caller_flag, int narg, char **arg) error->all(FLERR,"Illegal set command keyword"); } } + + // check keywords for properties that are part of rigid body data + // error if selection includes atoms in rigid bodies + // assume no conflict for properties not in list of cases + + for (int i = 0; i < naction; i++) + switch (actions[i].keyword) { + case X: + case Y: + case Z: + case MOLECULE: + case MASS: + case ANGMOM: + case SHAPE: + case DIAMETER: + case DENSITY: + case TEMPERATURE: + case QUAT: + case IMAGE: + if (modify->check_rigid_list_overlap(select)) + error->warning(FLERR,"Changing a property of atoms in rigid bodies " + "that has no effect unless rigid bodies are re-initialized"); + break; + default: + break; + } } /* ---------------------------------------------------------------------- @@ -325,20 +413,33 @@ void Set2::process_args(int caller_flag, int narg, char **arg) void Set2::invoke_actions() { + int nlocal = atom->nlocal; + Action *action; + + // NOTE: need to create vec1234 ahead of time + for (int i = 0; i < naction; i++) { - // overwrite dvalue, ivalue, xyzw value if variables defined - // else the input script scalar value remains in place + action = &actions[i]; + + // evaluate atom-style variable(s) if necessary - if (varflag) { - if (varflag1) { - dvalue = xvalue = vec1[i]; - ivalue = static_cast (dvalue); + if (action->varflag) { + if (action->varflag1) { + input->variable->compute_atom(action->ivar1,0,vec1,1,0); + } + if (action->varflag2) { + input->variable->compute_atom(action->ivar2,0,vec2,1,0); + } + if (action->varflag3) { + input->variable->compute_atom(action->ivar3,0,vec3,1,0); + } + if (action->varflag4) { + input->variable->compute_atom(action->ivar4,0,vec4,1,0); } - if (varflag2) yvalue = vec2[i]; - if (varflag3) zvalue = vec3[i]; - if (varflag4) wvalue = vec4[i]; } + + // invoke the action to reset per-atom values (this->*invoke_choice[i])(); } @@ -385,69 +486,9 @@ void Set2::selection(int n) if (region->match(x[i][0],x[i][1],x[i][2])) select[i] = 1; else select[i] = 0; } -} -/* ---------------------------------------------------------------------- - set owned atom properties directly - either scalar or per-atom values from atom-style variable(s) -------------------------------------------------------------------------- */ - -void Set2::set(int keyword) -{ - // evaluate atom-style variable(s) if necessary - - vec1 = vec2 = vec3 = vec4 = nullptr; - - if (varflag) { - int nlocal = atom->nlocal; - if (varflag1) { - memory->create(vec1,nlocal,"set:vec1"); - input->variable->compute_atom(ivar1,0,vec1,1,0); - } - if (varflag2) { - memory->create(vec2,nlocal,"set:vec2"); - input->variable->compute_atom(ivar2,0,vec2,1,0); - } - if (varflag3) { - memory->create(vec3,nlocal,"set:vec3"); - input->variable->compute_atom(ivar3,0,vec3,1,0); - } - if (varflag4) { - memory->create(vec4,nlocal,"set:vec4"); - input->variable->compute_atom(ivar4,0,vec4,1,0); - } - } - - // check if properties of atoms in rigid bodies are updated - // that are cached as per-body data + // NOTE: could count selected atoms here and output for caller = SET - switch (keyword) { - case X: - case Y: - case Z: - case MOLECULE: - case MASS: - case ANGMOM: - case SHAPE: - case DIAMETER: - case DENSITY: - case TEMPERATURE: - case QUAT: - case IMAGE: - if (modify->check_rigid_list_overlap(select)) - error->warning(FLERR,"Changing a property of atoms in rigid bodies " - "that has no effect unless rigid bodies are re-initialized"); - break; - default: // assume no conflict for all other properties - break; - } - - // clear up per-atom memory if allocated - - memory->destroy(vec1); - memory->destroy(vec2); - memory->destroy(vec3); - memory->destroy(vec4); } /* ---------------------------------------------------------------------- @@ -817,22 +858,23 @@ void Set2::topology(int keyword) void Set2::varparse(const char *name, int m) { - varflag = 1; int ivar = input->variable->find(name+2); - if (ivar < 0) error->all(FLERR,"Variable name {} for set command does not exist", name); if (!input->variable->atomstyle(ivar)) error->all(FLERR,"Variable {} for set command is invalid style", name); + Action *action = &actions[naction]; + action->varflag = 1; + if (m == 1) { - varflag1 = 1; ivar1 = ivar; + action->varflag1 = 1; action->ivar1 = ivar; } else if (m == 2) { - varflag2 = 1; ivar2 = ivar; + action->varflag2 = 1; action->ivar2 = ivar; } else if (m == 3) { - varflag3 = 1; ivar3 = ivar; + action->varflag3 = 1; action->ivar3 = ivar; } else if (m == 4) { - varflag4 = 1; ivar4 = ivar; + action->varflag4 = 1; action->ivar4 = ivar; } } @@ -843,19 +885,26 @@ void Set2::varparse(const char *name, int m) // separate two operations so can be called by either set or fix set command // ---------------------------------------------------------------------- +// DONE + void Set2::process_angle(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); - 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) - error->all(FLERR,"Invalid value in set command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); + + Action *action = &actions[naction]; + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ANGLE,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->nangletypes) + error->all(FLERR,"Invalid angle type in set command"); iarg += 2; } +// DONE + void Set2::invoke_angle() { topology(ANGLE); @@ -863,29 +912,49 @@ void Set2::invoke_angle() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_angmom(int &iarg, int narg, char **arg) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (!atom->angmom_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + iarg += 4; } +// DONE + void Set2::invoke_angmom() { int nlocal = atom->nlocal; double **angmom = atom->angmom; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; + } + angmom[i][0] = xvalue; angmom[i][1] = yvalue; angmom[i][2] = zvalue; @@ -894,19 +963,27 @@ void Set2::invoke_angmom() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_bond(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); - 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) - error->all(FLERR,"Invalid value in set command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); + + Action *action = &actions[naction]; + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::BOND,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->nbondtypes) + error->all(FLERR,"Invalid bond type in set command"); + iarg += 2; } +// DONE + void Set2::invoke_bond() { topology(BOND); @@ -914,9 +991,14 @@ void Set2::invoke_bond() /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_cc(int &iarg, int narg, char **arg) { + if (!atom->tdpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); + // NOTE: seems like error to not set cc_index for all 3 cases // syntax is iarg+1 is index, iarg+2 is value // doc page does not talk about NULL as valid value @@ -928,8 +1010,7 @@ void Set2::process_cc(int &iarg, int narg, char **arg) dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (cc_index < 1) error->all(FLERR,"Illegal set command"); } - if (!atom->tdpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 3; } @@ -946,52 +1027,77 @@ void Set2::invoke_cc() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_charge(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->q_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_charge() { int nlocal = atom->nlocal; double *q = atom->q; double *q_scaled = atom->q_scaled; double *epsilon = atom->epsilon; - - // ensure that scaled charges are consistent the new charge value - - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double qvalue; + if (!action->varflag1) qvalue = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - q[i] = dvalue; - if (epsilon) q_scaled[i] = dvalue / epsilon[i]; + + if (varflag) qvalue = vec1[i]; + q[i] = qvalue; + + // ensure scaled charges are consistent with new charge value + + if (epsilon) q_scaled[i] = qvalue / epsilon[i]; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_density(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->rmass_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (dvalue <= 0.0) error->all(FLERR,"Invalid density in set command"); - discflag = 0; + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid density in set command"); + } + + action->ivalue1 = 0; if (strcmp(arg[iarg],"density/disc") == 0) { - discflag = 1; + action->ivalue1 = 1; if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); } + iarg += 2; } +// NOT DONE + void Set2::invoke_density() { int nlocal = atom->nlocal; @@ -1053,13 +1159,22 @@ void Set2::invoke_density() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_diameter(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->radius_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid diameter in set command"); + } + iarg += 2; } @@ -1068,30 +1183,46 @@ void Set2::invoke_diameter() int nlocal = atom->nlocal; double *radius = atom->radius; - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double diam; + if (!action->varflag1) diam = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); - radius[i] = 0.5 * dvalue; + + if (varflag) { + diam = vec1[i]; + if (diam < 0.0) error->one(FLERR,"Invalid diameter in set command"); + } + + radius[i] = 0.5 * diam; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_dihedral(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); - 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) - error->all(FLERR,"Invalid value in set command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); + + Action *action = &actions[naction]; + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::DIHEDRAL,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->ndihedraltypes) + error->all(FLERR,"Invalid dihedral type in set command"); + iarg += 2; } +// DONE + void Set2::invoke_dihedral() { topology(DIHEDRAL); @@ -1099,17 +1230,23 @@ void Set2::invoke_dihedral() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_dipole(int &iarg, int narg, char **arg) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (!atom->mu_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + iarg += 4; } @@ -1117,11 +1254,23 @@ void Set2::invoke_dipole() { int nlocal = atom->nlocal; double **mu = atom->mu; - - // VARIABLE option + + Action *action = &actions[naction]; + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; + } + mu[i][0] = xvalue; mu[i][1] = yvalue; mu[i][2] = zvalue; @@ -1129,22 +1278,30 @@ void Set2::invoke_dipole() } } +// DONE + /* ---------------------------------------------------------------------- */ void Set2::process_dipole_random(int &iarg, int narg, char **arg) { - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (!atom->mu_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); + + Action *action = &actions[naction]; + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - if (dvalue <= 0.0) + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid dipole length in set command"); + iarg += 3; } +// DONE + void Set2::invoke_dipole_random() { setrandom(DIPOLE_RANDOM); @@ -1152,20 +1309,28 @@ void Set2::invoke_dipole_random() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_dpd_theta(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } if (!atom->dpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); + + Action *action = &actions[naction]; + + if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid dpd/theta value in set command"); + } + iarg += 2; } +// NOT DONE + void Set2::invoke_dpd_theta() { int nlocal = atom->nlocal; @@ -1178,9 +1343,9 @@ void Set2::invoke_dpd_theta() double tfactor = force->mvv2e / (domain->dimension * force->boltz); double onemass; double vx,vy,vz; - - // VARIABLE option or NULL to set temp to KE of particle - + + // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1198,55 +1363,82 @@ void Set2::invoke_dpd_theta() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_edpd_cv(int &iarg, int narg, char **arg) { + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); + + Action *action = &actions[naction]; + if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/cv value in set command"); } - if (!atom->edpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + iarg += 2; } +// NOT DONE + void Set2::invoke_edpd_cv() { int nlocal = atom->nlocal; double *edpd_cv = atom->edpd_cv; - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double cv; + if (!action->varflag1) cv = action->dvalue1; + + // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - edpd_cv[i] = dvalue; + + if (varflag) { + cv = vec1[i]; + if (cv < 0.0) error->one(FLERR,"Invalid edpd/cv value in set command"); + } + + edpd_cv[i] = cv; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_edpd_temp(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } if (!atom->edpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); + + Action *action = &actions[naction]; + + if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/temp value in set command"); + } iarg += 2; } +// NOT DONE + void Set2::invoke_edpd_temp() { int nlocal = atom->nlocal; double *edpd_temp = atom->edpd_temp; - - // VARIABLE option + + // VARIABLE option or NULL to set temp to KE of particle + // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1256,20 +1448,28 @@ void Set2::invoke_edpd_temp() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_epsilon(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) error->all(FLERR,"Illegal set command"); - } if (!atom->dielectric_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); + + Action *action = &actions[naction]; + + if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid epsilon in set command"); + } + iarg += 2; } +// NOT DONE + void Set2::invoke_epsilon() { int nlocal = atom->nlocal; @@ -1281,6 +1481,7 @@ void Set2::invoke_epsilon() // also update scaled charge value // VARIABLE option + // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1294,9 +1495,14 @@ void Set2::invoke_epsilon() /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_image(int &iarg, int narg, char **arg) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); + + Action *action = &actions[naction]; + ximageflag = yimageflag = zimageflag = 0; if (strcmp(arg[iarg+1],"NULL") != 0) { ximageflag = 1; @@ -1313,6 +1519,7 @@ void Set2::process_image(int &iarg, int narg, char **arg) if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); else zimage = utils::inumeric(FLERR,arg[iarg+3],false,lmp); } + if (ximageflag && ximage && !domain->xperiodic) error->all(FLERR, "Cannot set non-zero image flag for non-periodic dimension"); @@ -1322,9 +1529,12 @@ void Set2::process_image(int &iarg, int narg, char **arg) if (zimageflag && zimage && !domain->zperiodic) error->all(FLERR, "Cannot set non-zero image flag for non-periodic dimension"); + iarg += 4; } +// NOT DONE + void Set2::invoke_image() { int nlocal = atom->nlocal; @@ -1334,16 +1544,16 @@ void Set2::invoke_image() // reset any or all of 3 image flags - // VARIABLE option + Action *action = &actions[naction]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; xbox = (image[i] & IMGMASK) - IMGMAX; ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; zbox = (image[i] >> IMG2BITS) - IMGMAX; - if (varflag1) ximage = static_cast(xvalue); - if (varflag2) yimage = static_cast(yvalue); - if (varflag3) zimage = static_cast(zvalue); + if (action->varflag1) ximage = static_cast(xvalue); + if (action->varflag2) yimage = static_cast(yvalue); + if (action->varflag3) zimage = static_cast(zvalue); if (ximageflag) xbox = ximage; if (yimageflag) ybox = yimage; if (zimageflag) zbox = zimage; @@ -1355,19 +1565,27 @@ void Set2::invoke_image() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_improper(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); - 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) + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); + + Action *action = &actions[naction]; + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::IMPROPER,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->nimpropertypes) error->all(FLERR,"Invalid value in set command"); + iarg += 2; } +// DONE + void Set2::invoke_improper() { topology(IMPROPER); @@ -1375,27 +1593,46 @@ void Set2::invoke_improper() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_length(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid length in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_length() { int nlocal = atom->nlocal; auto avec_line = dynamic_cast(atom->style_match("line")); - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double length; + if (!action->varflag1) length = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid length in set command"); - avec_line->set_length(i,dvalue); + + if (varflag) { + length = vec1[i]; + if (length < 0.0) error->one(FLERR,"Invalid length in set command"); + } + + avec_line->set_length(i,length); } // update global line count @@ -1406,27 +1643,48 @@ void Set2::invoke_length() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_mass(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->rmass_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid mass in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_mass() { int nlocal = atom->nlocal; double *rmass = atom->rmass; - + + Action *action = &actions[naction]; + int varflag = action->varflag; + double mass_one; + if (!action->varflag1) mass_one = action->dvalue1; + // VARIABLE option for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue <= 0.0) error->one(FLERR,"Invalid mass in set command"); - rmass[i] = dvalue; + + if (varflag) { + mass_one = vec1[i]; + if (mass_one < 0.0) error->one(FLERR,"Invalid mass in set command"); + } + + rmass[i] = mass_one; } } @@ -1930,7 +2188,7 @@ void Set2::process_theta_random(int &iarg, int narg, char **arg) void Set2::invoke_theta_random() { - set(THETA_RANDOM); + setrandom(THETA_RANDOM); } /* ---------------------------------------------------------------------- */ @@ -1981,11 +2239,11 @@ void Set2::invoke_type() int nlocal = atom->nlocal; int *type = atom->type; - // VARIABLE option + Action *action = &actions[naction]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (varflag) + if (action->varflag) if (ivalue <= 0 || ivalue > atom->ntypes) error->one(FLERR,"Invalid value in set command"); type[i] = ivalue; @@ -2241,6 +2499,8 @@ void Set2::process_custom(int &iarg, int narg, char **arg) if (index_custom < 0) error->all(FLERR,"Set keyword or custom property {} does not exist",pname); + Action *action = &actions[naction]; + switch (argi.get_type()) { case ArgInfo::INAME: @@ -2251,7 +2511,7 @@ void Set2::process_custom(int &iarg, int narg, char **arg) if (argi.get_dim() == 0) { if (cols > 0) error->all(FLERR,"Set command custom integer property {} is not a vector",pname); - custom_flag = IVEC; + action->keyword = IVEC; } else if (argi.get_dim() == 1) { if (cols == 0) error->all(FLERR,"Set command custom integer property {} is not an array",pname); @@ -2259,7 +2519,7 @@ void Set2::process_custom(int &iarg, int narg, char **arg) if (icol_custom <= 0 || icol_custom > cols) error->all(FLERR,"Set command per-atom custom integer array {} is accessed " "out-of-range",pname); - custom_flag = IARRAY; + action->keyword = IARRAY; } else error->all(FLERR,"Illegal set command"); break; @@ -2271,7 +2531,7 @@ void Set2::process_custom(int &iarg, int narg, char **arg) if (argi.get_dim() == 0) { if (cols > 0) error->all(FLERR,"Set command custom double property {} is not a vector",pname); - custom_flag = DVEC; + action->keyword = DVEC; } else if (argi.get_dim() == 1) { if (cols == 0) error->all(FLERR,"Set command custom double property {} is not an array",pname); @@ -2279,7 +2539,7 @@ void Set2::process_custom(int &iarg, int narg, char **arg) if (icol_custom <= 0 || icol_custom > cols) error->all(FLERR,"Set command per-atom custom double array {} is " "accessed out-of-range",pname); - custom_flag = DARRAY; + action->keyword = DARRAY; } else error->all(FLERR,"Illegal set command"); break; @@ -2295,27 +2555,27 @@ void Set2::invoke_custom() { int nlocal = atom->nlocal; - // VARIABLE option + Action *action = &actions[naction]; - if (custom_flag == IVEC) { + if (action->keyword == IVEC) { int *ivector = atom->ivector[index_custom]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; ivector[i] = ivalue; } - } else if (custom_flag == DVEC) { + } else if (action->keyword == DVEC) { double *dvector = atom->dvector[index_custom]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; dvector[i] = dvalue; } - } else if (custom_flag == IARRAY) { + } else if (action->keyword == IARRAY) { int **iarray = atom->iarray[index_custom]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; iarray[i][icol_custom-1] = ivalue; } - } else if (custom_flag == DARRAY) { + } else if (action->keyword == DARRAY) { double **darray = atom->darray[index_custom]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; diff --git a/src/set2.h b/src/set2.h index 4a303e6cc4..ea76175336 100644 --- a/src/set2.h +++ b/src/set2.h @@ -27,9 +27,19 @@ namespace LAMMPS_NS { class Set2 : public Command { public: Set2(class LAMMPS *lmp) : Command(lmp){}; + ~Set2(); + void command(int, char **) override; - private: + void process_args(int, int, char **); + void selection(int); + void invoke_actions(); + + private: + int caller; // SETCOMMAND or FIXSET + + // params for atom selection + int style; char *id; int nlo,nhi; @@ -37,39 +47,42 @@ class Set2 : public Command { int groupbit; class Region *region; - int caller; - - struct Action { - - }; - - int naction,maxaction; - Action *actions; - - int *select; - - typedef void (Set2::*FnPtrPack)(); - FnPtrPack *invoke_choice; // list of ptrs to invoke functions - + // atom property setting params for keyword/value pairs int ivalue, newtype, count, index_custom, icol_custom; int ximage, yimage, zimage, ximageflag, yimageflag, zimageflag; int cc_index; bigint nsubset; double dvalue, xvalue, yvalue, zvalue, wvalue, fraction; - - int varflag, varflag1, varflag2, varflag3, varflag4; - int ivar1, ivar2, ivar3, ivar4; - double *vec1, *vec2, *vec3, *vec4; - - int custom_flag; int discflag; - void process_args(int, int, char **); - void invoke_actions(); + // one Action = one keyword/value pair + + struct Action { + int keyword; + int varflag; + int varflag1, varflag2, varflag3, varflag4; + int ivar1, ivar2, ivar3, ivar4; + int ivalue1; + double dvalue1,dvalue2,dvalue3,dvalue4; + }; + + int naction,maxaction; + Action *actions; + + typedef void (Set2::*FnPtrPack)(); + FnPtrPack *invoke_choice; // list of ptrs to invoke functions + + // storage for evaluated variables + + double *vec1, *vec2, *vec3, *vec4; + + // flag for selected atoms + + int *select; + + // private functions - void selection(int); - void set(int); void setrandom(int); void topology(int); void varparse(const char *, int); From c583a5240222e25b23bc5efea7d4cb10852ecba2 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Tue, 28 Nov 2023 16:44:07 -0700 Subject: [PATCH 04/26] more refactoring --- src/set2.cpp | 660 +++++++++++++++++++++++++++++++++++++++------------ src/set2.h | 1 + 2 files changed, 509 insertions(+), 152 deletions(-) diff --git a/src/set2.cpp b/src/set2.cpp index aa831e6c7b..872f8f3065 100644 --- a/src/set2.cpp +++ b/src/set2.cpp @@ -1674,8 +1674,6 @@ void Set2::invoke_mass() double mass_one; if (!action->varflag1) mass_one = action->dvalue1; - // VARIABLE option - for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1690,54 +1688,96 @@ void Set2::invoke_mass() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_mol(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (!atom->molecule_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->tvalue1 = utils::tnumeric(FLERR,arg[iarg+1],false,lmp); + if (action->tvalue1 < 0) error->one(FLERR,"Invalid molecule ID in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_mol() { int nlocal = atom->nlocal; int *molecule = atom->molecule; - - // VARIABLE option + + Action *action = &actions[naction]; + int varflag = action->varflag; + tagint molID; + if (!action->varflag1) molID = action->tvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - molecule[i] = ivalue; + + if (varflag) { + molID = vec1[i]; + if (molID < 0) error->one(FLERR,"Invalid molecule ID in set command"); + } + + molecule[i] = molID; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_omega(int &iarg, int narg, char **arg) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (!atom->omega_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + iarg += 4; } +// DONE + void Set2::invoke_omega() { int nlocal = atom->nlocal; double **omega = atom->angmom; + Action *action = &actions[naction]; + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + // VARIABLE option for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; + } + omega[i][0] = xvalue; omega[i][1] = yvalue; omega[i][2] = zvalue; @@ -1746,22 +1786,30 @@ void Set2::invoke_omega() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_quat(int &iarg, int narg, char **arg) { - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else wvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); + else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); + iarg += 5; } +// NOT DONE + void Set2::invoke_quat() { int nlocal = atom->nlocal; @@ -1812,17 +1860,24 @@ void Set2::invoke_quat() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_quat_random(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed in set command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); + + Action *action = &actions[naction]; + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); + iarg += 2; } +// DONE + void Set2::invoke_quat_random() { setrandom(QUAT_RANDOM); @@ -1830,63 +1885,110 @@ void Set2::invoke_quat_random() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_radius_election(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->eradius_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid electron radius in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_radius_election() { int nlocal = atom->nlocal; double *eradius = atom->eradius; - - // VARIABLE option - + + Action *action = &actions[naction]; + int varflag = action->varflag; + double radius; + if (!action->varflag1) radius = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) - error->one(FLERR,"Incorrect value for electron radius: {}", dvalue); - eradius[i] = dvalue; + + if (varflag) { + radius = vec1[i]; + if (radius < 0.0) error->one(FLERR,"Invalid electron radius in set command"); + } + + eradius[i] = radius; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_shape(int &iarg, int narg, char **arg) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (!atom->ellipsoid_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid shape in set command"); + } + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else { + action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue2 < 0.0) error->one(FLERR,"Invalid shape in set command"); + } + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else { + action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (action->dvalue3 < 0.0) error->one(FLERR,"Invalid shape in set command"); + } + iarg += 4; } +// DONE + void Set2::invoke_shape() { int nlocal = atom->nlocal; auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) error->one(FLERR,"Invalid shape in set command"); - if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) { - if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) - error->one(FLERR,"Invalid shape in set command"); - } - avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); + } + + if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) + if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) + error->one(FLERR,"Invalid shape in set command"); + + avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); } // update global ellipsoid count @@ -1897,173 +1999,273 @@ void Set2::invoke_shape() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->smd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid smd/contact/radius in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_smd_contact_radius() { int nlocal = atom->nlocal; double *contact_radius = atom->contact_radius; - - // VARIABLE option + + Action *action = &actions[naction]; + int varflag = action->varflag; + double radius; + if (!action->varflag1) radius = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - contact_radius[i] = dvalue; + + if (varflag) { + radius = vec1[i]; + if (radius < 0.0) error->one(FLERR,"Invalid smd/contact/radius in set command"); + } + + contact_radius[i] = radius; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_smd_mass_density(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->smd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_smd_mass_density() { int nlocal = atom->nlocal; double *rmass = atom->rmass; double *vfrac = atom->vfrac; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double density; + if (!action->varflag1) density = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - // set mass from volume and supplied mass density - rmass[i] = vfrac[i] * dvalue; + + if (varflag) { + density = vec1[i]; + if (density < 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); + } + + rmass[i] = vfrac[i] * density; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_sph_cv(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->cv_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_sph_cv() { int nlocal = atom->nlocal; double *cv = atom->cv; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double sph_cv; + if (!action->varflag1) sph_cv = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - cv[i] = dvalue; + if (varflag) sph_cv = vec1[i]; + cv[i] = sph_cv; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_sph_e(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->esph_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_sph_e() { int nlocal = atom->nlocal; double *esph = atom->esph; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double sph_e; + if (!action->varflag1) sph_e = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - esph[i] = dvalue; + if (varflag) sph_e = vec1[i]; + esph[i] = sph_e; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_sph_rho(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->rho_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_sph_rho() { int nlocal = atom->nlocal; double *rho = atom->rho; - - // VARIABLE option + + Action *action = &actions[naction]; + int varflag = action->varflag; + double sph_rho; + if (!action->varflag1) sph_rho = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - rho[i] = dvalue; + if (varflag) sph_rho = vec1[i]; + rho[i] = sph_rho; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_spin_atom(int &iarg, int narg, char **arg) { if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin is deprecated. Please use spin/atom instead."); - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else xvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else yvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else zvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); - if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) - error->all(FLERR,"At least one spin vector component must be non-zero"); + error->warning(FLERR, "Set attribute spin is deprecated -- use spin/atom instead"); if (!atom->sp_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (dvalue <= 0.0) - error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); + } + + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); + else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); + iarg += 5; } +// DONE + void Set2::invoke_spin_atom() { int nlocal = atom->nlocal; double **sp = atom->sp; - double norm; - - // VARIABLE option - + + Action *action = &actions[naction]; + int varflag = action->varflag; + double magnitude,xvalue,yvalue,zvalue; + if (!action->varflag1) magnitude = action->dvalue1; + if (!action->varflag2) xvalue = action->dvalue2; + if (!action->varflag3) yvalue = action->dvalue3; + if (!action->varflag4) zvalue = action->dvalue4; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) - error->one(FLERR,"Incorrect value for atomic spin magnitude: {}", dvalue); + + if (varflag) { + if (action->varflag1) magnitude = vec1[i]; + if (magnitude < 0.0) + error->one(FLERR,"Invalid spin magnitude in set command"); + if (action->varflag2) xvalue = vec2[i]; + if (action->varflag3) yvalue = vec3[i]; + if (action->varflag4) zvalue = vec4[i]; + } + + if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) + error->all(FLERR,"At least one spin vector component must be non-zero"); + norm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); sp[i][0] = norm*xvalue; sp[i][1] = norm*yvalue; sp[i][2] = norm*zvalue; - sp[i][3] = dvalue; + sp[i][3] = magnitude; } } @@ -2071,18 +2273,20 @@ void Set2::invoke_spin_atom() void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) { + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); + ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) error->warning(FLERR, "Set attribute spin/random is deprecated. " "Please use spin/atom/random instead."); - if (!atom->sp_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (ivalue <= 0) error->all(FLERR,"Invalid random number seed {} in set {} command", ivalue, arg[iarg]); if (dvalue <= 0.0) error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + iarg += 3; } @@ -2093,69 +2297,116 @@ void Set2::invoke_spin_atom_random() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_spin_electron(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (!atom->spin_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 < -1 || action->ivalue1 > 3) + error->one(FLERR,"Invalid value for electron spin: {}", ivalue); + } + iarg += 2; } +// DONE + void Set2::invoke_spin_electron() { int nlocal = atom->nlocal; int *spin = atom->spin; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + int ispin; + if (!action->varflag1) ispin = action->ivalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (ivalue < -1 || ivalue > 3) - error->one(FLERR,"Incorrect value for electron spin: {}", ivalue); - atom->spin[i] = ivalue; + + if (varflag) { + ispin = static_cast (vec1[i]); + if (ispin < -1 || ispin > 3) + error->one(FLERR,"Incorrect value for electron spin: {}", ivalue); + } + + atom->spin[i] = ispin; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_temperature(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->temperature_flag) error->all(FLERR,"Cannot set this attribute for this atom style"); + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid temperature in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_temperature() { int nlocal = atom->nlocal; double *temperature = atom->temperature; - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double temp; + if (!action->varflag1) temp = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid temperature in set command"); - temperature[i] = dvalue; + + if (varflag) { + temp = vec1[i]; + if (temp < 0.0) error->one(FLERR,"Invalid temperature in set command"); + } + + temperature[i] = temp; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_theta(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_theta() { int nlocal = atom->nlocal; @@ -2163,29 +2414,39 @@ void Set2::invoke_theta() auto avec_line = dynamic_cast(atom->style_match("line")); - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double theta; + if (!action->varflag1) theta = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (line[i] < 0) - error->one(FLERR,"Cannot set theta for atom that is not a line"); + if (line[i] < 0) error->one(FLERR,"Cannot set theta for atom which is not a line"); + if (varflag) theta = vec1[i]; avec_line->bonus[atom->line[i]].theta = dvalue; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_theta_random(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed in set command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); + + Action *action = &actions[naction]; + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); + iarg += 2; } +// DONE + void Set2::invoke_theta_random() { setrandom(THETA_RANDOM); @@ -2222,6 +2483,8 @@ void Set2::invoke_tri() MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); } +/* ---------------------------------------------------------------------- */ + void Set2::process_type(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set type", error); @@ -2324,166 +2587,256 @@ void Set2::invoke_type_subset() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_volume(int &iarg, int narg, char **arg) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->vfrac_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (dvalue <= 0.0) error->all(FLERR,"Invalid volume in set command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); + + Action *action = &actions[naction]; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid volume in set command"); + } + iarg += 2; } +// DONE + void Set2::invoke_volume() { int nlocal = atom->nlocal; double *vfrac = atom->vfrac; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double vol; + if (!action->varflag1) vol = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid diameter in set command"); - vfrac[i] = dvalue; + + if (varflag) { + vol = vec1[i]; + if (vol < 0.0) error->one(FLERR,"Invalid volume in set command"); + } + + vfrac[i] = vol; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_vx(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vx", error); + + Action *action = &actions[naction]; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_vx() { int nlocal = atom->nlocal; double **v = atom->v; - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double vx; + if (!action->varflag1) vx = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - v[i][0] = dvalue; + if (varflag) vx = vec1[i]; + v[i][0] = vx; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_vy(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vy", error); + + Action *action = &actions[naction]; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_vy() { int nlocal = atom->nlocal; double **v = atom->v; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double vy; + if (!action->varflag1) vy = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - v[i][1] = dvalue; + if (varflag) vy = vec1[i]; + v[i][1] = vy; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_vz(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vz", error); + + Action *action = &actions[naction]; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_vz() { int nlocal = atom->nlocal; double **v = atom->v; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double vz; + if (!action->varflag1) vz = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - v[i][2] = dvalue; + if (varflag) vz = vec1[i]; + v[i][2] = vz; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_x(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); + + Action *action = &actions[naction]; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_x() { int nlocal = atom->nlocal; double **x = atom->x; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double coord; + if (!action->varflag1) coord = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - x[i][0] = dvalue; + if (varflag) coord = vec1[i]; + x[i][0] = coord; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_y(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); + + Action *action = &actions[naction]; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_y() { int nlocal = atom->nlocal; double **x = atom->x; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double coord; + if (!action->varflag1) coord = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - x[i][1] = dvalue; + if (varflag) coord = vec1[i]; + x[i][1] = coord; } } /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_z(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); + + Action *action = &actions[naction]; + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + iarg += 2; } +// DONE + void Set2::invoke_z() { int nlocal = atom->nlocal; double **x = atom->x; - // VARIABLE option + Action *action = &actions[naction]; + int varflag = action->varflag; + double coord; + if (!action->varflag1) coord = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - x[i][2] = dvalue; + if (varflag) coord = vec1[i]; + x[i][2] = coord; } } @@ -2494,6 +2847,7 @@ void Set2::process_custom(int &iarg, int narg, char **arg) int flag,cols; ArgInfo argi(arg[iarg],ArgInfo::DNAME|ArgInfo::INAME); const char *pname = argi.get_name(); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set", error); index_custom = atom->find_custom(argi.get_name(),flag,cols); if (index_custom < 0) @@ -2557,6 +2911,8 @@ void Set2::invoke_custom() Action *action = &actions[naction]; + // NOTE: what about icol_custom + if (action->keyword == IVEC) { int *ivector = atom->ivector[index_custom]; for (int i = 0; i < nlocal; i++) { diff --git a/src/set2.h b/src/set2.h index ea76175336..bbb811d236 100644 --- a/src/set2.h +++ b/src/set2.h @@ -64,6 +64,7 @@ class Set2 : public Command { int varflag1, varflag2, varflag3, varflag4; int ivar1, ivar2, ivar3, ivar4; int ivalue1; + tagint tvalue1; double dvalue1,dvalue2,dvalue3,dvalue4; }; From 6c9c537ab14b29ec160925c173ca037b2fb47ced Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 29 Nov 2023 10:29:40 -0700 Subject: [PATCH 05/26] more refactoring --- src/set2.cpp | 522 ++++++++++++++++++++++++++++++++------------------- src/set2.h | 12 +- 2 files changed, 331 insertions(+), 203 deletions(-) diff --git a/src/set2.cpp b/src/set2.cpp index 872f8f3065..579861c419 100644 --- a/src/set2.cpp +++ b/src/set2.cpp @@ -47,10 +47,10 @@ enum{SET,FIXSET}; enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, - DIPOLE_RANDOM,DPDTHETA,EDPD_CV,EDPD_TEMP,EPSILON,IMAGE,IMPROPER,LENGTH, + DIPOLE_RANDOM,DPD_THETA,EDPD_CV,EDPD_TEMP,EPSILON,IMAGE,IMPROPER,LENGTH, MASS,MOLECULE,OMEGA,QUAT,QUAT_RANDOM,RADIUS_ELECTRON,SHAPE, SMD_CONTACT_RADIUS,SMD_MASS_DENSITY,SPH_CV,SPH_E,SPH_RHO, - SPIN_ATOM,SPIN_ELECTRON,SPIN_RANDOM,TEMPERATURE,THETA,THETA_RANDOM, + SPIN_ATOM,SPIN_ATOM_RANDOM,SPIN_ELECTRON,TEMPERATURE,THETA,THETA_RANDOM, TRI,TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET,VOLUME,VX,VY,VZ,X,Y,Z, IVEC,DVEC,IARRAY,DARRAY}; @@ -186,187 +186,187 @@ void Set2::process_args(int caller_flag, int narg, char **arg) process_angle(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_angle; } else if (strcmp(arg[iarg],"angmom") == 0) { - action->keyword = ANGLE; + action->keyword = ANGMOM; process_angmom(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_angmom; } else if (strcmp(arg[iarg],"bond") == 0) { - action->keyword = ANGLE; + action->keyword = BOND; process_bond(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_bond; } else if (strcmp(arg[iarg],"cc") == 0) { - action->keyword = ANGLE; + action->keyword = CC; process_cc(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_cc; } else if (strcmp(arg[iarg],"charge") == 0) { - action->keyword = ANGLE; + action->keyword = CHARGE; process_charge(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_charge; } else if (strcmp(arg[iarg],"density") == 0 ||(strcmp(arg[iarg],"density/disc") == 0)) { - action->keyword = ANGLE; + action->keyword = DENSITY; process_density(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_density; } else if (strcmp(arg[iarg],"diameter") == 0) { - action->keyword = ANGLE; + action->keyword = DIAMETER; process_diameter(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_diameter; } else if (strcmp(arg[iarg],"dihedral") == 0) { - action->keyword = ANGLE; + action->keyword = DIHEDRAL; process_dihedral(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dihedral; } else if (strcmp(arg[iarg],"dipole") == 0) { - action->keyword = ANGLE; + action->keyword = DIPOLE; process_dipole(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dipole; } else if (strcmp(arg[iarg],"dipole/random") == 0) { - action->keyword = ANGLE; + action->keyword = DIPOLE_RANDOM; process_dipole_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dipole_random; } else if (strcmp(arg[iarg],"dpd/theta") == 0) { - action->keyword = ANGLE; + action->keyword = DPD_THETA; process_dpd_theta(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_dpd_theta; } else if (strcmp(arg[iarg],"edpd/cv") == 0) { - action->keyword = ANGLE; + action->keyword = EDPD_CV; process_edpd_cv(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_edpd_cv; } else if (strcmp(arg[iarg],"edpd/temp") == 0) { - action->keyword = ANGLE; + action->keyword = EDPD_TEMP; process_edpd_temp(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_edpd_temp; } else if (strcmp(arg[iarg],"epsilon") == 0) { - action->keyword = ANGLE; + action->keyword = EPSILON; process_epsilon(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_epsilon; } else if (strcmp(arg[iarg],"image") == 0) { - action->keyword = ANGLE; + action->keyword = IMAGE; process_image(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_image; } else if (strcmp(arg[iarg],"improper") == 0) { - action->keyword = ANGLE; + action->keyword = IMPROPER; process_improper(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_improper; } else if (strcmp(arg[iarg],"length") == 0) { - action->keyword = ANGLE; + action->keyword = LENGTH; process_length(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_length; } else if (strcmp(arg[iarg],"mass") == 0) { - action->keyword = ANGLE; + action->keyword = MASS; process_mass(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_mass; } else if (strcmp(arg[iarg],"mol") == 0) { - action->keyword = ANGLE; + action->keyword = MOLECULE; process_mol(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_mol; } else if (strcmp(arg[iarg],"omega") == 0) { - action->keyword = ANGLE; + action->keyword = OMEGA; process_omega(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_omega; } else if (strcmp(arg[iarg],"quat") == 0) { - action->keyword = ANGLE; + action->keyword = QUAT; process_quat(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_quat; } else if (strcmp(arg[iarg],"quat/random") == 0) { - action->keyword = ANGLE; + action->keyword = QUAT_RANDOM; process_quat_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_quat_random; } else if (strcmp(arg[iarg],"radius/electron") == 0) { - action->keyword = ANGLE; + action->keyword = RADIUS_ELECTRON; process_radius_election(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_radius_election; } else if (strcmp(arg[iarg],"shape") == 0) { - action->keyword = ANGLE; + action->keyword = SHAPE; process_shape(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_shape; } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { - action->keyword = ANGLE; + action->keyword = SMD_CONTACT_RADIUS; process_smd_contact_radius(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_smd_contact_radius; } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { - action->keyword = ANGLE; + action->keyword = SMD_MASS_DENSITY; process_smd_mass_density(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_density; } else if (strcmp(arg[iarg],"sph/cv") == 0) { - action->keyword = ANGLE; + action->keyword = SPH_CV; process_sph_cv(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_sph_cv; } else if (strcmp(arg[iarg],"sph/e") == 0) { - action->keyword = ANGLE; + action->keyword = SPH_E; process_sph_e(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_sph_e; } else if (strcmp(arg[iarg],"sph/rho") == 0) { - action->keyword = ANGLE; + action->keyword = SPH_RHO; process_sph_rho(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_sph_rho; } else if ((strcmp(arg[iarg],"spin/atom") == 0) || (strcmp(arg[iarg],"spin") == 0)) { - action->keyword = ANGLE; + action->keyword = SPIN_ATOM; process_spin_atom(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_spin_atom; } else if ((strcmp(arg[iarg],"spin/atom/random") == 0) || (strcmp(arg[iarg],"spin/random") == 0)) { - action->keyword = ANGLE; + action->keyword = SPIN_ATOM_RANDOM; process_spin_atom_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_spin_atom_random; } else if (strcmp(arg[iarg],"spin/electron") == 0) { - action->keyword = ANGLE; + action->keyword = SPIN_ELECTRON; process_spin_electron(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_spin_electron; } else if (strcmp(arg[iarg],"temperature") == 0) { - action->keyword = ANGLE; + action->keyword = TEMPERATURE; process_temperature(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_temperature; } else if (strcmp(arg[iarg],"theta") == 0) { - action->keyword = ANGLE; + action->keyword = THETA; process_theta(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_theta; } else if (strcmp(arg[iarg],"theta/random") == 0) { - action->keyword = ANGLE; + action->keyword = THETA_RANDOM; process_theta_random(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_theta_random; } else if (strcmp(arg[iarg],"tri") == 0) { - action->keyword = ANGLE; + action->keyword = TRI; process_tri(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_tri; } else if (strcmp(arg[iarg],"type") == 0) { - action->keyword = ANGLE; + action->keyword = TYPE; process_type(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type; } else if (strcmp(arg[iarg],"type/fraction") == 0) { - action->keyword = ANGLE; + action->keyword = TYPE_FRACTION; process_type_fraction(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type_fraction; } else if (strcmp(arg[iarg],"type/ratio") == 0) { - action->keyword = ANGLE; + action->keyword = TYPE_RATIO; process_type_ratio(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type_ratio; } else if (strcmp(arg[iarg],"type/subset") == 0) { - action->keyword = ANGLE; + action->keyword = TYPE_SUBSET; process_type_subset(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_type_subset; } else if (strcmp(arg[iarg],"volume") == 0) { - action->keyword = ANGLE; + action->keyword = VOLUME; process_volume(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_volume; } else if (strcmp(arg[iarg],"vx") == 0) { - action->keyword = ANGLE; + action->keyword = VX; process_vx(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_vx; } else if (strcmp(arg[iarg],"vy") == 0) { - action->keyword = ANGLE; + action->keyword = VY; process_vy(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_vy; } else if (strcmp(arg[iarg],"vz") == 0) { - action->keyword = ANGLE; + action->keyword = VZ; process_vz(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_vz; } else if (strcmp(arg[iarg],"x") == 0) { - action->keyword = ANGLE; + action->keyword = X; process_x(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_x; } else if (strcmp(arg[iarg],"y") == 0) { - action->keyword = ANGLE; + action->keyword = Y; process_y(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_y; } else if (strcmp(arg[iarg],"z") == 0) { - action->keyword = ANGLE; + action->keyword = Z; process_z(iarg,narg,arg); invoke_choice[naction++] = &Set2::invoke_z; @@ -398,7 +398,7 @@ void Set2::process_args(int caller_flag, int narg, char **arg) case QUAT: case IMAGE: if (modify->check_rigid_list_overlap(select)) - error->warning(FLERR,"Changing a property of atoms in rigid bodies " + error->warning(FLERR,"Setting a property of atoms in rigid bodies " "that has no effect unless rigid bodies are re-initialized"); break; default: @@ -414,13 +414,12 @@ void Set2::process_args(int caller_flag, int narg, char **arg) void Set2::invoke_actions() { int nlocal = atom->nlocal; - Action *action; // NOTE: need to create vec1234 ahead of time for (int i = 0; i < naction; i++) { - action = &actions[i]; + Action *action = &actions[i]; // evaluate atom-style variable(s) if necessary @@ -507,7 +506,7 @@ void Set2::setrandom(int keyword) auto avec_body = dynamic_cast(atom->style_match("body")); double **x = atom->x; - int seed = ivalue; + int seed = action->ivalue1; auto ranpark = new RanPark(lmp,1); auto ranmars = new RanMars(lmp,seed + comm->me); @@ -516,7 +515,8 @@ void Set2::setrandom(int keyword) if (keyword == TYPE_FRACTION) { int nlocal = atom->nlocal; - + double fraction = action->dvalue1; + for (i = 0; i < nlocal; i++) if (select[i]) { ranpark->reset(seed,x[i]); @@ -544,9 +544,12 @@ void Set2::setrandom(int keyword) bigint allcount; MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); + bigint nsubset; if (keyword == TYPE_RATIO) { + double fraction = action->dvalue1; nsubset = static_cast (fraction * allcount); } else if (keyword == TYPE_SUBSET) { + nsubset = action->bvalue1; if (nsubset > allcount) error->all(FLERR,"Set type/subset value exceeds eligible atoms"); } @@ -622,7 +625,7 @@ void Set2::setrandom(int keyword) // set spin moments to random orientations in 3d or 2d // spin length is fixed to unity - } else if (keyword == SPIN_RANDOM) { + } else if (keyword == SPIN_ATOM_RANDOM) { double **sp = atom->sp; int nlocal = atom->nlocal; @@ -991,7 +994,7 @@ void Set2::invoke_bond() /* ---------------------------------------------------------------------- */ -// NOT DONE +// DONE void Set2::process_cc(int &iarg, int narg, char **arg) { @@ -999,29 +1002,44 @@ void Set2::process_cc(int &iarg, int narg, char **arg) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); - // NOTE: seems like error to not set cc_index for all 3 cases - // syntax is iarg+1 is index, iarg+2 is value - // doc page does not talk about NULL as valid value - // check package DPD-MESO package examples for tDPD for use of this command - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + Action *action = &actions[naction]; + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 < 1) error->all(FLERR,"Invalid cc index in set command"); + + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],1); else { - cc_index = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (cc_index < 1) error->all(FLERR,"Illegal set command"); + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid cc value in set command"); } iarg += 3; } +// DONE + void Set2::invoke_cc() { int nlocal = atom->nlocal; double **cc = atom->cc; + Action *action = &actions[naction]; + int cc_index = action->ivalue1 - 1; + // NOTE: need to check if cc_index exceeds cc array allocation + + int varflag = action->varflag; + double ccvalue; + if (!action->varflag1) ccvalue = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - cc[i][cc_index-1] = dvalue; + + if (varflag) { + ccvalue = vec1[i]; + if (ccvalue < 0.0) error->all(FLERR,"Invalid cc value in set command"); + } + + cc[i][cc_index] = ccvalue; } } @@ -1096,7 +1114,7 @@ void Set2::process_density(int &iarg, int narg, char **arg) iarg += 2; } -// NOT DONE +// DONE void Set2::invoke_density() { @@ -1116,6 +1134,12 @@ void Set2::invoke_density() auto avec_line = dynamic_cast(atom->style_match("line")); auto avec_tri = dynamic_cast(atom->style_match("tri")); + Action *action = &actions[naction]; + int varflag = action->varflag; + double density; + if (!action->varflag1) density = action->dvalue1; + int discflag = action->ivalue1; + // set rmass via density // if radius > 0.0, treat as sphere or disc // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) @@ -1123,25 +1147,31 @@ void Set2::invoke_density() // if area > 0.0, treat as tri // else set rmass to density directly - // VARIABLE option - for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue <= 0.0) error->one(FLERR,"Invalid density in set command"); + + if (varflag) { + density = vec1[i]; + if (density <= 0.0) error->one(FLERR,"Invalid density in set command"); + } + if (radius_flag && radius[i] > 0.0) - if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * dvalue; - else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * dvalue; + if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * density; + else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * density; + else if (ellipsoid_flag && ellipsoid[i] >= 0) { double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; - // enable 2d ellipse (versus 3d ellipsoid) when time integration + // could enable 2d ellipse (versus 3d ellipsoid) when time integration // options (fix nve/asphere, fix nh/asphere) are also implemented // if (discflag) // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; // else - rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue; + rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * density; + } else if (line_flag && line[i] >= 0) { double length = avec_line->bonus[line[i]].length; - rmass[i] = length * dvalue; + rmass[i] = length * density; + } else if (tri_flag && tri[i] >= 0) { double *c1 = avec_tri->bonus[tri[i]].c1; double *c2 = avec_tri->bonus[tri[i]].c2; @@ -1152,8 +1182,9 @@ void Set2::invoke_density() double norm[3]; MathExtra::cross3(c2mc1,c3mc1,norm); double area = 0.5 * MathExtra::len3(norm); - rmass[i] = area * dvalue; - } else rmass[i] = dvalue; + rmass[i] = area * density; + + } else rmass[i] = density; } } @@ -1250,6 +1281,8 @@ void Set2::process_dipole(int &iarg, int narg, char **arg) iarg += 4; } +// DONE + void Set2::invoke_dipole() { int nlocal = atom->nlocal; @@ -1278,10 +1311,10 @@ void Set2::invoke_dipole() } } -// DONE - /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_dipole_random(int &iarg, int narg, char **arg) { if (!atom->mu_flag) @@ -1329,7 +1362,7 @@ void Set2::process_dpd_theta(int &iarg, int narg, char **arg) iarg += 2; } -// NOT DONE +// DONE void Set2::invoke_dpd_theta() { @@ -1344,12 +1377,22 @@ void Set2::invoke_dpd_theta() double onemass; double vx,vy,vz; - // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting + Action *action = &actions[naction]; + int varflag = action->varflag; + double theta; + if (!action->varflag1) theta = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue >= 0.0) dpdTheta[i] = dvalue; + if (varflag) { + theta = vec1[i]; + if (theta < 0.0) error->one(FLERR,"Invalid dpd/theta value in set command"); + } + + // if theta is negative, NULL was used, set dpdTheta to KE of particle + + if (theta >= 0.0) dpdTheta[i] = theta; else { if (rmass) onemass = rmass[i]; else onemass = mass[type[i]]; @@ -1373,8 +1416,7 @@ void Set2::process_edpd_cv(int &iarg, int narg, char **arg) Action *action = &actions[naction]; - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else 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 { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/cv value in set command"); @@ -1383,7 +1425,7 @@ void Set2::process_edpd_cv(int &iarg, int narg, char **arg) iarg += 2; } -// NOT DONE +// DONE void Set2::invoke_edpd_cv() { @@ -1395,8 +1437,6 @@ void Set2::invoke_edpd_cv() double cv; if (!action->varflag1) cv = action->dvalue1; - // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting - for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1421,8 +1461,7 @@ void Set2::process_edpd_temp(int &iarg, int narg, char **arg) Action *action = &actions[naction]; - if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; - else 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 { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/temp value in set command"); @@ -1430,19 +1469,27 @@ void Set2::process_edpd_temp(int &iarg, int narg, char **arg) iarg += 2; } -// NOT DONE +// DONE void Set2::invoke_edpd_temp() { int nlocal = atom->nlocal; double *edpd_temp = atom->edpd_temp; - // VARIABLE option or NULL to set temp to KE of particle - // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting - + Action *action = &actions[naction]; + int varflag = action->varflag; + double temp; + if (!action->varflag1) temp = action->dvalue1; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - edpd_temp[i] = dvalue; + + if (varflag) { + temp = vec1[i]; + if (temp < 0.0) error->one(FLERR,"Invalid edpd/temp value in set command"); + } + + edpd_temp[i] = temp; } } @@ -1458,17 +1505,16 @@ void Set2::process_epsilon(int &iarg, int narg, char **arg) Action *action = &actions[naction]; - if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; - else 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 { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid epsilon in set command"); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid epsilon in set command"); } iarg += 2; } -// NOT DONE +// DONE void Set2::invoke_epsilon() { @@ -1477,83 +1523,115 @@ void Set2::invoke_epsilon() double *q = atom->q; double *q_scaled = atom->q_scaled; + Action *action = &actions[naction]; + int varflag = action->varflag; + double eps; + if (!action->varflag1) eps = action->dvalue1; + // assign local dielectric constant // also update scaled charge value - // VARIABLE option - // is doc page correct then dvalue1 = -1.0 ? i.e. NULL setting - for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - // NOTE: should it be error if dvalue < 0.0 ? - if (dvalue >= 0.0) { - epsilon[i] = dvalue; - q_scaled[i] = q[i] / dvalue; + + if (varflag) { + eps = vec1[i]; + if (eps <= 0.0) error->one(FLERR,"Invalid epsilon in set command"); } + + epsilon[i] = eps; + q_scaled[i] = q[i] / eps; } } /* ---------------------------------------------------------------------- */ -// NOT DONE +// DONE void Set2::process_image(int &iarg, int narg, char **arg) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); Action *action = &actions[naction]; - - ximageflag = yimageflag = zimageflag = 0; - if (strcmp(arg[iarg+1],"NULL") != 0) { - ximageflag = 1; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ximage = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - } - if (strcmp(arg[iarg+2],"NULL") != 0) { - yimageflag = 1; - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yimage = utils::inumeric(FLERR,arg[iarg+2],false,lmp); - } - if (strcmp(arg[iarg+3],"NULL") != 0) { - zimageflag = 1; - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zimage = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + + if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue4 = 0; + else { + action->ivalue4 = 1; + if (utils::strmatch(arg[iarg+1],"^v_")) { + if (!domain->xperiodic) + error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); + varparse(arg[iarg+1],1); + } else { + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 && !domain->xperiodic) + error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); + } } - if (ximageflag && ximage && !domain->xperiodic) - error->all(FLERR, - "Cannot set non-zero image flag for non-periodic dimension"); - if (yimageflag && yimage && !domain->yperiodic) - error->all(FLERR, - "Cannot set non-zero image flag for non-periodic dimension"); - if (zimageflag && zimage && !domain->zperiodic) - error->all(FLERR, - "Cannot set non-zero image flag for non-periodic dimension"); + if (strcmp(arg[iarg+2],"NULL") == 0) action->ivalue5 = 0; + else { + action->ivalue5 = 1; + if (utils::strmatch(arg[iarg+2],"^v_")) { + if (!domain->yperiodic) + error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); + varparse(arg[iarg+2],2); + } else { + action->ivalue2 = utils::inumeric(FLERR,arg[iarg+2],false,lmp); + if (action->ivalue2 && !domain->yperiodic) + error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); + } + } + + if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue6 = 0; + else { + action->ivalue6 = 1; + if (utils::strmatch(arg[iarg+3],"^v_")) { + if (!domain->zperiodic) + error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); + varparse(arg[iarg+3],3); + } else { + action->ivalue3 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue3 && !domain->zperiodic) + error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); + } + } iarg += 4; } -// NOT DONE - +// DONE + void Set2::invoke_image() { int nlocal = atom->nlocal; imageint *image = atom->image; - int xbox,ybox,zbox; + Action *action = &actions[naction]; + int ximageflag = action->ivalue4; + int yimageflag = action->ivalue5; + int zimageflag = action->ivalue6; + + int varflag = action->varflag; + int ximage,yimage,zimage; + if (!action->varflag1) ximage = action->ivalue1; + if (!action->varflag2) yimage = action->ivalue2; + if (!action->varflag3) zimage = action->ivalue3; + // reset any or all of 3 image flags - Action *action = &actions[naction]; - for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) ximage = static_cast (vec1[i]); + if (action->varflag2) yimage = static_cast (vec2[i]); + if (action->varflag3) zimage = static_cast (vec3[i]); + } + xbox = (image[i] & IMGMASK) - IMGMAX; ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; zbox = (image[i] >> IMG2BITS) - IMGMAX; - if (action->varflag1) ximage = static_cast(xvalue); - if (action->varflag2) yimage = static_cast(yvalue); - if (action->varflag3) zimage = static_cast(zvalue); if (ximageflag) xbox = ximage; if (yimageflag) ybox = yimage; if (zimageflag) zbox = zimage; @@ -1767,15 +1845,13 @@ void Set2::invoke_omega() if (!action->varflag2) yvalue = action->dvalue2; if (!action->varflag3) zvalue = action->dvalue3; - // VARIABLE option - for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) { if (action->varflag1) xvalue = vec1[i]; - if (action->varflag1) yvalue = vec2[i]; - if (action->varflag1) zvalue = vec3[i]; + if (action->varflag2) yvalue = vec2[i]; + if (action->varflag3) zvalue = vec3[i]; } omega[i][0] = xvalue; @@ -1793,13 +1869,22 @@ void Set2::process_quat(int &iarg, int narg, char **arg) if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); + int dimension = domain->dimension; Action *action = &actions[naction]; if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dimension == 2 && action->dvalue1 != 0.0) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + } if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + else { + action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (dimension == 2 && action->dvalue2 != 0.0) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + } if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); @@ -1808,7 +1893,7 @@ void Set2::process_quat(int &iarg, int narg, char **arg) iarg += 5; } -// NOT DONE +// DONE void Set2::invoke_quat() { @@ -1824,37 +1909,47 @@ void Set2::invoke_quat() auto avec_body = dynamic_cast(atom->style_match("body")); int dimension = domain->dimension; - double theta2,sintheta2; + double radians,sintheta; double *quat_one; - // VARIABLE option - + Action *action = &actions[naction]; + int varflag = action->varflag; + double xvalue,yvalue,zvalue,theta; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + if (!action->varflag4) theta = action->dvalue4; + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (avec_ellipsoid && ellipsoid[i] >= 0) - quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; - else if (avec_tri && tri[i] >= 0) - quat_one = avec_tri->bonus[tri[i]].quat; - else if (avec_body && body[i] >= 0) - quat_one = avec_body->bonus[body[i]].quat; - else if (quat_flag) - quat_one = quat[i]; - else - error->one(FLERR,"Cannot set quaternion for atom that has none"); - - // quat rotation vector must be only in z dir for 2d systems + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_tri && tri[i] >= 0) + quat_one = avec_tri->bonus[tri[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag2) yvalue = vec2[i]; + if (action->varflag3) zvalue = vec3[i]; + if (action->varflag4) theta = vec4[i]; if (dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + } - theta2 = MY_PI2 * wvalue/180.0; - sintheta2 = sin(theta2); - quat_one[0] = cos(theta2); - quat_one[1] = xvalue * sintheta2; - quat_one[2] = yvalue * sintheta2; - quat_one[3] = zvalue * sintheta2; - MathExtra::qnormalize(quat_one); + radians = MY_PI2 * theta/180.0; + sintheta = sin(radians); + quat_one[0] = cos(radians); + quat_one[1] = xvalue * sintheta; + quat_one[2] = yvalue * sintheta; + quat_one[3] = zvalue * sintheta; + MathExtra::qnormalize(quat_one); } } @@ -2271,28 +2366,32 @@ void Set2::invoke_spin_atom() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) { + if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin/random is deprecated -- use spin/atom/random instead"); if (!atom->sp_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); + + Action *action = &actions[naction]; + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin/random is deprecated. " - "Please use spin/atom/random instead."); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed {} in set {} command", ivalue, arg[iarg]); - if (dvalue <= 0.0) - error->all(FLERR,"Invalid spin magnitude {} in set {} command", dvalue, arg[iarg]); + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); iarg += 3; } +// DONE + void Set2::invoke_spin_atom_random() { - setrandom(SPIN_RANDOM); + setrandom(SPIN_ATOM_RANDOM); } /* ---------------------------------------------------------------------- */ @@ -2454,6 +2553,8 @@ void Set2::invoke_theta_random() /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_tri(int &iarg, int narg, char **arg) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); @@ -2464,6 +2565,8 @@ void Set2::process_tri(int &iarg, int narg, char **arg) iarg += 2; } +// NOT DONE + void Set2::invoke_tri() { int nlocal = atom->nlocal; @@ -2473,7 +2576,7 @@ void Set2::invoke_tri() for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (dvalue < 0.0) error->one(FLERR,"Invalid tri size in set command"); + //if (dvalue < 0.0) error->one(FLERR,"Invalid tri size in set command"); avec_tri->set_equilateral(i,dvalue); } @@ -2485,18 +2588,22 @@ void Set2::invoke_tri() /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_type(int &iarg, int narg, char **arg) { 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 { char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + //ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; } iarg += 2; } +// NOT DONE + void Set2::invoke_type() { int nlocal = atom->nlocal; @@ -2507,21 +2614,24 @@ void Set2::invoke_type() for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (action->varflag) - if (ivalue <= 0 || ivalue > atom->ntypes) + if (action->ivalue1 <= 0 || action->ivalue1 > atom->ntypes) error->one(FLERR,"Invalid value in set command"); - type[i] = ivalue; + type[i] = action->ivalue1; } } /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_type_fraction(int &iarg, int narg, char **arg) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); 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); + double fraction = utils::numeric(FLERR,arg[iarg+2],false,lmp); + int ivalue; ivalue = utils::inumeric(FLERR,arg[iarg+3],false,lmp); if (newtype <= 0 || newtype > atom->ntypes) error->all(FLERR,"Invalid type value {} in set type/fraction command", newtype); @@ -2539,6 +2649,8 @@ void Set2::invoke_type_fraction() /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_type_ratio(int &iarg, int narg, char **arg) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error); @@ -2563,6 +2675,8 @@ void Set2::invoke_type_ratio() /* ---------------------------------------------------------------------- */ +// NOT DONE + void Set2::process_type_subset(int &iarg, int narg, char **arg) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error); @@ -2842,6 +2956,8 @@ void Set2::invoke_z() /* ---------------------------------------------------------------------- */ +// DONE + void Set2::process_custom(int &iarg, int narg, char **arg) { int flag,cols; @@ -2854,13 +2970,14 @@ void Set2::process_custom(int &iarg, int narg, char **arg) error->all(FLERR,"Set keyword or custom property {} does not exist",pname); Action *action = &actions[naction]; + action->ivalue2 = index_custom; switch (argi.get_type()) { case ArgInfo::INAME: - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (flag != 0) error->all(FLERR,"Set command custom property {} is not integer",pname); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (argi.get_dim() == 0) { if (cols > 0) @@ -2869,18 +2986,19 @@ void Set2::process_custom(int &iarg, int narg, char **arg) } else if (argi.get_dim() == 1) { if (cols == 0) error->all(FLERR,"Set command custom integer property {} is not an array",pname); - icol_custom = argi.get_index1(); + int icol_custom = argi.get_index1(); if (icol_custom <= 0 || icol_custom > cols) error->all(FLERR,"Set command per-atom custom integer array {} is accessed " "out-of-range",pname); + action->ivalue3 = icol_custom; action->keyword = IARRAY; } else error->all(FLERR,"Illegal set command"); break; case ArgInfo::DNAME: - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (flag != 1) error->all(FLERR,"Custom property {} is not floating-point",argi.get_name()); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (argi.get_dim() == 0) { if (cols > 0) @@ -2889,10 +3007,11 @@ void Set2::process_custom(int &iarg, int narg, char **arg) } else if (argi.get_dim() == 1) { if (cols == 0) error->all(FLERR,"Set command custom double property {} is not an array",pname); - icol_custom = argi.get_index1(); + int icol_custom = argi.get_index1(); if (icol_custom <= 0 || icol_custom > cols) error->all(FLERR,"Set command per-atom custom double array {} is " "accessed out-of-range",pname); + action->ivalue3 = icol_custom; action->keyword = DARRAY; } else error->all(FLERR,"Illegal set command"); break; @@ -2905,37 +3024,54 @@ void Set2::process_custom(int &iarg, int narg, char **arg) iarg += 2; } +// DONE + void Set2::invoke_custom() { int nlocal = atom->nlocal; - + int ivalue; + double dvalue; + Action *action = &actions[naction]; - - // NOTE: what about icol_custom + int varflag = action->varflag; + int index_custom = action->ivalue2; if (action->keyword == IVEC) { + if (!varflag) ivalue = action->ivalue1; int *ivector = atom->ivector[index_custom]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + if (varflag) ivalue = static_cast (vec1[i]); ivector[i] = ivalue; } + } else if (action->keyword == DVEC) { + if (!varflag) dvalue = action->dvalue1; double *dvector = atom->dvector[index_custom]; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; + if (varflag) dvalue = vec1[i]; dvector[i] = dvalue; } + } else if (action->keyword == IARRAY) { + if (!varflag) ivalue = action->ivalue1; int **iarray = atom->iarray[index_custom]; + int icol_custom = action->ivalue3 - 1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - iarray[i][icol_custom-1] = ivalue; + if (varflag) ivalue = static_cast (vec1[i]); + iarray[i][icol_custom] = ivalue; } + } else if (action->keyword == DARRAY) { + if (!varflag) dvalue = action->dvalue1; double **darray = atom->darray[index_custom]; + int icol_custom = action->ivalue3 - 1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - darray[i][icol_custom-1] = dvalue; + if (varflag) dvalue = vec1[i]; + darray[i][icol_custom] = dvalue; } } } diff --git a/src/set2.h b/src/set2.h index bbb811d236..f0d64a0175 100644 --- a/src/set2.h +++ b/src/set2.h @@ -47,15 +47,6 @@ class Set2 : public Command { int groupbit; class Region *region; - // atom property setting params for keyword/value pairs - - int ivalue, newtype, count, index_custom, icol_custom; - int ximage, yimage, zimage, ximageflag, yimageflag, zimageflag; - int cc_index; - bigint nsubset; - double dvalue, xvalue, yvalue, zvalue, wvalue, fraction; - int discflag; - // one Action = one keyword/value pair struct Action { @@ -63,13 +54,14 @@ class Set2 : public Command { int varflag; int varflag1, varflag2, varflag3, varflag4; int ivar1, ivar2, ivar3, ivar4; - int ivalue1; + int ivalue1, ivalue2, ivalue3, ivalue4, ivalue5, ivalue6; tagint tvalue1; double dvalue1,dvalue2,dvalue3,dvalue4; }; int naction,maxaction; Action *actions; + Action *action; typedef void (Set2::*FnPtrPack)(); FnPtrPack *invoke_choice; // list of ptrs to invoke functions From 1d64be30d9ce57d1319e6fb5d7350e4cfc847a36 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Thu, 30 Nov 2023 10:42:59 -0700 Subject: [PATCH 06/26] finished initial refactoring Set class --- src/set2.cpp | 1164 +++++++++++++++++++++----------------------------- src/set2.h | 220 +++++----- 2 files changed, 589 insertions(+), 795 deletions(-) diff --git a/src/set2.cpp b/src/set2.cpp index 579861c419..5c9548498c 100644 --- a/src/set2.cpp +++ b/src/set2.cpp @@ -42,7 +42,7 @@ using namespace LAMMPS_NS; using namespace MathConst; -enum{SET,FIXSET}; +enum{SETCOMMAND,FIXSET}; enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; @@ -59,8 +59,19 @@ enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, /* ---------------------------------------------------------------------- */ +Set2::Set2(class LAMMPS *lmp) : Command(lmp) +{ + select = nullptr; +} + +/* ---------------------------------------------------------------------- */ + Set2::~Set2() { + memory->destroy(select); + + // DELELTE Actions + memory->destroy(vec1); memory->destroy(vec2); memory->destroy(vec3); @@ -76,10 +87,9 @@ void Set2::command(int narg, char **arg) if (atom->natoms == 0) error->all(FLERR,"Set command on system without atoms"); - select = nullptr; - - process_args(SET,narg-3,&arg[3]); - + int iarg = process_args(SETCOMMAND,narg-3,&arg[3]); + if (iarg + 3 != narg) error->all(FLERR,"Illegal set command keyword"); + if (comm->me == 0) utils::logmesg(lmp,"Setting atom values ...\n"); selection(atom->nlocal); @@ -88,35 +98,38 @@ void Set2::command(int narg, char **arg) invoke_actions(); - // statistics + // print stats for each action // for CC option, include species index - int origarg; - - int count,allcount; - MPI_Allreduce(&count,&allcount,1,MPI_INT,MPI_SUM,world); - - if (comm->me == 0) { - if (strcmp(arg[origarg],"cc") == 0) - utils::logmesg(lmp," {} settings made for {} index {}\n", - allcount,arg[origarg],arg[origarg+1]); - else - utils::logmesg(lmp," {} settings made for {}\n", - allcount,arg[origarg]); + bigint bcount,allcount; + + for (int i = 0; i < naction; i++) { + Action *action = &actions[i]; + int iarg = action->argindex; + + if (action->count_action < 0) bcount = action->count_select; + else bcount = action->count_action; + MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); + + if (comm->me == 0) { + if (strcmp(arg[iarg],"cc") == 0) + utils::logmesg(lmp," {} settings made for {} index {}\n", + allcount,arg[iarg],arg[iarg+1]); + else + utils::logmesg(lmp," {} settings made for {}\n", + allcount,arg[iarg]); + } } - - // clean up - - memory->destroy(select); } /* ---------------------------------------------------------------------- set an owned atom property randomly set seed based on atom coordinates make atom result independent of what proc owns it + return iarg = index of next arg to process (could be none left) ------------------------------------------------------------------------- */ -void Set2::process_args(int caller_flag, int narg, char **arg) +int Set2::process_args(int caller_flag, int narg, char **arg) { caller = caller_flag; @@ -178,212 +191,213 @@ void Set2::process_args(int caller_flag, int narg, char **arg) } action = &actions[naction]; + action->argindex = iarg; action->varflag = 0; action->varflag1 = action->varflag2 = action->varflag3 = action->varflag4 = 0; if (strcmp(arg[iarg],"angle") == 0) { action->keyword = ANGLE; - process_angle(iarg,narg,arg); + process_angle(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_angle; } else if (strcmp(arg[iarg],"angmom") == 0) { action->keyword = ANGMOM; - process_angmom(iarg,narg,arg); + process_angmom(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_angmom; } else if (strcmp(arg[iarg],"bond") == 0) { action->keyword = BOND; - process_bond(iarg,narg,arg); + process_bond(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_bond; } else if (strcmp(arg[iarg],"cc") == 0) { action->keyword = CC; - process_cc(iarg,narg,arg); + process_cc(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_cc; } else if (strcmp(arg[iarg],"charge") == 0) { action->keyword = CHARGE; - process_charge(iarg,narg,arg); + process_charge(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_charge; } else if (strcmp(arg[iarg],"density") == 0 ||(strcmp(arg[iarg],"density/disc") == 0)) { action->keyword = DENSITY; - process_density(iarg,narg,arg); + process_density(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_density; } else if (strcmp(arg[iarg],"diameter") == 0) { action->keyword = DIAMETER; - process_diameter(iarg,narg,arg); + process_diameter(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_diameter; } else if (strcmp(arg[iarg],"dihedral") == 0) { action->keyword = DIHEDRAL; - process_dihedral(iarg,narg,arg); + process_dihedral(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_dihedral; } else if (strcmp(arg[iarg],"dipole") == 0) { action->keyword = DIPOLE; - process_dipole(iarg,narg,arg); + process_dipole(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_dipole; } else if (strcmp(arg[iarg],"dipole/random") == 0) { action->keyword = DIPOLE_RANDOM; - process_dipole_random(iarg,narg,arg); + process_dipole_random(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_dipole_random; } else if (strcmp(arg[iarg],"dpd/theta") == 0) { action->keyword = DPD_THETA; - process_dpd_theta(iarg,narg,arg); + process_dpd_theta(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_dpd_theta; } else if (strcmp(arg[iarg],"edpd/cv") == 0) { action->keyword = EDPD_CV; - process_edpd_cv(iarg,narg,arg); + process_edpd_cv(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_edpd_cv; } else if (strcmp(arg[iarg],"edpd/temp") == 0) { action->keyword = EDPD_TEMP; - process_edpd_temp(iarg,narg,arg); + process_edpd_temp(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_edpd_temp; } else if (strcmp(arg[iarg],"epsilon") == 0) { action->keyword = EPSILON; - process_epsilon(iarg,narg,arg); + process_epsilon(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_epsilon; } else if (strcmp(arg[iarg],"image") == 0) { action->keyword = IMAGE; - process_image(iarg,narg,arg); + process_image(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_image; } else if (strcmp(arg[iarg],"improper") == 0) { action->keyword = IMPROPER; - process_improper(iarg,narg,arg); + process_improper(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_improper; } else if (strcmp(arg[iarg],"length") == 0) { action->keyword = LENGTH; - process_length(iarg,narg,arg); + process_length(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_length; } else if (strcmp(arg[iarg],"mass") == 0) { action->keyword = MASS; - process_mass(iarg,narg,arg); + process_mass(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_mass; } else if (strcmp(arg[iarg],"mol") == 0) { action->keyword = MOLECULE; - process_mol(iarg,narg,arg); + process_mol(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_mol; } else if (strcmp(arg[iarg],"omega") == 0) { action->keyword = OMEGA; - process_omega(iarg,narg,arg); + process_omega(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_omega; } else if (strcmp(arg[iarg],"quat") == 0) { action->keyword = QUAT; - process_quat(iarg,narg,arg); + process_quat(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_quat; } else if (strcmp(arg[iarg],"quat/random") == 0) { action->keyword = QUAT_RANDOM; - process_quat_random(iarg,narg,arg); + process_quat_random(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_quat_random; } else if (strcmp(arg[iarg],"radius/electron") == 0) { action->keyword = RADIUS_ELECTRON; - process_radius_election(iarg,narg,arg); + process_radius_election(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_radius_election; } else if (strcmp(arg[iarg],"shape") == 0) { action->keyword = SHAPE; - process_shape(iarg,narg,arg); + process_shape(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_shape; } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { action->keyword = SMD_CONTACT_RADIUS; - process_smd_contact_radius(iarg,narg,arg); + process_smd_contact_radius(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_smd_contact_radius; } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { action->keyword = SMD_MASS_DENSITY; - process_smd_mass_density(iarg,narg,arg); + process_smd_mass_density(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_density; } else if (strcmp(arg[iarg],"sph/cv") == 0) { action->keyword = SPH_CV; - process_sph_cv(iarg,narg,arg); + process_sph_cv(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_sph_cv; } else if (strcmp(arg[iarg],"sph/e") == 0) { action->keyword = SPH_E; - process_sph_e(iarg,narg,arg); + process_sph_e(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_sph_e; } else if (strcmp(arg[iarg],"sph/rho") == 0) { action->keyword = SPH_RHO; - process_sph_rho(iarg,narg,arg); + process_sph_rho(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_sph_rho; } else if ((strcmp(arg[iarg],"spin/atom") == 0) || (strcmp(arg[iarg],"spin") == 0)) { action->keyword = SPIN_ATOM; - process_spin_atom(iarg,narg,arg); + process_spin_atom(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_spin_atom; } else if ((strcmp(arg[iarg],"spin/atom/random") == 0) || (strcmp(arg[iarg],"spin/random") == 0)) { action->keyword = SPIN_ATOM_RANDOM; - process_spin_atom_random(iarg,narg,arg); + process_spin_atom_random(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_spin_atom_random; } else if (strcmp(arg[iarg],"spin/electron") == 0) { action->keyword = SPIN_ELECTRON; - process_spin_electron(iarg,narg,arg); + process_spin_electron(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_spin_electron; } else if (strcmp(arg[iarg],"temperature") == 0) { action->keyword = TEMPERATURE; - process_temperature(iarg,narg,arg); + process_temperature(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_temperature; } else if (strcmp(arg[iarg],"theta") == 0) { action->keyword = THETA; - process_theta(iarg,narg,arg); + process_theta(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_theta; } else if (strcmp(arg[iarg],"theta/random") == 0) { action->keyword = THETA_RANDOM; - process_theta_random(iarg,narg,arg); + process_theta_random(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_theta_random; } else if (strcmp(arg[iarg],"tri") == 0) { action->keyword = TRI; - process_tri(iarg,narg,arg); + process_tri(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_tri; } else if (strcmp(arg[iarg],"type") == 0) { action->keyword = TYPE; - process_type(iarg,narg,arg); + process_type(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_type; } else if (strcmp(arg[iarg],"type/fraction") == 0) { action->keyword = TYPE_FRACTION; - process_type_fraction(iarg,narg,arg); + process_type_fraction(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_type_fraction; } else if (strcmp(arg[iarg],"type/ratio") == 0) { action->keyword = TYPE_RATIO; - process_type_ratio(iarg,narg,arg); + process_type_ratio(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_type_ratio; } else if (strcmp(arg[iarg],"type/subset") == 0) { action->keyword = TYPE_SUBSET; - process_type_subset(iarg,narg,arg); + process_type_subset(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_type_subset; } else if (strcmp(arg[iarg],"volume") == 0) { action->keyword = VOLUME; - process_volume(iarg,narg,arg); + process_volume(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_volume; } else if (strcmp(arg[iarg],"vx") == 0) { action->keyword = VX; - process_vx(iarg,narg,arg); + process_vx(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_vx; } else if (strcmp(arg[iarg],"vy") == 0) { action->keyword = VY; - process_vy(iarg,narg,arg); + process_vy(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_vy; } else if (strcmp(arg[iarg],"vz") == 0) { action->keyword = VZ; - process_vz(iarg,narg,arg); + process_vz(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_vz; } else if (strcmp(arg[iarg],"x") == 0) { action->keyword = X; - process_x(iarg,narg,arg); + process_x(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_x; } else if (strcmp(arg[iarg],"y") == 0) { action->keyword = Y; - process_y(iarg,narg,arg); + process_y(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_y; } else if (strcmp(arg[iarg],"z") == 0) { action->keyword = Z; - process_z(iarg,narg,arg); + process_z(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_z; } else if (utils::strmatch(arg[iarg],"^[id]2?_")) { - process_custom(iarg,narg,arg); + process_custom(iarg,narg,arg,action); invoke_choice[naction++] = &Set2::invoke_custom; - } else { - error->all(FLERR,"Illegal set command keyword"); - } + // just exit with unrecognized keyword + + } else break; } // check keywords for properties that are part of rigid body data // error if selection includes atoms in rigid bodies // assume no conflict for properties not in list of cases - for (int i = 0; i < naction; i++) + for (int i = 0; i < naction; i++) { switch (actions[i].keyword) { case X: case Y: @@ -404,44 +418,12 @@ void Set2::process_args(int caller_flag, int narg, char **arg) default: break; } -} - -/* ---------------------------------------------------------------------- - loop over list of actions - perform each on all selected atoms via call to invoke_choice() method -------------------------------------------------------------------------- */ - -void Set2::invoke_actions() -{ - int nlocal = atom->nlocal; - - // NOTE: need to create vec1234 ahead of time - - for (int i = 0; i < naction; i++) { - - Action *action = &actions[i]; - - // evaluate atom-style variable(s) if necessary - - if (action->varflag) { - if (action->varflag1) { - input->variable->compute_atom(action->ivar1,0,vec1,1,0); - } - if (action->varflag2) { - input->variable->compute_atom(action->ivar2,0,vec2,1,0); - } - if (action->varflag3) { - input->variable->compute_atom(action->ivar3,0,vec3,1,0); - } - if (action->varflag4) { - input->variable->compute_atom(action->ivar4,0,vec4,1,0); - } - } - - // invoke the action to reset per-atom values - - (this->*invoke_choice[i])(); } + + // return index to next arg to process + // fix set command may append its own options + + return iarg; } /* ---------------------------------------------------------------------- @@ -486,8 +468,83 @@ void Set2::selection(int n) else select[i] = 0; } - // NOTE: could count selected atoms here and output for caller = SET + // count_select = count of selected owned atoms + + count_select = 0; + for (int i = 0; i < n; i++) + if (select[i]) count_select++; +} + +/* ---------------------------------------------------------------------- + loop over list of actions + perform each on all selected atoms via call to invoke_choice() method +------------------------------------------------------------------------- */ + +void Set2::invoke_actions() +{ + int nlocal = atom->nlocal; + + // NOTE: need to create vec1234 ahead of time + for (int i = 0; i < naction; i++) { + + Action *action = &actions[i]; + + // use count_action to optionally override count_select + // if stays -1, count_select is used by caller + // if overwritten by an invoke method, count_action is used + // only a handful of invoke methods tally their own count + + count_action = -1; + + // evaluate atom-style variable(s) if necessary + + if (action->varflag) { + if (action->varflag1) { + input->variable->compute_atom(action->ivar1,0,vec1,1,0); + } + if (action->varflag2) { + input->variable->compute_atom(action->ivar2,0,vec2,1,0); + } + if (action->varflag3) { + input->variable->compute_atom(action->ivar3,0,vec3,1,0); + } + if (action->varflag4) { + input->variable->compute_atom(action->ivar4,0,vec4,1,0); + } + } + + // invoke the action to reset per-atom or per-topology values + + (this->*invoke_choice[i])(action); + + action->count_select = count_select; + action->count_action = count_action; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set2::varparse(const char *name, int m) +{ + int ivar = input->variable->find(name+2); + if (ivar < 0) + error->all(FLERR,"Variable name {} for set command does not exist", name); + if (!input->variable->atomstyle(ivar)) + error->all(FLERR,"Variable {} for set command is invalid style", name); + + Action *action = &actions[naction]; + action->varflag = 1; + + if (m == 1) { + action->varflag1 = 1; action->ivar1 = ivar; + } else if (m == 2) { + action->varflag2 = 1; action->ivar2 = ivar; + } else if (m == 3) { + action->varflag3 = 1; action->ivar3 = ivar; + } else if (m == 4) { + action->varflag4 = 1; action->ivar4 = ivar; + } } /* ---------------------------------------------------------------------- @@ -496,7 +553,7 @@ void Set2::selection(int n) make atom result independent of what proc owns it ------------------------------------------------------------------------- */ -void Set2::setrandom(int keyword) +void Set2::setrandom(int keyword, Action *action) { int i; @@ -506,7 +563,10 @@ void Set2::setrandom(int keyword) auto avec_body = dynamic_cast(atom->style_match("body")); double **x = atom->x; - int seed = action->ivalue1; + + // seed is always set to ivalue1 in process() methods + + int seed = action->ivalue1; auto ranpark = new RanPark(lmp,1); auto ranmars = new RanMars(lmp,seed + comm->me); @@ -516,6 +576,8 @@ void Set2::setrandom(int keyword) if (keyword == TYPE_FRACTION) { int nlocal = atom->nlocal; double fraction = action->dvalue1; + int newtype = action->ivalue2; + int count = 0; for (i = 0; i < nlocal; i++) if (select[i]) { @@ -524,6 +586,8 @@ void Set2::setrandom(int keyword) atom->type[i] = newtype; count++; } + + count_action = count; // set exact count of atom types to newtype // for TYPE_RATIO, exact = fraction out of total eligible @@ -531,16 +595,11 @@ void Set2::setrandom(int keyword) } else if (keyword == TYPE_RATIO || keyword == TYPE_SUBSET) { int nlocal = atom->nlocal; + int newtype = action->ivalue2; - // count = number of eligible atoms I own + // convert specified fraction to nsubset of all selected atoms - count = 0; - for (i = 0; i < nlocal; i++) - if (select[i]) count++; - - // convert specified fraction to nsubset - - bigint bcount = count; + bigint bcount = count_select; bigint allcount; MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); @@ -556,16 +615,17 @@ void Set2::setrandom(int keyword) // make selection - int *flag = memory->create(flag,count,"set:flag"); - int *work = memory->create(work,count,"set:work"); + int *flag = memory->create(flag,count_select,"set:flag"); + int *work = memory->create(work,count_select,"set:work"); - ranmars->select_subset(nsubset,count,flag,work); + ranmars->select_subset(nsubset,count_select,flag,work); // change types of selected atoms // flag vector from select_subset() is only for eligible atoms - count = 0; + int count = 0; int eligible = 0; + for (i = 0; i < nlocal; i++) { if (!select[i]) continue; if (flag[eligible]) { @@ -574,7 +634,9 @@ void Set2::setrandom(int keyword) } eligible++; } - + + count_action = count; + // clean up memory->destroy(flag); @@ -586,7 +648,7 @@ void Set2::setrandom(int keyword) } else if (keyword == DIPOLE_RANDOM) { double **mu = atom->mu; int nlocal = atom->nlocal; - + double dmag = action->dvalue1; double msq,scale; if (domain->dimension == 3) { @@ -597,12 +659,11 @@ void Set2::setrandom(int keyword) mu[i][1] = ranpark->uniform() - 0.5; mu[i][2] = ranpark->uniform() - 0.5; msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]; - scale = dvalue/sqrt(msq); + scale = dmag/sqrt(msq); mu[i][0] *= scale; mu[i][1] *= scale; mu[i][2] *= scale; - mu[i][3] = dvalue; - count++; + mu[i][3] = dmag; } } else { @@ -613,24 +674,22 @@ void Set2::setrandom(int keyword) mu[i][1] = ranpark->uniform() - 0.5; mu[i][2] = 0.0; msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1]; - scale = dvalue/sqrt(msq); + scale = dmag/sqrt(msq); mu[i][0] *= scale; mu[i][1] *= scale; - mu[i][3] = dvalue; - count++; + mu[i][3] = dmag; } } - // set spin moments to random orientations in 3d or 2d // spin length is fixed to unity } else if (keyword == SPIN_ATOM_RANDOM) { double **sp = atom->sp; int nlocal = atom->nlocal; - + double dlen = action->dvalue1; double sp_sq,scale; - + if (domain->dimension == 3) { for (i = 0; i < nlocal; i++) if (select[i]) { @@ -643,8 +702,7 @@ void Set2::setrandom(int keyword) sp[i][0] *= scale; sp[i][1] *= scale; sp[i][2] *= scale; - sp[i][3] = dvalue; - count++; + sp[i][3] = dlen; } } else { @@ -658,30 +716,33 @@ void Set2::setrandom(int keyword) scale = 1.0/sqrt(sp_sq); sp[i][0] *= scale; sp[i][1] *= scale; - sp[i][3] = dvalue; - count++; + sp[i][3] = dlen; } } // set quaternions to random orientations in 3d and 2d } else if (keyword == QUAT_RANDOM) { + int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; + int *body = atom->body; + double **quat = atom->quat; int nlocal = atom->nlocal; - double *quat; - double **quat2; - + int quat_flag = atom->quat_flag; + double *quat_one; + if (domain->dimension == 3) { double s,t1,t2,theta1,theta2; for (i = 0; i < nlocal; i++) if (select[i]) { - if (avec_ellipsoid && atom->ellipsoid[i] >= 0) - quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; - else if (avec_tri && atom->tri[i] >= 0) - quat = avec_tri->bonus[atom->tri[i]].quat; - else if (avec_body && atom->body[i] >= 0) - quat = avec_body->bonus[atom->body[i]].quat; - else if (atom->quat_flag) - quat2 = atom->quat; + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_tri && tri[i] >= 0) + quat_one = avec_tri->bonus[tri[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; else error->one(FLERR,"Cannot set quaternion for atom that has none"); @@ -691,61 +752,46 @@ void Set2::setrandom(int keyword) t2 = sqrt(s); theta1 = 2.0*MY_PI*ranpark->uniform(); theta2 = 2.0*MY_PI*ranpark->uniform(); - if (atom->quat_flag) { - quat2[i][0] = cos(theta2)*t2; - quat2[i][1] = sin(theta1)*t1; - quat2[i][2] = cos(theta1)*t1; - quat2[i][3] = sin(theta2)*t2; - } else { - quat[0] = cos(theta2)*t2; - quat[1] = sin(theta1)*t1; - quat[2] = cos(theta1)*t1; - quat[3] = sin(theta2)*t2; - } - count++; + quat_one[0] = cos(theta2)*t2; + quat_one[1] = sin(theta1)*t1; + quat_one[2] = cos(theta1)*t1; + quat_one[3] = sin(theta2)*t2; } } else { double theta2; for (i = 0; i < nlocal; i++) if (select[i]) { - if (avec_ellipsoid && atom->ellipsoid[i] >= 0) - quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; - else if (avec_body && atom->body[i] >= 0) - quat = avec_body->bonus[atom->body[i]].quat; - else if (atom->quat_flag) - quat2 = atom->quat; + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; else error->one(FLERR,"Cannot set quaternion for atom that has none"); ranpark->reset(seed,x[i]); theta2 = MY_PI*ranpark->uniform(); - if (atom->quat_flag) { - quat2[i][0] = cos(theta2); - quat2[i][1] = 0.0; - quat2[i][2] = 0.0; - quat2[i][3] = sin(theta2); - } else { - quat[0] = cos(theta2); - quat[1] = 0.0; - quat[2] = 0.0; - quat[3] = sin(theta2); - } - count++; + quat_one[0] = cos(theta2); + quat_one[1] = 0.0; + quat_one[2] = 0.0; + quat_one[3] = sin(theta2); } } // set theta to random orientation in 2d } else if (keyword == THETA_RANDOM) { + int *line = atom->line; int nlocal = atom->nlocal; + for (i = 0; i < nlocal; i++) { if (select[i]) { - if (atom->line[i] < 0) + if (line[i] < 0) error->one(FLERR,"Cannot set theta for atom that is not a line"); ranpark->reset(seed,x[i]); - avec_line->bonus[atom->line[i]].theta = MY_2PI*ranpark->uniform(); - count++; + avec_line->bonus[line[i]].theta = MY_2PI*ranpark->uniform(); } } } @@ -756,7 +802,7 @@ void Set2::setrandom(int keyword) /* ---------------------------------------------------------------------- */ -void Set2::topology(int keyword) +void Set2::topology(int keyword, Action *action) { int m,atom1,atom2,atom3,atom4; @@ -785,16 +831,23 @@ void Set2::topology(int keyword) selection(atom->nlocal + atom->nghost); + int count = 0; + // for BOND, each of 2 atoms must be in group if (keyword == BOND) { + int *num_bond = atom->num_bond; + int **bond_type = atom->bond_type; + tagint **bond_atom = atom->bond_atom; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_bond[i]; m++) { - atom1 = atom->map(atom->bond_atom[i][m]); + for (m = 0; m < num_bond[i]; m++) { + atom1 = atom->map(bond_atom[i][m]); if (atom1 == -1) error->one(FLERR,"Bond atom missing in set command"); if (select[i] && select[atom1]) { - atom->bond_type[i][m] = ivalue; + bond_type[i][m] = itype; count++; } } @@ -802,17 +855,24 @@ void Set2::topology(int keyword) // for ANGLE, each of 3 atoms must be in group - if (keyword == ANGLE) { + if (keyword == ANGLE) { + int *num_angle = atom->num_angle; + int **angle_type = atom->angle_type; + tagint **angle_atom1 = atom->angle_atom1; + tagint **angle_atom2 = atom->angle_atom2; + tagint **angle_atom3 = atom->angle_atom3; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_angle[i]; m++) { - atom1 = atom->map(atom->angle_atom1[i][m]); - atom2 = atom->map(atom->angle_atom2[i][m]); - atom3 = atom->map(atom->angle_atom3[i][m]); + for (m = 0; m < num_angle[i]; m++) { + atom1 = atom->map(angle_atom1[i][m]); + atom2 = atom->map(angle_atom2[i][m]); + atom3 = atom->map(angle_atom3[i][m]); if (atom1 == -1 || atom2 == -1 || atom3 == -1) error->one(FLERR,"Angle atom missing in set command"); if (select[atom1] && select[atom2] && select[atom3]) { - atom->angle_type[i][m] = ivalue; + angle_type[i][m] = itype; count++; } } @@ -821,17 +881,25 @@ void Set2::topology(int keyword) // for DIHEDRAL, each of 4 atoms must be in group if (keyword == DIHEDRAL) { + int *num_dihedral = atom->num_dihedral; + int **dihedral_type = atom->dihedral_type; + tagint **dihedral_atom1 = atom->dihedral_atom1; + tagint **dihedral_atom2 = atom->dihedral_atom2; + tagint **dihedral_atom3 = atom->dihedral_atom3; + tagint **dihedral_atom4 = atom->dihedral_atom4; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_dihedral[i]; m++) { - atom1 = atom->map(atom->dihedral_atom1[i][m]); - atom2 = atom->map(atom->dihedral_atom2[i][m]); - atom3 = atom->map(atom->dihedral_atom3[i][m]); - atom4 = atom->map(atom->dihedral_atom4[i][m]); + for (m = 0; m < num_dihedral[i]; m++) { + atom1 = atom->map(dihedral_atom1[i][m]); + atom2 = atom->map(dihedral_atom2[i][m]); + atom3 = atom->map(dihedral_atom3[i][m]); + atom4 = atom->map(dihedral_atom4[i][m]); if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) error->one(FLERR,"Dihedral atom missing in set command"); if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { - atom->dihedral_type[i][m] = ivalue; + dihedral_type[i][m] = itype; count++; } } @@ -840,45 +908,33 @@ void Set2::topology(int keyword) // for IMPROPER, each of 4 atoms must be in group if (keyword == IMPROPER) { + int *num_improper = atom->num_improper; + int **improper_type = atom->improper_type; + tagint **improper_atom1 = atom->improper_atom1; + tagint **improper_atom2 = atom->improper_atom2; + tagint **improper_atom3 = atom->improper_atom3; + tagint **improper_atom4 = atom->improper_atom4; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_improper[i]; m++) { - atom1 = atom->map(atom->improper_atom1[i][m]); - atom2 = atom->map(atom->improper_atom2[i][m]); - atom3 = atom->map(atom->improper_atom3[i][m]); - atom4 = atom->map(atom->improper_atom4[i][m]); + for (m = 0; m < num_improper[i]; m++) { + atom1 = atom->map(improper_atom1[i][m]); + atom2 = atom->map(improper_atom2[i][m]); + atom3 = atom->map(improper_atom3[i][m]); + atom4 = atom->map(improper_atom4[i][m]); if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) error->one(FLERR,"Improper atom missing in set command"); if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { - atom->improper_type[i][m] = ivalue; + improper_type[i][m] = itype; count++; } } } -} -/* ---------------------------------------------------------------------- */ + // set count_action for all topology actions -void Set2::varparse(const char *name, int m) -{ - int ivar = input->variable->find(name+2); - if (ivar < 0) - error->all(FLERR,"Variable name {} for set command does not exist", name); - if (!input->variable->atomstyle(ivar)) - error->all(FLERR,"Variable {} for set command is invalid style", name); - - Action *action = &actions[naction]; - action->varflag = 1; - - if (m == 1) { - action->varflag1 = 1; action->ivar1 = ivar; - } else if (m == 2) { - action->varflag2 = 1; action->ivar2 = ivar; - } else if (m == 3) { - action->varflag3 = 1; action->ivar3 = ivar; - } else if (m == 4) { - action->varflag4 = 1; action->ivar4 = ivar; - } + count_action = count; } // ---------------------------------------------------------------------- @@ -888,16 +944,12 @@ void Set2::varparse(const char *name, int m) // separate two operations so can be called by either set or fix set command // ---------------------------------------------------------------------- -// DONE - -void Set2::process_angle(int &iarg, int narg, char **arg) +void Set2::process_angle(int &iarg, int narg, char **arg, Action *action) { if (atom->avec->angles_allow == 0) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); - Action *action = &actions[naction]; - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ANGLE,lmp); action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; @@ -906,24 +958,19 @@ void Set2::process_angle(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_angle() +void Set2::invoke_angle(Action *action) { - topology(ANGLE); + topology(ANGLE,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_angmom(int &iarg, int narg, char **arg) +void Set2::process_angmom(int &iarg, int narg, char **arg, Action *action) { if (!atom->angmom_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); - Action *action = &actions[naction]; if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -935,14 +982,11 @@ void Set2::process_angmom(int &iarg, int narg, char **arg) iarg += 4; } -// DONE - -void Set2::invoke_angmom() +void Set2::invoke_angmom(Action *action) { int nlocal = atom->nlocal; double **angmom = atom->angmom; - Action *action = &actions[naction]; int varflag = action->varflag; double xvalue,yvalue,zvalue; if (!action->varflag1) xvalue = action->dvalue1; @@ -966,16 +1010,12 @@ void Set2::invoke_angmom() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_bond(int &iarg, int narg, char **arg) +void Set2::process_bond(int &iarg, int narg, char **arg, Action *action) { if (atom->avec->bonds_allow == 0) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); - Action *action = &actions[naction]; - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::BOND,lmp); action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; @@ -985,25 +1025,19 @@ void Set2::process_bond(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_bond() +void Set2::invoke_bond(Action *action) { - topology(BOND); + topology(BOND,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_cc(int &iarg, int narg, char **arg) +void Set2::process_cc(int &iarg, int narg, char **arg, Action *action) { if (!atom->tdpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); - Action *action = &actions[naction]; - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 < 1) error->all(FLERR,"Invalid cc index in set command"); @@ -1016,14 +1050,11 @@ void Set2::process_cc(int &iarg, int narg, char **arg) iarg += 3; } -// DONE - -void Set2::invoke_cc() +void Set2::invoke_cc(Action *action) { int nlocal = atom->nlocal; double **cc = atom->cc; - Action *action = &actions[naction]; int cc_index = action->ivalue1 - 1; // NOTE: need to check if cc_index exceeds cc array allocation @@ -1045,32 +1076,25 @@ void Set2::invoke_cc() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_charge(int &iarg, int narg, char **arg) +void Set2::process_charge(int &iarg, int narg, char **arg, Action *action) { if (!atom->q_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_charge() +void Set2::invoke_charge(Action *action) { int nlocal = atom->nlocal; double *q = atom->q; double *q_scaled = atom->q_scaled; double *epsilon = atom->epsilon; - Action *action = &actions[naction]; int varflag = action->varflag; double qvalue; if (!action->varflag1) qvalue = action->dvalue1; @@ -1089,16 +1113,12 @@ void Set2::invoke_charge() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_density(int &iarg, int narg, char **arg) +void Set2::process_density(int &iarg, int narg, char **arg, Action *action) { if (!atom->rmass_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1114,9 +1134,7 @@ void Set2::process_density(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_density() +void Set2::invoke_density(Action *action) { int nlocal = atom->nlocal; double *rmass = atom->rmass; @@ -1134,7 +1152,6 @@ void Set2::invoke_density() auto avec_line = dynamic_cast(atom->style_match("line")); auto avec_tri = dynamic_cast(atom->style_match("tri")); - Action *action = &actions[naction]; int varflag = action->varflag; double density; if (!action->varflag1) density = action->dvalue1; @@ -1190,16 +1207,12 @@ void Set2::invoke_density() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_diameter(int &iarg, int narg, char **arg) +void Set2::process_diameter(int &iarg, int narg, char **arg, Action *action) { if (!atom->radius_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1209,12 +1222,11 @@ void Set2::process_diameter(int &iarg, int narg, char **arg) iarg += 2; } -void Set2::invoke_diameter() +void Set2::invoke_diameter(Action *action) { int nlocal = atom->nlocal; double *radius = atom->radius; - Action *action = &actions[naction]; int varflag = action->varflag; double diam; if (!action->varflag1) diam = action->dvalue1; @@ -1233,16 +1245,12 @@ void Set2::invoke_diameter() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_dihedral(int &iarg, int narg, char **arg) +void Set2::process_dihedral(int &iarg, int narg, char **arg, Action *action) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); - Action *action = &actions[naction]; - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::DIHEDRAL,lmp); action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; @@ -1252,25 +1260,19 @@ void Set2::process_dihedral(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_dihedral() +void Set2::invoke_dihedral(Action *action) { - topology(DIHEDRAL); + topology(DIHEDRAL,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_dipole(int &iarg, int narg, char **arg) +void Set2::process_dipole(int &iarg, int narg, char **arg, Action *action) { if (!atom->mu_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); @@ -1281,14 +1283,11 @@ void Set2::process_dipole(int &iarg, int narg, char **arg) iarg += 4; } -// DONE - -void Set2::invoke_dipole() +void Set2::invoke_dipole(Action *action) { int nlocal = atom->nlocal; double **mu = atom->mu; - Action *action = &actions[naction]; int varflag = action->varflag; double xvalue,yvalue,zvalue; if (!action->varflag1) xvalue = action->dvalue1; @@ -1313,15 +1312,11 @@ void Set2::invoke_dipole() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_dipole_random(int &iarg, int narg, char **arg) +void Set2::process_dipole_random(int &iarg, int narg, char **arg, Action *action) { if (!atom->mu_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); - - Action *action = &actions[naction]; action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); @@ -1333,24 +1328,18 @@ void Set2::process_dipole_random(int &iarg, int narg, char **arg) iarg += 3; } -// DONE - -void Set2::invoke_dipole_random() +void Set2::invoke_dipole_random(Action *action) { - setrandom(DIPOLE_RANDOM); + setrandom(DIPOLE_RANDOM,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_dpd_theta(int &iarg, int narg, char **arg) +void Set2::process_dpd_theta(int &iarg, int narg, char **arg, Action *action) { if (!atom->dpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); - - Action *action = &actions[naction]; if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); @@ -1362,9 +1351,7 @@ void Set2::process_dpd_theta(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_dpd_theta() +void Set2::invoke_dpd_theta(Action *action) { int nlocal = atom->nlocal; int *type = atom->type; @@ -1377,7 +1364,6 @@ void Set2::invoke_dpd_theta() double onemass; double vx,vy,vz; - Action *action = &actions[naction]; int varflag = action->varflag; double theta; if (!action->varflag1) theta = action->dvalue1; @@ -1406,16 +1392,12 @@ void Set2::invoke_dpd_theta() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_edpd_cv(int &iarg, int narg, char **arg) +void Set2::process_edpd_cv(int &iarg, int narg, char **arg, Action *action) { if (!atom->edpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1425,14 +1407,11 @@ void Set2::process_edpd_cv(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_edpd_cv() +void Set2::invoke_edpd_cv(Action *action) { int nlocal = atom->nlocal; double *edpd_cv = atom->edpd_cv; - Action *action = &actions[naction]; int varflag = action->varflag; double cv; if (!action->varflag1) cv = action->dvalue1; @@ -1451,16 +1430,12 @@ void Set2::invoke_edpd_cv() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_edpd_temp(int &iarg, int narg, char **arg) +void Set2::process_edpd_temp(int &iarg, int narg, char **arg, Action *action) { if (!atom->edpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1469,14 +1444,11 @@ void Set2::process_edpd_temp(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_edpd_temp() +void Set2::invoke_edpd_temp(Action *action) { int nlocal = atom->nlocal; double *edpd_temp = atom->edpd_temp; - Action *action = &actions[naction]; int varflag = action->varflag; double temp; if (!action->varflag1) temp = action->dvalue1; @@ -1495,16 +1467,12 @@ void Set2::invoke_edpd_temp() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_epsilon(int &iarg, int narg, char **arg) +void Set2::process_epsilon(int &iarg, int narg, char **arg, Action *action) { if (!atom->dielectric_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1514,16 +1482,13 @@ void Set2::process_epsilon(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_epsilon() +void Set2::invoke_epsilon(Action *action) { int nlocal = atom->nlocal; double *epsilon = atom->epsilon; double *q = atom->q; double *q_scaled = atom->q_scaled; - Action *action = &actions[naction]; int varflag = action->varflag; double eps; if (!action->varflag1) eps = action->dvalue1; @@ -1546,13 +1511,9 @@ void Set2::invoke_epsilon() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_image(int &iarg, int narg, char **arg) +void Set2::process_image(int &iarg, int narg, char **arg, Action *action) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); - - Action *action = &actions[naction]; if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue4 = 0; else { @@ -1599,15 +1560,12 @@ void Set2::process_image(int &iarg, int narg, char **arg) iarg += 4; } -// DONE - -void Set2::invoke_image() +void Set2::invoke_image(Action *action) { int nlocal = atom->nlocal; imageint *image = atom->image; int xbox,ybox,zbox; - Action *action = &actions[naction]; int ximageflag = action->ivalue4; int yimageflag = action->ivalue5; int zimageflag = action->ivalue6; @@ -1643,16 +1601,12 @@ void Set2::invoke_image() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_improper(int &iarg, int narg, char **arg) +void Set2::process_improper(int &iarg, int narg, char **arg, Action *action) { if (atom->avec->impropers_allow == 0) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); - Action *action = &actions[naction]; - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::IMPROPER,lmp); action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; @@ -1662,25 +1616,19 @@ void Set2::process_improper(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_improper() +void Set2::invoke_improper(Action *action) { - topology(IMPROPER); + topology(IMPROPER,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_length(int &iarg, int narg, char **arg) +void Set2::process_length(int &iarg, int narg, char **arg, Action *action) { if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1690,14 +1638,11 @@ void Set2::process_length(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_length() +void Set2::invoke_length(Action *action) { int nlocal = atom->nlocal; auto avec_line = dynamic_cast(atom->style_match("line")); - Action *action = &actions[naction]; int varflag = action->varflag; double length; if (!action->varflag1) length = action->dvalue1; @@ -1721,16 +1666,12 @@ void Set2::invoke_length() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_mass(int &iarg, int narg, char **arg) +void Set2::process_mass(int &iarg, int narg, char **arg, Action *action) { if (!atom->rmass_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1740,14 +1681,11 @@ void Set2::process_mass(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_mass() +void Set2::invoke_mass(Action *action) { int nlocal = atom->nlocal; double *rmass = atom->rmass; - Action *action = &actions[naction]; int varflag = action->varflag; double mass_one; if (!action->varflag1) mass_one = action->dvalue1; @@ -1766,16 +1704,12 @@ void Set2::invoke_mass() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_mol(int &iarg, int narg, char **arg) +void Set2::process_mol(int &iarg, int narg, char **arg, Action *action) { if (!atom->molecule_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->tvalue1 = utils::tnumeric(FLERR,arg[iarg+1],false,lmp); @@ -1785,14 +1719,11 @@ void Set2::process_mol(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_mol() +void Set2::invoke_mol(Action *action) { int nlocal = atom->nlocal; int *molecule = atom->molecule; - Action *action = &actions[naction]; int varflag = action->varflag; tagint molID; if (!action->varflag1) molID = action->tvalue1; @@ -1811,16 +1742,12 @@ void Set2::invoke_mol() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_omega(int &iarg, int narg, char **arg) +void Set2::process_omega(int &iarg, int narg, char **arg, Action *action) { if (!atom->omega_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); @@ -1831,14 +1758,11 @@ void Set2::process_omega(int &iarg, int narg, char **arg) iarg += 4; } -// DONE - -void Set2::invoke_omega() +void Set2::invoke_omega(Action *action) { int nlocal = atom->nlocal; double **omega = atom->angmom; - Action *action = &actions[naction]; int varflag = action->varflag; double xvalue,yvalue,zvalue; if (!action->varflag1) xvalue = action->dvalue1; @@ -1862,17 +1786,13 @@ void Set2::invoke_omega() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_quat(int &iarg, int narg, char **arg) +void Set2::process_quat(int &iarg, int narg, char **arg, Action *action) { if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); int dimension = domain->dimension; - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -1893,9 +1813,7 @@ void Set2::process_quat(int &iarg, int narg, char **arg) iarg += 5; } -// DONE - -void Set2::invoke_quat() +void Set2::invoke_quat(Action *action) { int nlocal = atom->nlocal; int *ellipsoid = atom->ellipsoid; @@ -1912,7 +1830,6 @@ void Set2::invoke_quat() double radians,sintheta; double *quat_one; - Action *action = &actions[naction]; int varflag = action->varflag; double xvalue,yvalue,zvalue,theta; if (!action->varflag1) xvalue = action->dvalue1; @@ -1955,40 +1872,30 @@ void Set2::invoke_quat() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_quat_random(int &iarg, int narg, char **arg) +void Set2::process_quat_random(int &iarg, int narg, char **arg, Action *action) { if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); - Action *action = &actions[naction]; - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); iarg += 2; } -// DONE - -void Set2::invoke_quat_random() +void Set2::invoke_quat_random(Action *action) { - setrandom(QUAT_RANDOM); + setrandom(QUAT_RANDOM,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_radius_election(int &iarg, int narg, char **arg) +void Set2::process_radius_election(int &iarg, int narg, char **arg, Action *action) { if (!atom->eradius_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); - - Action *action = &actions[naction]; if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { @@ -1999,14 +1906,11 @@ void Set2::process_radius_election(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_radius_election() +void Set2::invoke_radius_election(Action *action) { int nlocal = atom->nlocal; double *eradius = atom->eradius; - Action *action = &actions[naction]; int varflag = action->varflag; double radius; if (!action->varflag1) radius = action->dvalue1; @@ -2025,16 +1929,12 @@ void Set2::invoke_radius_election() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_shape(int &iarg, int narg, char **arg) +void Set2::process_shape(int &iarg, int narg, char **arg, Action *action) { if (!atom->ellipsoid_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -2054,14 +1954,11 @@ void Set2::process_shape(int &iarg, int narg, char **arg) iarg += 4; } -// DONE - -void Set2::invoke_shape() +void Set2::invoke_shape(Action *action) { int nlocal = atom->nlocal; auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - Action *action = &actions[naction]; int varflag = action->varflag; double xvalue,yvalue,zvalue; if (!action->varflag1) xvalue = action->dvalue1; @@ -2094,16 +1991,12 @@ void Set2::invoke_shape() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg) +void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg, Action *action) { if (!atom->smd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -2113,14 +2006,11 @@ void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_smd_contact_radius() +void Set2::invoke_smd_contact_radius(Action *action) { int nlocal = atom->nlocal; double *contact_radius = atom->contact_radius; - Action *action = &actions[naction]; int varflag = action->varflag; double radius; if (!action->varflag1) radius = action->dvalue1; @@ -2140,16 +2030,12 @@ void Set2::invoke_smd_contact_radius() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_smd_mass_density(int &iarg, int narg, char **arg) +void Set2::process_smd_mass_density(int &iarg, int narg, char **arg, Action *action) { if (!atom->smd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -2159,15 +2045,12 @@ void Set2::process_smd_mass_density(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_smd_mass_density() +void Set2::invoke_smd_mass_density(Action *action) { int nlocal = atom->nlocal; double *rmass = atom->rmass; double *vfrac = atom->vfrac; - Action *action = &actions[naction]; int varflag = action->varflag; double density; if (!action->varflag1) density = action->dvalue1; @@ -2186,30 +2069,23 @@ void Set2::invoke_smd_mass_density() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_sph_cv(int &iarg, int narg, char **arg) +void Set2::process_sph_cv(int &iarg, int narg, char **arg, Action *action) { if (!atom->cv_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_sph_cv() +void Set2::invoke_sph_cv(Action *action) { int nlocal = atom->nlocal; double *cv = atom->cv; - Action *action = &actions[naction]; int varflag = action->varflag; double sph_cv; if (!action->varflag1) sph_cv = action->dvalue1; @@ -2223,30 +2099,23 @@ void Set2::invoke_sph_cv() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_sph_e(int &iarg, int narg, char **arg) +void Set2::process_sph_e(int &iarg, int narg, char **arg, Action *action) { if (!atom->esph_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_sph_e() +void Set2::invoke_sph_e(Action *action) { int nlocal = atom->nlocal; double *esph = atom->esph; - Action *action = &actions[naction]; int varflag = action->varflag; double sph_e; if (!action->varflag1) sph_e = action->dvalue1; @@ -2260,30 +2129,23 @@ void Set2::invoke_sph_e() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_sph_rho(int &iarg, int narg, char **arg) +void Set2::process_sph_rho(int &iarg, int narg, char **arg, Action *action) { if (!atom->rho_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_sph_rho() +void Set2::invoke_sph_rho(Action *action) { int nlocal = atom->nlocal; double *rho = atom->rho; - Action *action = &actions[naction]; int varflag = action->varflag; double sph_rho; if (!action->varflag1) sph_rho = action->dvalue1; @@ -2297,9 +2159,7 @@ void Set2::invoke_sph_rho() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_spin_atom(int &iarg, int narg, char **arg) +void Set2::process_spin_atom(int &iarg, int narg, char **arg, Action *action) { if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) error->warning(FLERR, "Set attribute spin is deprecated -- use spin/atom instead"); @@ -2307,8 +2167,6 @@ void Set2::process_spin_atom(int &iarg, int narg, char **arg) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -2325,15 +2183,12 @@ void Set2::process_spin_atom(int &iarg, int narg, char **arg) iarg += 5; } -// DONE - -void Set2::invoke_spin_atom() +void Set2::invoke_spin_atom(Action *action) { int nlocal = atom->nlocal; double **sp = atom->sp; double norm; - Action *action = &actions[naction]; int varflag = action->varflag; double magnitude,xvalue,yvalue,zvalue; if (!action->varflag1) magnitude = action->dvalue1; @@ -2366,9 +2221,7 @@ void Set2::invoke_spin_atom() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) +void Set2::process_spin_atom_random(int &iarg, int narg, char **arg, Action *action) { if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) error->warning(FLERR, "Set attribute spin/random is deprecated -- use spin/atom/random instead"); @@ -2376,8 +2229,6 @@ void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); - Action *action = &actions[naction]; - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); @@ -2387,43 +2238,34 @@ void Set2::process_spin_atom_random(int &iarg, int narg, char **arg) iarg += 3; } -// DONE - -void Set2::invoke_spin_atom_random() +void Set2::invoke_spin_atom_random(Action *action) { - setrandom(SPIN_ATOM_RANDOM); + setrandom(SPIN_ATOM_RANDOM,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_spin_electron(int &iarg, int narg, char **arg) +void Set2::process_spin_electron(int &iarg, int narg, char **arg, Action *action) { if (!atom->spin_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 < -1 || action->ivalue1 > 3) - error->one(FLERR,"Invalid value for electron spin: {}", ivalue); + error->one(FLERR,"Invalid electron spin in set command"); } iarg += 2; } -// DONE - -void Set2::invoke_spin_electron() +void Set2::invoke_spin_electron(Action *action) { int nlocal = atom->nlocal; int *spin = atom->spin; - Action *action = &actions[naction]; int varflag = action->varflag; int ispin; if (!action->varflag1) ispin = action->ivalue1; @@ -2434,7 +2276,7 @@ void Set2::invoke_spin_electron() if (varflag) { ispin = static_cast (vec1[i]); if (ispin < -1 || ispin > 3) - error->one(FLERR,"Incorrect value for electron spin: {}", ivalue); + error->one(FLERR,"Invalid electron spin in set command"); } atom->spin[i] = ispin; @@ -2443,15 +2285,11 @@ void Set2::invoke_spin_electron() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_temperature(int &iarg, int narg, char **arg) +void Set2::process_temperature(int &iarg, int narg, char **arg, Action *action) { if (!atom->temperature_flag) error->all(FLERR,"Cannot set this attribute for this atom style"); if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); - - Action *action = &actions[naction]; if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { @@ -2462,14 +2300,11 @@ void Set2::process_temperature(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_temperature() +void Set2::invoke_temperature(Action *action) { int nlocal = atom->nlocal; double *temperature = atom->temperature; - Action *action = &actions[naction]; int varflag = action->varflag; double temp; if (!action->varflag1) temp = action->dvalue1; @@ -2488,32 +2323,25 @@ void Set2::invoke_temperature() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_theta(int &iarg, int narg, char **arg) +void Set2::process_theta(int &iarg, int narg, char **arg, Action *action) { if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_theta() +void Set2::invoke_theta(Action *action) { int nlocal = atom->nlocal; int *line = atom->line; auto avec_line = dynamic_cast(atom->style_match("line")); - Action *action = &actions[naction]; int varflag = action->varflag; double theta; if (!action->varflag1) theta = action->dvalue1; @@ -2522,21 +2350,17 @@ void Set2::invoke_theta() if (!select[i]) continue; if (line[i] < 0) error->one(FLERR,"Cannot set theta for atom which is not a line"); if (varflag) theta = vec1[i]; - avec_line->bonus[atom->line[i]].theta = dvalue; + avec_line->bonus[atom->line[i]].theta = theta; } } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_theta_random(int &iarg, int narg, char **arg) +void Set2::process_theta_random(int &iarg, int narg, char **arg, Action *action) { if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); - - Action *action = &actions[naction]; action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); @@ -2544,40 +2368,49 @@ void Set2::process_theta_random(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_theta_random() +void Set2::invoke_theta_random(Action *action) { - setrandom(THETA_RANDOM); + setrandom(THETA_RANDOM,action); } /* ---------------------------------------------------------------------- */ -// NOT DONE - -void Set2::process_tri(int &iarg, int narg, char **arg) +void Set2::process_tri(int &iarg, int narg, char **arg, Action *action) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (!atom->tri_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid tri size in set command"); + } + iarg += 2; } -// NOT DONE - -void Set2::invoke_tri() +void Set2::invoke_tri(Action *action) { int nlocal = atom->nlocal; + int *tri = atom->tri; + auto avec_tri = dynamic_cast(atom->style_match("tri")); - // VARIABLE option + int varflag = action->varflag; + double trisize; + if (!action->varflag1) trisize = action->dvalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - //if (dvalue < 0.0) error->one(FLERR,"Invalid tri size in set command"); - avec_tri->set_equilateral(i,dvalue); + if (tri[i] < 0) error->one(FLERR,"Cannot set tri for atom which is not a triangle"); + + if (varflag) { + trisize = vec1[i]; + if (trisize < 0.0) error->one(FLERR,"Invalid tri size in set command"); + } + + avec_tri->set_equilateral(i,trisize); } // update bonus tri count @@ -2588,129 +2421,142 @@ void Set2::invoke_tri() /* ---------------------------------------------------------------------- */ -// NOT DONE - -void Set2::process_type(int &iarg, int narg, char **arg) +void Set2::process_type(int &iarg, int narg, char **arg, Action *action) { 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 { char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - //ivalue = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->ntypes) + error->one(FLERR,"Invalid atom type in set command"); } + iarg += 2; } -// NOT DONE - -void Set2::invoke_type() +void Set2::invoke_type(Action *action) { int nlocal = atom->nlocal; int *type = atom->type; - Action *action = &actions[naction]; + int varflag = action->varflag; + int itype; + if (!action->varflag1) itype = action->ivalue1; for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - if (action->varflag) - if (action->ivalue1 <= 0 || action->ivalue1 > atom->ntypes) - error->one(FLERR,"Invalid value in set command"); - type[i] = action->ivalue1; + + if (action->varflag) { + itype = static_cast (vec1[i]); + if (itype <= 0 || itype > atom->ntypes) + error->one(FLERR,"Invalid atom type in set command"); + } + + type[i] = itype; } } /* ---------------------------------------------------------------------- */ -// NOT DONE - -void Set2::process_type_fraction(int &iarg, int narg, char **arg) +void Set2::process_type_fraction(int &iarg, int narg, char **arg, Action *action) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); + + // random seed must be ivalue1 for use in setrandom() + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - newtype = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; - double fraction = utils::numeric(FLERR,arg[iarg+2],false,lmp); - int ivalue; - ivalue = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - if (newtype <= 0 || newtype > atom->ntypes) - error->all(FLERR,"Invalid type value {} in set type/fraction command", newtype); - if (fraction < 0.0 || fraction > 1.0) - error->all(FLERR,"Invalid fraction value {} in set type/fraction command", fraction); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed {} in set type/fraction command", ivalue); + if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) + error->one(FLERR,"Invalid atom type in set command"); + + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) + error->all(FLERR,"Invalid fraction in set command"); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 4; } -void Set2::invoke_type_fraction() +void Set2::invoke_type_fraction(Action *action) { - setrandom(TYPE_FRACTION); + setrandom(TYPE_FRACTION,action); } /* ---------------------------------------------------------------------- */ -// NOT DONE - -void Set2::process_type_ratio(int &iarg, int narg, char **arg) +void Set2::process_type_ratio(int &iarg, int narg, char **arg, Action *action) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error); + + // random seed must be ivalue1 for use in setrandom() + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - newtype = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + action->ivalue2 = 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) - error->all(FLERR,"Invalid type value {} in set type/ratio command", newtype); - if (fraction < 0.0 || fraction > 1.0) - error->all(FLERR,"Invalid fraction value {} in set type/ratio command", fraction); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed {} in set type/ratio command", ivalue); + if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) + error->all(FLERR,"Invalid atom type in set command"); + + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) + error->all(FLERR,"Invalid fraction in set command"); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 4; } -void Set2::invoke_type_ratio() +void Set2::invoke_type_ratio(Action *action) { - setrandom(TYPE_RATIO); + setrandom(TYPE_RATIO,action); } /* ---------------------------------------------------------------------- */ -// NOT DONE - -void Set2::process_type_subset(int &iarg, int narg, char **arg) +void Set2::process_type_subset(int &iarg, int narg, char **arg, Action *action) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error); + + // random seed must be ivalue1 for use in setrandom() + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - newtype = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + action->ivalue2 = 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) - error->all(FLERR,"Invalid type value {} in set type/subset command", newtype); - if (nsubset < 0) - error->all(FLERR,"Invalid subset size {} in set type/subset command", nsubset); - if (ivalue <= 0) - error->all(FLERR,"Invalid random number seed {} in set type/subset command", ivalue); + if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) + error->all(FLERR,"Invalid atom type in set command"); + + action->bvalue1 = utils::bnumeric(FLERR,arg[iarg+2],false,lmp); + if (action->bvalue1 < 0) + error->all(FLERR,"Invalid subset size in set command"); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + iarg += 4; } -void Set2::invoke_type_subset() +void Set2::invoke_type_subset(Action *action) { - setrandom(TYPE_SUBSET); + setrandom(TYPE_SUBSET,action); } /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_volume(int &iarg, int narg, char **arg) +void Set2::process_volume(int &iarg, int narg, char **arg, Action *action) { if (!atom->vfrac_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -2720,14 +2566,11 @@ void Set2::process_volume(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_volume() +void Set2::invoke_volume(Action *action) { int nlocal = atom->nlocal; double *vfrac = atom->vfrac; - Action *action = &actions[naction]; int varflag = action->varflag; double vol; if (!action->varflag1) vol = action->dvalue1; @@ -2746,28 +2589,21 @@ void Set2::invoke_volume() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_vx(int &iarg, int narg, char **arg) +void Set2::process_vx(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vx", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_vx() +void Set2::invoke_vx(Action *action) { int nlocal = atom->nlocal; double **v = atom->v; - Action *action = &actions[naction]; int varflag = action->varflag; double vx; if (!action->varflag1) vx = action->dvalue1; @@ -2781,28 +2617,21 @@ void Set2::invoke_vx() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_vy(int &iarg, int narg, char **arg) +void Set2::process_vy(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vy", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_vy() +void Set2::invoke_vy(Action *action) { int nlocal = atom->nlocal; double **v = atom->v; - Action *action = &actions[naction]; int varflag = action->varflag; double vy; if (!action->varflag1) vy = action->dvalue1; @@ -2816,28 +2645,21 @@ void Set2::invoke_vy() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_vz(int &iarg, int narg, char **arg) +void Set2::process_vz(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vz", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_vz() +void Set2::invoke_vz(Action *action) { int nlocal = atom->nlocal; double **v = atom->v; - Action *action = &actions[naction]; int varflag = action->varflag; double vz; if (!action->varflag1) vz = action->dvalue1; @@ -2851,13 +2673,9 @@ void Set2::invoke_vz() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_x(int &iarg, int narg, char **arg) +void Set2::process_x(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); - - Action *action = &actions[naction]; if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -2865,14 +2683,11 @@ void Set2::process_x(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_x() +void Set2::invoke_x(Action *action) { int nlocal = atom->nlocal; double **x = atom->x; - Action *action = &actions[naction]; int varflag = action->varflag; double coord; if (!action->varflag1) coord = action->dvalue1; @@ -2886,28 +2701,21 @@ void Set2::invoke_x() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_y(int &iarg, int narg, char **arg) +void Set2::process_y(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_y() +void Set2::invoke_y(Action *action) { int nlocal = atom->nlocal; double **x = atom->x; - Action *action = &actions[naction]; int varflag = action->varflag; double coord; if (!action->varflag1) coord = action->dvalue1; @@ -2921,28 +2729,21 @@ void Set2::invoke_y() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_z(int &iarg, int narg, char **arg) +void Set2::process_z(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); - Action *action = &actions[naction]; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; } -// DONE - -void Set2::invoke_z() +void Set2::invoke_z(Action *action) { int nlocal = atom->nlocal; double **x = atom->x; - Action *action = &actions[naction]; int varflag = action->varflag; double coord; if (!action->varflag1) coord = action->dvalue1; @@ -2956,20 +2757,16 @@ void Set2::invoke_z() /* ---------------------------------------------------------------------- */ -// DONE - -void Set2::process_custom(int &iarg, int narg, char **arg) +void Set2::process_custom(int &iarg, int narg, char **arg, Action *action) { int flag,cols; ArgInfo argi(arg[iarg],ArgInfo::DNAME|ArgInfo::INAME); const char *pname = argi.get_name(); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set", error); - index_custom = atom->find_custom(argi.get_name(),flag,cols); + int index_custom = atom->find_custom(argi.get_name(),flag,cols); if (index_custom < 0) error->all(FLERR,"Set keyword or custom property {} does not exist",pname); - - Action *action = &actions[naction]; action->ivalue2 = index_custom; switch (argi.get_type()) { @@ -3024,15 +2821,12 @@ void Set2::process_custom(int &iarg, int narg, char **arg) iarg += 2; } -// DONE - -void Set2::invoke_custom() +void Set2::invoke_custom(Action *action) { int nlocal = atom->nlocal; int ivalue; double dvalue; - Action *action = &actions[naction]; int varflag = action->varflag; int index_custom = action->ivalue2; diff --git a/src/set2.h b/src/set2.h index f0d64a0175..c1d0c9b1bc 100644 --- a/src/set2.h +++ b/src/set2.h @@ -26,12 +26,12 @@ namespace LAMMPS_NS { class Set2 : public Command { public: - Set2(class LAMMPS *lmp) : Command(lmp){}; + Set2(class LAMMPS *lmp); ~Set2(); void command(int, char **) override; - void process_args(int, int, char **); + int process_args(int, int, char **); void selection(int); void invoke_actions(); @@ -51,138 +51,138 @@ class Set2 : public Command { struct Action { int keyword; + int argindex; + int count_select,count_action; int varflag; int varflag1, varflag2, varflag3, varflag4; int ivar1, ivar2, ivar3, ivar4; int ivalue1, ivalue2, ivalue3, ivalue4, ivalue5, ivalue6; tagint tvalue1; + bigint bvalue1; double dvalue1,dvalue2,dvalue3,dvalue4; }; int naction,maxaction; Action *actions; - Action *action; - typedef void (Set2::*FnPtrPack)(); + typedef void (Set2::*FnPtrPack)(Action *); FnPtrPack *invoke_choice; // list of ptrs to invoke functions - // storage for evaluated variables - - double *vec1, *vec2, *vec3, *vec4; + double *vec1, *vec2, *vec3, *vec4; // storage for evaluated peratom variables - // flag for selected atoms + int *select; // flag for selected atoms + int count_select; // count of selected atoms on this proc + int count_action; // count of actions on this proc, only if different than selected - int *select; - // private functions - void setrandom(int); - void topology(int); void varparse(const char *, int); + void setrandom(int, Action *); + void topology(int, Action *); - // customize by adding a process method prototype + // customize by adding a process method - void process_angle(int &, int, char **); - void process_angmom(int &, int, char **); - void process_bond(int &, int, char **); - void process_cc(int &, int, char **); - void process_charge(int &, int, char **); - void process_density(int &, int, char **); - void process_diameter(int &, int, char **); - void process_dihedral(int &, int, char **); - void process_dipole(int &, int, char **); - void process_dipole_random(int &, int, char **); - void process_dpd_theta(int &, int, char **); - void process_edpd_cv(int &, int, char **); - void process_edpd_temp(int &, int, char **); - void process_epsilon(int &, int, char **); - void process_image(int &, int, char **); - void process_improper(int &, int, char **); - void process_length(int &, int, char **); - void process_mass(int &, int, char **); - void process_mol(int &, int, char **); - void process_omega(int &, int, char **); - void process_quat(int &, int, char **); - void process_quat_random(int &, int, char **); - void process_radius_election(int &, int, char **); - void process_shape(int &, int, char **); - void process_smd_contact_radius(int &, int, char **); - void process_smd_mass_density(int &, int, char **); - void process_sph_cv(int &, int, char **); - void process_sph_e(int &, int, char **); - void process_sph_rho(int &, int, char **); - void process_spin_atom(int &, int, char **); - void process_spin_atom_random(int &, int, char **); - void process_spin_electron(int &, int, char **); - void process_temperature(int &, int, char **); - void process_theta(int &, int, char **); - void process_theta_random(int &, int, char **); - void process_tri(int &, int, char **); - void process_type(int &, int, char **); - void process_type_fraction(int &, int, char **); - void process_type_ratio(int &, int, char **); - void process_type_subset(int &, int, char **); - void process_volume(int &, int, char **); - void process_vx(int &, int, char **); - void process_vy(int &, int, char **); - void process_vz(int &, int, char **); - void process_x(int &, int, char **); - void process_y(int &, int, char **); - void process_z(int &, int, char **); + void process_angle(int &, int, char **, Action *); + void process_angmom(int &, int, char **, Action *); + void process_bond(int &, int, char **, Action *); + void process_cc(int &, int, char **, Action *); + void process_charge(int &, int, char **, Action *); + void process_density(int &, int, char **, Action *); + void process_diameter(int &, int, char **, Action *); + void process_dihedral(int &, int, char **, Action *); + void process_dipole(int &, int, char **, Action *); + void process_dipole_random(int &, int, char **, Action *); + void process_dpd_theta(int &, int, char **, Action *); + void process_edpd_cv(int &, int, char **, Action *); + void process_edpd_temp(int &, int, char **, Action *); + void process_epsilon(int &, int, char **, Action *); + void process_image(int &, int, char **, Action *); + void process_improper(int &, int, char **, Action *); + void process_length(int &, int, char **, Action *); + void process_mass(int &, int, char **, Action *); + void process_mol(int &, int, char **, Action *); + void process_omega(int &, int, char **, Action *); + void process_quat(int &, int, char **, Action *); + void process_quat_random(int &, int, char **, Action *); + void process_radius_election(int &, int, char **, Action *); + void process_shape(int &, int, char **, Action *); + void process_smd_contact_radius(int &, int, char **, Action *); + void process_smd_mass_density(int &, int, char **, Action *); + void process_sph_cv(int &, int, char **, Action *); + void process_sph_e(int &, int, char **, Action *); + void process_sph_rho(int &, int, char **, Action *); + void process_spin_atom(int &, int, char **, Action *); + void process_spin_atom_random(int &, int, char **, Action *); + void process_spin_electron(int &, int, char **, Action *); + void process_temperature(int &, int, char **, Action *); + void process_theta(int &, int, char **, Action *); + void process_theta_random(int &, int, char **, Action *); + void process_tri(int &, int, char **, Action *); + void process_type(int &, int, char **, Action *); + void process_type_fraction(int &, int, char **, Action *); + void process_type_ratio(int &, int, char **, Action *); + void process_type_subset(int &, int, char **, Action *); + void process_volume(int &, int, char **, Action *); + void process_vx(int &, int, char **, Action *); + void process_vy(int &, int, char **, Action *); + void process_vz(int &, int, char **, Action *); + void process_x(int &, int, char **, Action *); + void process_y(int &, int, char **, Action *); + void process_z(int &, int, char **, Action *); - void process_custom(int &, int, char **); + void process_custom(int &, int, char **, Action *); - // customize by adding an invoke method prototype + // customize by adding an invoke method - void invoke_angle(); - void invoke_angmom(); - void invoke_bond(); - void invoke_cc(); - void invoke_charge(); - void invoke_density(); - void invoke_diameter(); - void invoke_dihedral(); - void invoke_dipole(); - void invoke_dipole_random(); - void invoke_dpd_theta(); - void invoke_edpd_cv(); - void invoke_edpd_temp(); - void invoke_epsilon(); - void invoke_image(); - void invoke_improper(); - void invoke_length(); - void invoke_mass(); - void invoke_mol(); - void invoke_omega(); - void invoke_quat(); - void invoke_quat_random(); - void invoke_radius_election(); - void invoke_shape(); - void invoke_smd_contact_radius(); - void invoke_smd_mass_density(); - void invoke_sph_cv(); - void invoke_sph_e(); - void invoke_sph_rho(); - void invoke_spin_atom(); - void invoke_spin_atom_random(); - void invoke_spin_electron(); - void invoke_temperature(); - void invoke_theta(); - void invoke_theta_random(); - void invoke_tri(); - void invoke_type(); - void invoke_type_fraction(); - void invoke_type_ratio(); - void invoke_type_subset(); - void invoke_volume(); - void invoke_vx(); - void invoke_vy(); - void invoke_vz(); - void invoke_x(); - void invoke_y(); - void invoke_z(); + void invoke_angle(Action *); + void invoke_angmom(Action *); + void invoke_bond(Action *); + void invoke_cc(Action *); + void invoke_charge(Action *); + void invoke_density(Action *); + void invoke_diameter(Action *); + void invoke_dihedral(Action *); + void invoke_dipole(Action *); + void invoke_dipole_random(Action *); + void invoke_dpd_theta(Action *); + void invoke_edpd_cv(Action *); + void invoke_edpd_temp(Action *); + void invoke_epsilon(Action *); + void invoke_image(Action *); + void invoke_improper(Action *); + void invoke_length(Action *); + void invoke_mass(Action *); + void invoke_mol(Action *); + void invoke_omega(Action *); + void invoke_quat(Action *); + void invoke_quat_random(Action *); + void invoke_radius_election(Action *); + void invoke_shape(Action *); + void invoke_smd_contact_radius(Action *); + void invoke_smd_mass_density(Action *); + void invoke_sph_cv(Action *); + void invoke_sph_e(Action *); + void invoke_sph_rho(Action *); + void invoke_spin_atom(Action *); + void invoke_spin_atom_random(Action *); + void invoke_spin_electron(Action *); + void invoke_temperature(Action *); + void invoke_theta(Action *); + void invoke_theta_random(Action *); + void invoke_tri(Action *); + void invoke_type(Action *); + void invoke_type_fraction(Action *); + void invoke_type_ratio(Action *); + void invoke_type_subset(Action *); + void invoke_volume(Action *); + void invoke_vx(Action *); + void invoke_vy(Action *); + void invoke_vz(Action *); + void invoke_x(Action *); + void invoke_y(Action *); + void invoke_z(Action *); - void invoke_custom(); + void invoke_custom(Action *); }; } // namespace LAMMPS_NS From 130033ec7580e2c2dd340abe577caa2eb2ac0b1d Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 23 Apr 2025 13:04:54 -0600 Subject: [PATCH 07/26] first working version of fix set with refactored set command --- doc/src/set.rst | 787 +++++----- doc/src/set2.rst | 656 -------- src/fix_set.cpp | 75 + src/fix_set.h | 41 + src/set.cpp | 3753 +++++++++++++++++++++++++++++++--------------- src/set.h | 180 ++- src/set2.cpp | 2871 ----------------------------------- src/set2.h | 192 --- 8 files changed, 3218 insertions(+), 5337 deletions(-) delete mode 100644 doc/src/set2.rst create mode 100644 src/fix_set.cpp create mode 100644 src/fix_set.h delete mode 100644 src/set2.cpp delete mode 100644 src/set2.h diff --git a/doc/src/set.rst b/doc/src/set.rst index 6be590e9b6..dde5ca99fe 100644 --- a/doc/src/set.rst +++ b/doc/src/set.rst @@ -22,21 +22,110 @@ Syntax 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 - *dipole* or *dipole/random* or *quat* or *spin/atom* or *spin/atom/random* or - *spin/electron* or *radius/electron* or - *quat* or *quat/random* or *diameter* or *shape* or *length* or *tri* or - *theta* or *theta/random* or *angmom* or *omega* or - *mass* or *density* or *density/disc* or *temperature* or - *volume* or *image* or *bond* or *angle* or *dihedral* or - *improper* or *sph/e* or *sph/cv* or *sph/rho* or - *smd/contact/radius* or *smd/mass/density* or *dpd/theta* or - *edpd/temp* or *edpd/cv* or *cc* or *epsilon* or - *i_name* or *d_name* or *i2_name* or *d2_name* + +* keyword = *angle* or *angmom* or *bond* or *cc* or *charge* or + *density* or *density/disc* or *diameter* or *dihedral* or *dipole* + or *dipole/random* or *dpd/theta* or *edpd/cv* or *edpd/temp* or + *epsilon* or *image* or *improper* or *length* or *mass* or *mol* or + *omega* or *quat* or *quat/random* or *radius/electron* or *shape* or + *smd/contact/radius* or *smd/mass/density* or *sph/cv* or *sph/e* or + *sph/rho* or *spin/atom* or *spin/atom/random* or *spin/electron* or + *temperature* or *theta* or *theta/random* or *tri* or *type* or + *type/fraction* or *type/ratio* or *type/subset* or *volume* or *vx* + or *vy* or *vz* or *x* or *y* or *z* or *i_name* or *d_name* or + *i2_name* or *d2_name* .. parsed-literal:: + *angle* value = numeric angle type or angle type label, for all angles between selected atoms + *angmom* values = Lx Ly Lz + Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units) + any of Lx,Ly,Lz can be an atom-style variable (see below) + *bond* value = numeric bond type or bond type label, for all bonds between selected atoms + *cc* values = index cc + index = index of a chemical species (1 to Nspecies) + cc = chemical concentration of tDPD particles for a species (mole/volume units) + cc can be an atom-style variable (see below) + *charge* value = atomic charge (charge units) + value can be an atom-style variable (see below) + *density* value = particle density for a sphere or ellipsoid (mass/distance\^3 units), or for a triangle (mass/distance\^2 units) or line (mass/distance units) particle + value can be an atom-style variable (see below) + *density/disc* value = particle density for a 2d disc or ellipse (mass/distance\^2 units) + value can be an atom-style variable (see below) + *diameter* value = diameter of spherical particle (distance units) + value can be an atom-style variable (see below) + *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms + *dipole* values = x y z + x,y,z = orientation of dipole moment vector + any of x,y,z can be an atom-style variable (see below) + *dipole/random* values = seed Dlen + seed = random # seed (positive integer) for dipole moment orientations + Dlen = magnitude of dipole moment (dipole units) + *dpd/theta* value = internal temperature of DPD particles (temperature units) + value can be an atom-style variable (see below) + value can be NULL which sets internal temp of each particle to KE temp + *edpd/cv* value = volumetric heat capacity of eDPD particles (energy/temperature/volume units) + value can be an atom-style variable (see below) + *edpd/temp* value = temperature of eDPD particles (temperature units) + value can be an atom-style variable (see below) + *epsilon* value = dielectric constant of the medium where the atoms reside + value can be an atom-style variable (see below) + *image* values = 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) + *improper* value = numeric improper type or improper type label, for all impropers between selected atoms + *length* value = len + len = length of line segment (distance units) + len can be an atom-style variable (see below) + *mass* value = per-atom mass (mass units) + value can be an atom-style variable (see below) + *mol* value = molecule ID + the moleclue ID can be an atom-style variable (see below) + *omega* values = Wx Wy Wz + Wx,Wy,Wz = components of angular velocity vector (radians/time units) + any of Wx,Wy,Wz can be an atom-style variable (see below) + *quat* values = a b c theta + a,b,c = unit vector to rotate particle around via right-hand rule + theta = rotation angle (degrees) + any of a,b,c,theta values can be an atom-style variable (see below) + *quat/random* value = seed + seed = random # seed (positive integer) for quaternion orientations + *radius/electron* value = eradius + eradius = electron radius (or fixed-core radius) (distance units) + value can be an atom-style variable (see below) + *shape* values = Sx Sy Sz + Sx,Sy,Sz = 3 diameters of ellipsoid (distance units) + any of Sx,Sy,Sz can be an atom-style variable (see below) + *smd/contact/radius* value = radius for short range interactions, i.e. contact and friction + value can be an atom-style variable (see below) + *smd/mass/density* value = set particle mass based on volume by providing a mass density + value can be an atom-style variable (see below) + *sph/cv* value = heat capacity of SPH particles (need units) + value can be an atom-style variable (see below) + *sph/e* value = energy of SPH particles (need units) + value can be an atom-style variable (see below) + *sph/rho* value = density of SPH particles (need units) + value can be an atom-style variable (see below) + *spin/atom* values = g x y z + g = magnitude of magnetic spin vector (in Bohr magneton's unit) + x,y,z = orientation of magnetic spin vector + any of x,y,z can be an atom-style variable (see below) + *spin/atom/random* values = seed Dlen + seed = random # seed (positive integer) for magnetic spin orientations + Dlen = magnitude of magnetic spin vector (in Bohr magneton's unit) + *spin/electron* value = espin + espin = electron spin (+1/-1), 0 = nuclei, 2 = fixed-core, 3 = pseudo-cores (i.e. ECP) + value can be an atom-style variable (see below) + *temperature* value = temperature for finite-size particles (temperature units) + value can be an atom-style variable (see below) + *theta* value = angle (degrees) + angle = orientation of line segment with respect to x-axis + value can be an atom-style variable (see below) + *theta/random* value = seed + seed = random # seed (positive integer) for line segment orienations + *tri* value = side + side = side length of equilateral triangle (distance units) + value can be an atom-style variable (see below) *type* value = numeric atom type or type label value can be an atom-style variable (see below) *type/fraction* values = type fraction seed @@ -51,104 +140,22 @@ Syntax 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) - *x*,\ *y*,\ *z* value = atom coordinate (distance units) + *volume* value = particle volume for Peridynamic particle (distance\^3 units) value can be an atom-style variable (see below) *vx*,\ *vy*,\ *vz* value = atom velocity (velocity units) value can be an atom-style variable (see below) - *charge* value = atomic charge (charge units) + *x*,\ *y*,\ *z* value = atom coordinate (distance units) value can be an atom-style variable (see below) - *dipole* values = x y z - x,y,z = orientation of dipole moment vector - any of x,y,z can be an atom-style variable (see below) - *dipole/random* value = seed Dlen - seed = random # seed (positive integer) for dipole moment orientations - Dlen = magnitude of dipole moment (dipole units) - *spin/atom* values = g x y z - g = magnitude of magnetic spin vector (in Bohr magneton's unit) - x,y,z = orientation of magnetic spin vector - any of x,y,z can be an atom-style variable (see below) - *spin/atom/random* value = seed Dlen - seed = random # seed (positive integer) for magnetic spin orientations - Dlen = magnitude of magnetic spin vector (in Bohr magneton's unit) - *radius/electron* values = eradius - eradius = electron radius (or fixed-core radius) (distance units) - *spin/electron* value = espin - espin = electron spin (+1/-1), 0 = nuclei, 2 = fixed-core, 3 = pseudo-cores (i.e. ECP) - *quat* values = a b c theta - a,b,c = unit vector to rotate particle around via right-hand rule - theta = rotation angle (degrees) - any of a,b,c,theta can be an atom-style variable (see below) - *quat/random* value = seed - seed = random # seed (positive integer) for quaternion orientations - *diameter* value = diameter of spherical particle (distance units) - value can be an atom-style variable (see below) - *shape* value = Sx Sy Sz - Sx,Sy,Sz = 3 diameters of ellipsoid (distance units) - *length* value = len - len = length of line segment (distance units) - len can be an atom-style variable (see below) - *tri* value = side - side = side length of equilateral triangle (distance units) - side can be an atom-style variable (see below) - *theta* value = angle (degrees) - angle = orientation of line segment with respect to x-axis - angle can be an atom-style variable (see below) - *theta/random* value = seed - seed = random # seed (positive integer) for line segment orienations - *angmom* values = Lx Ly Lz - Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units) - any of Lx,Ly,Lz can be an atom-style variable (see below) - *omega* values = Wx Wy Wz - Wx,Wy,Wz = components of angular velocity vector (radians/time units) - any of wx,wy,wz can be an atom-style variable (see below) - *mass* value = per-atom mass (mass units) - value can be an atom-style variable (see below) - *density* value = particle density for a sphere or ellipsoid (mass/distance\^3 units), or for a triangle (mass/distance\^2 units) or line (mass/distance units) particle - value can be an atom-style variable (see below) - *density/disc* value = particle density for a 2d disc or ellipse (mass/distance\^2 units) - value can be an atom-style variable (see below) - *temperature* value = temperature for finite-size particles (temperature units) - value can be an atom-style variable (see below) - *volume* value = particle volume for Peridynamic particle (distance\^3 units) - value can be an atom-style variable (see below) - *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 = 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 - *rheo/rho* value = density of RHEO particles (mass/distance\^3) - *rheo/status* value = status or phase of RHEO particles (unitless) - *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) - value can be an atom-style variable (see below) - *sph/rho* value = density of SPH particles (need units) - value can be an atom-style variable (see below) - *smd/contact/radius* = radius for short range interactions, i.e. contact and friction - value can be an atom-style variable (see below) - *smd/mass/density* = set particle mass based on volume by providing a mass density - value can be an atom-style variable (see below) - *dpd/theta* value = internal temperature of DPD particles (temperature units) - value can be an atom-style variable (see below) - value can be NULL which sets internal temp of each particle to KE temp - *edpd/temp* value = temperature of eDPD particles (temperature units) - value can be an atom-style variable (see below) - *edpd/cv* value = volumetric heat capacity of eDPD particles (energy/temperature/volume units) - value can be an atom-style variable (see below) - *cc* values = index cc - index = index of a chemical species (1 to Nspecies) - cc = chemical concentration of tDPD particles for a species (mole/volume units) - *epsilon* value = dielectric constant of the medium where the atoms reside *i_name* value = custom integer vector with name + value can be an atom-style variable (see below) *d_name* value = custom floating-point vector with name - *i2_name* value = column of a custom integer array with name + value can be an atom-style variable (see below) + *i2_name* value = custom integer array with name column specified as i2_name[N] where N is 1 to Ncol - *d2_name* value = column of a custom floating-point array with name + value can be an atom-style variable (see below) + *d2_name* value = custom floating-point array with name column specified as d2_name[N] where N is 1 to Ncol + value can be an atom-style variable (see below) Examples """""""" @@ -177,16 +184,16 @@ Description Set one or more properties of one or more atoms. Since atom properties are initially assigned by the :doc:`read_data `, -:doc:`read_restart ` or :doc:`create_atoms ` -commands, this command changes those assignments. This can be useful -for overriding the default values assigned by the -:doc:`create_atoms ` command (e.g. charge = 0.0). It can -be useful for altering pairwise and molecular force interactions, +:doc:`read_restart ` or :doc:`create_atoms +` commands, this command changes those assignments. +This can be useful for overriding the default values assigned by the +:doc:`create_atoms ` command (e.g. charge = 0.0). It +can be useful for altering pairwise and molecular force interactions, since force-field coefficients are defined in terms of types. It can be used to change the labeling of atoms by atom type or molecule ID -when they are output in :doc:`dump ` files. It can also be useful -for debugging purposes; i.e. positioning an atom at a precise location -to compute subsequent forces or energy. +when they are output in :doc:`dump ` files. It can also be +useful for debugging purposes; i.e. positioning an atom at a precise +location to compute subsequent forces or energy. Note that the *style* and *ID* arguments determine which atoms have their properties reset. The remaining keywords specify which @@ -211,8 +218,8 @@ 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 -of values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For +numeric value, or with a wildcard asterisk to specify a range of +values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For example, for the style *type*, if N = the number of atom types, then an asterisk with no numeric values means all types from 1 to N. A leading asterisk means all types from 1 to n (inclusive). A trailing @@ -222,25 +229,25 @@ means all types from m to n (inclusive). For all the styles except The style *group* selects all the atoms in the specified group. The style *region* selects all the atoms in the specified geometric -region. See the :doc:`group ` and :doc:`region ` commands -for details of how to specify a group or region. +region. See the :doc:`group ` and :doc:`region ` +commands for details of how to specify a group or region. ---------- -This section describes the keyword options for which properties to +The next section describes the keyword options for which properties to change, for the selected atoms. Note that except where explicitly prohibited below, all of the keywords allow an :doc:`atom-style or atomfile-style variable ` to be used as the specified value(s). If the value is a -variable, it should be specified as v_name, where name is the -variable name. In this case, the variable will be evaluated, and its -resulting per-atom value used to determine the value assigned to each -selected atom. Note that the per-atom value from the variable will be -ignored for atoms that are not selected via the *style* and *ID* -settings explained above. A simple way to use per-atom values from -the variable to reset a property for all atoms is to use style *atom* -with *ID* = "\*"; this selects all atom IDs. +variable, it should be specified as v_name, where name is the variable +name. In this case, the variable will be evaluated, and its resulting +per-atom value used to determine the value assigned to each selected +atom. Note that the per-atom value from the variable will be ignored +for atoms that are not selected via the *style* and *ID* settings +explained above. A simple way to use per-atom values from the +variable to reset a property for all atoms is to use style *atom* with +*ID* = "\*"; this selects all atom IDs. Atom-style variables can specify formulas with various mathematical functions, and include :doc:`thermo_style ` command @@ -256,52 +263,110 @@ from a file. .. note:: Atom-style and atomfile-style variables return floating point - per-atom values. If the values are assigned to an integer variable, - 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. + per-atom values. If the values are assigned to an integer + variable, 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. + +---------- .. versionchanged:: 28Mar2023 - Support for type labels was added for setting atom, bond, angle, - dihedral, and improper types + Support for type labels was added for setting angle 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 ` command or -the *atom types* field in the header of the data file read by the -:doc:`read_data ` command. When using a type label it must -have been defined previously. See the :doc:`Howto type labels -` doc page for the allowed syntax of type labels -and a general discussion of how type labels can be used. +Keyword *angle* sets the angle type of all angles of selected atoms to +the specified value. The value can be a numeric type from 1 to +nangletypes. Or it can be a angle type label. See the :doc:`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 angle must be selected atoms in order for +the change to be made. The value of nangletypes was set by the *angle +types* field in the header of the data file read by the +:doc:`read_data ` command. This keyword does NOT allow use +of an atom-style variable. -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 -many processors are being used. This keyword does not allow use of an -atom-style variable. +Keyword *angmom* sets the angular momentum of selected atoms. The +particles must be ellipsoids as defined by the :doc:`atom_style +ellipsoid ` command or triangles as defined by the +:doc:`atom_style tri ` command. The angular momentum +vector of the particles is set to the 3 specified components. -Keywords *type/ratio* and *type/subset* also set the atom type for a -fraction of the selected atoms. The actual number of atoms changed -will be exactly the requested number. For *type/ratio* the specified -fraction (0 <= *fraction* <= 1) determines the number. For -*type/subset*, the specified *Nsubset* is the number. An iterative -algorithm is used which ensures the correct number of atoms are -selected, in a perfectly random fashion. Which atoms are selected -will change with the number of processors used. These keywords do not -allow use of an atom-style variable. +.. versionchanged:: 28Mar2023 -Keyword *mol* sets the molecule ID for all selected atoms. The -:doc:`atom style ` being used must support the use of -molecule IDs. + Support for type labels was added for setting bond types -Keywords *x*, *y*, *z*, and *charge* set the coordinates or -charge of all selected atoms. For *charge*, the :doc:`atom style -` being used must support the use of atomic -charge. Keywords *vx*, *vy*, and *vz* set the velocities of all -selected atoms. +Keyword *bond* sets the bond type of all bonds of selected atoms to +the specified value. The value can be a numeric type from 1 to +nbondtypes. Or it can be a bond type label. See the :doc:`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 must be selected atoms in order for the +change to be made. The value of nbondtypes was set by the *bond +types* field in the header of the data file read by the +:doc:`read_data ` command. This keyword does NOT allow use +of an atom-style variable. + +Keyword *cc* sets the chemical concentration of a tDPD particle for a +specified species as defined by the DPD-MESO package. Currently, only +:doc:`atom_style tdpd ` defines particles with this +attribute. An integer for "index" selects a chemical species (1 to +Nspecies) where Nspecies is set by the atom_style command. The value +for the chemical concentration must be >= 0.0. + +Keyword *charge* set the charge of all selected atoms. The :doc:`atom +style ` being used must support the use of atomic charge. + +Keyword *density* or *density/disc* also sets the mass of all selected +particles, but in a different way. The particles must have a per-atom +mass attribute, as defined by the :doc:`atom_style ` +command. If the atom has a radius attribute (see :doc:`atom_style +sphere `) and its radius is non-zero, its mass is set from +the density and particle volume for 3d systems (the input density is +assumed to be in mass/distance\^3 units). For 2d, the default is for +LAMMPS to model particles with a radius attribute as spheres. +However, if the *density/disc* keyword is used, then they can be +modeled as 2d discs (circles). Their mass is set from the density and +particle area (the input density is assumed to be in mass/distance\^2 +units). + +If the atom has a shape attribute (see :doc:`atom_style ellipsoid +`) and its 3 shape parameters are non-zero, then its mass +is set from the density and particle volume (the input density is +assumed to be in mass/distance\^3 units). The *density/disc* keyword +has no effect; it does not (yet) treat 3d ellipsoids as 2d ellipses. + +If the atom has a length attribute (see :doc:`atom_style line +`) and its length is non-zero, then its mass is set from +the density and line segment length (the input density is assumed to +be in mass/distance units). If the atom has an area attribute (see +:doc:`atom_style tri `) and its area is non-zero, then its +mass is set from the density and triangle area (the input density is +assumed to be in mass/distance\^2 units). + +If none of these cases are valid, then the mass is set to the density +value directly (the input density is assumed to be in mass units). + +Keyword *diameter* sets the size of the selected atoms. The particles +must be finite-size spheres as defined by the :doc:`atom_style sphere +` command. The diameter of a particle can be set to 0.0, +which means they will be treated as point particles. Note that this +command does not adjust the particle mass, even if it was defined with +a density, e.g. via the :doc:`read_data ` command. + +.. versionchanged:: 28Mar2023 + + Support for type labels was added for setting dihedral types + +Keyword *dihedral* sets the dihedral type of all dihedrals of selected +atoms to the specified value. The value can be a numeric type from 1 +to ndihedraltypes. Or it can be a dihedral type label. See the +:doc:`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 dihedral must be selected atoms in +order for the change to be made. The value of ndihedraltypes was set +by the *dihedral types* field in the header of the data file read by +the :doc:`read_data ` command. This keyword does NOT allow +use of an atom-style variable. Keyword *dipole* uses the specified x,y,z values as components of a vector to set as the orientation of the dipole moment vectors of the @@ -313,40 +378,106 @@ moment vectors for the selected atoms and sets the magnitude of each to the specified *Dlen* value. For 2d systems, the z component of the orientation is set to 0.0. Random numbers are used in such a way that the orientation of a particular atom is the same, regardless of how -many processors are being used. This keyword does not allow use of an +many processors are being used. This keyword does NOT allow use of an atom-style variable. -.. versionchanged:: 15Sep2022 +Keyword *dpd/theta* sets the internal temperature of a DPD particle as +defined by the DPD-REACT package. If the specified value is a number +it must be >= 0.0. If the specified value is NULL, then the kinetic +temperature Tkin of each particle is computed as 3/2 k Tkin = KE = 1/2 +m v\^2 = 1/2 m (vx\*vx+vy\*vy+vz\*vz). Each particle's internal +temperature is set to Tkin. If the specified value is an atom-style +variable, then the variable is evaluated for each particle. If a +value >= 0.0, the internal temperature is set to that value. If it is +< 0.0, the computation of Tkin is performed and the internal +temperature is set to that value. -Keyword *spin/atom* uses the specified g value to set the magnitude of the -magnetic spin vectors, and the x,y,z values as components of a vector -to set as the orientation of the magnetic spin vectors of the selected -atoms. This keyword was previously called *spin*. +Keywords *edpd/temp* and *edpd/cv* set the temperature and volumetric +heat capacity of an eDPD particle as defined by the DPD-MESO package. +Currently, only :doc:`atom_style edpd ` defines particles +with these attributes. The values for the temperature and heat +capacity must be positive. -.. versionchanged:: 15Sep2022 +Keyword *epsilon* sets the dielectric constant of a particle to be +that of the medium where the particle resides as defined by the +DIELECTRIC package. Currently, only :doc:`atom_style dielectric +` defines particles with this attribute. The value for the +dielectric constant must be >= 0.0. Note that the set command with +this keyword will rescale the particle charge accordingly so that the +real charge (e.g., as read from a data file) stays intact. To change +the real charges, one needs to use the set command with the *charge* +keyword. Care must be taken to ensure that the real and scaled charges +and the dielectric constants are consistent. -Keyword *spin/atom/random* randomizes the orientation of the magnetic spin -vectors for the selected atoms and sets the magnitude of each to the -specified *Dlen* value. This keyword was previously called *spin/random*. +Keyword *image* sets which image of the simulation box the atom is +considered to be in. An image of 0 means it is inside the box as +defined. A value of 2 means add 2 box lengths to get the true value. +A value of -1 means subtract 1 box length to get the true value. +LAMMPS updates these flags as atoms cross periodic boundaries during +the simulation. The flags can be output with atom snapshots via the +:doc:`dump ` command. If a value of NULL is specified for any +of nx,ny,nz, then the current image value for that dimension is +unchanged. For non-periodic dimensions only a value of 0 can be +specified. This command can be useful after a system has been +equilibrated and atoms have diffused one or more box lengths in +various directions. This command can then reset the image values for +atoms so that they are effectively inside the simulation box, e.g if a +diffusion coefficient is about to be measured via the :doc:`compute +msd ` command. Care should be taken not to reset the +image flags of two atoms in a bond to the same value if the bond +straddles a periodic boundary (rather they should be different by +/- +1). This will not affect the dynamics of a 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. -.. versionadded:: 15Sep2022 +.. versionchanged:: 28Mar2023 -Keyword *radius/electron* uses the specified value to set the radius of -electrons or fixed cores. + Support for type labels was added for setting improper types -.. versionadded:: 15Sep2022 +Keyword *improper* sets the improper type of all impropers of selected +atoms to the specified value. The value can be a numeric type from 1 +to nimpropertypes. Or it can be a improper type label. See the +:doc:`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 improper must be selected atoms in +order for the change to be made. The value of nimpropertypes was set +by the *improper types* field in the header of the data file read by +the :doc:`read_data ` command. This keyword does NOT allow +use of an atom-style variable. -Keyword *spin/electron* sets the spin of an electron (+/- 1) or indicates -nuclei (=0), fixed-cores (=2), or pseudo-cores (= 3). +Keyword *length* sets the length of selected atoms. The particles +must be line segments as defined by the :doc:`atom_style line +` command. If the specified value is non-zero the line +segment is (re)set to a length = the specified value, centered around +the particle position, with an orientation along the x-axis. If the +specified value is 0.0, the particle will become a point particle. +Note that this command does not adjust the particle mass, even if it +was defined with a density, e.g. via the :doc:`read_data ` +command. + +Keyword *mass* sets the mass of all selected particles. The particles +must have a per-atom mass attribute, as defined by the +:doc:`atom_style ` command. See the "mass" command for +how to set mass values on a per-type basis. + +Keyword *mol* sets the molecule ID for all selected atoms. The +:doc:`atom style ` being used must support the use of +molecule IDs. + +Keyword *omega* sets the angular velocity of selected atoms. The +particles must be spheres as defined by the :doc:`atom_style sphere +` command. The angular velocity vector of the particles +is set to the 3 specified components. Keyword *quat* uses the specified values to create a quaternion (4-vector) that represents the orientation of the selected atoms. The particles must define a quaternion for their orientation (e.g. ellipsoids, triangles, body particles) as defined by the -:doc:`atom_style ` command. Note that particles defined by -:doc:`atom_style ellipsoid ` have 3 shape parameters. The 3 -values must be non-zero for each particle set by this command. They -are used to specify the aspect ratios of an ellipsoidal particle, +:doc:`atom_style ` command. Note that particles defined +by :doc:`atom_style ellipsoid ` have 3 shape parameters. +The 3 values must be non-zero for each particle set by this command. +They are used to specify the aspect ratios of an ellipsoidal particle, which is oriented by default with its x-axis along the simulation box's x-axis, and similarly for y and z. If this body is rotated (via the right-hand rule) by an angle theta around a unit rotation vector @@ -360,51 +491,77 @@ ignored, since a rotation vector of (0,0,1) is the only valid choice. Keyword *quat/random* randomizes the orientation of the quaternion for the selected atoms. The particles must define a quaternion for their orientation (e.g. ellipsoids, triangles, body particles) as defined by -the :doc:`atom_style ` command. Random numbers are used in -such a way that the orientation of a particular atom is the same, +the :doc:`atom_style ` command. Random numbers are used +in such a way that the orientation of a particular atom is the same, regardless of how many processors are being used. For 2d systems, only orientations in the xy plane are generated. As with keyword *quat*, for ellipsoidal particles, the 3 shape values must be non-zero -for each particle set by this command. This keyword does not allow +for each particle set by this command. This keyword does NOT allow use of an atom-style variable. -Keyword *diameter* sets the size of the selected atoms. The particles -must be finite-size spheres as defined by the :doc:`atom_style sphere -` command. The diameter of a particle can be set to 0.0, -which means they will be treated as point particles. Note that this -command does not adjust the particle mass, even if it was defined with -a density, e.g. via the :doc:`read_data ` command. +.. versionadded:: 15Sep2022 + +Keyword *radius/electron* uses the specified value to set the radius +of electrons or fixed cores. Keyword *shape* sets the size and shape of the selected atoms. The particles must be ellipsoids as defined by the :doc:`atom_style -ellipsoid ` command. The *Sx*, *Sy*, *Sz* settings -are the 3 diameters of the ellipsoid in each direction. All 3 can be -set to the same value, which means the ellipsoid is effectively a -sphere. They can also all be set to 0.0 which means the particle will -be treated as a point particle. Note that this command does not -adjust the particle mass, even if it was defined with a density, -e.g. via the :doc:`read_data ` command. +ellipsoid ` command. The *Sx*, *Sy*, *Sz* settings are +the 3 diameters of the ellipsoid in each direction. All 3 can be set +to the same value, which means the ellipsoid is effectively a sphere. +They can also all be set to 0.0 which means the particle will be +treated as a point particle. Note that this command does not adjust +the particle mass, even if it was defined with a density, e.g. via the +:doc:`read_data ` command. -Keyword *length* sets the length of selected atoms. The particles -must be line segments as defined by the :doc:`atom_style line -` command. If the specified value is non-zero the line -segment is (re)set to a length = the specified value, centered around -the particle position, with an orientation along the x-axis. If the -specified value is 0.0, the particle will become a point particle. -Note that this command does not adjust the particle mass, even if it -was defined with a density, e.g. via the :doc:`read_data ` -command. +Keyword *smd/contact/radius* only applies to simulations with the +Smooth Mach Dynamics package MACHDYN. Itsets an interaction radius +for computing short-range interactions, e.g. repulsive forces to +prevent different individual physical bodies from penetrating each +other. Note that the SPH smoothing kernel diameter used for computing +long range, nonlocal interactions, is set using the *diameter* +keyword. -Keyword *tri* sets the size of selected atoms. The particles must be -triangles as defined by the :doc:`atom_style tri ` command. -If the specified value is non-zero the triangle is (re)set to be an -equilateral triangle in the xy plane with side length = the specified -value, with a centroid at the particle position, with its base -parallel to the x axis, and the y-axis running from the center of the -base to the top point of the triangle. If the specified value is 0.0, -the particle will become a point particle. Note that this command -does not adjust the particle mass, even if it was defined with a -density, e.g. via the :doc:`read_data ` command. +Keyword *smd/mass/density* sets the mass of all selected particles, +but it is only applicable to the Smooth Mach Dynamics package MACHDYN. +It assumes that the particle volume has already been correctly set and +calculates particle mass from the provided mass density value. + +Keywords *sph/cv*, *sph/e*, and *sph/rho* set the heat capacity, +energy, and density of smoothed particle hydrodynamics (SPH) +particles. See `this PDF guide `_ to +using SPH in LAMMPS. + +.. note:: + + Noote that the SPH PDF guide file has not been updated for many + years and thus does not reflect the current *syntax* of the SPH + package commands. For that, please refer to the LAMMPS manual. + +.. versionchanged:: 15Sep2022 + +Keyword *spin/atom* uses the specified g value to set the magnitude of +the magnetic spin vectors, and the x,y,z values as components of a +vector to set as the orientation of the magnetic spin vectors of the +selected atoms. This keyword was previously called *spin*. + +.. versionchanged:: 15Sep2022 + +Keyword *spin/atom/random* randomizes the orientation of the magnetic +spin vectors for the selected atoms and sets the magnitude of each to +the specified *Dlen* value. This keyword does NOT allow use of an +atom-style variable. This keyword was previously called +*spin/random*. + +.. versionadded:: 15Sep2022 + +Keyword *spin/electron* sets the spin of an electron (+/- 1) or +indicates nuclei (=0), fixed-cores (=2), or pseudo-cores (= 3). + +Keyword *temperature* sets the temperature of a finite-size particle. +Currently, only the GRANULAR package supports this attribute. The +temperature must be added using an instance of :doc:`fix property/atom +` The values for the temperature must be positive. Keyword *theta* sets the orientation of selected atoms. The particles must be line segments as defined by the :doc:`atom_style line @@ -413,169 +570,71 @@ orientation angle of the line segments with respect to the x axis. Keyword *theta/random* randomizes the orientation of theta for the selected atoms. The particles must be line segments as defined by the -:doc:`atom_style line ` command. Random numbers are used in -such a way that the orientation of a particular atom is the same, +:doc:`atom_style line ` command. Random numbers are used +in such a way that the orientation of a particular atom is the same, regardless of how many processors are being used. This keyword does -not allow use of an atom-style variable. +NOT allow use of an atom-style variable. -Keyword *angmom* sets the angular momentum of selected atoms. The -particles must be ellipsoids as defined by the :doc:`atom_style -ellipsoid ` command or triangles as defined by the -:doc:`atom_style tri ` command. The angular momentum -vector of the particles is set to the 3 specified components. +Keyword *tri* sets the size of selected atoms. The particles must be +triangles as defined by the :doc:`atom_style tri ` +command. If the specified value is non-zero the triangle is (re)set +to be an equilateral triangle in the xy plane with side length = the +specified value, with a centroid at the particle position, with its +base parallel to the x axis, and the y-axis running from the center of +the base to the top point of the triangle. If the specified value is +0.0, the particle will become a point particle. Note that this +command does not adjust the particle mass, even if it was defined with +a density, e.g. via the :doc:`read_data ` command. -Keyword *omega* sets the angular velocity of selected atoms. The -particles must be spheres as defined by the :doc:`atom_style sphere -` command. The angular velocity vector of the particles is -set to the 3 specified components. +.. versionchanged:: 28Mar2023 -Keyword *mass* sets the mass of all selected particles. The particles -must have a per-atom mass attribute, as defined by the :doc:`atom_style -` command. See the "mass" command for how to set mass -values on a per-type basis. - -Keyword *density* or *density/disc* also sets the mass of all selected -particles, but in a different way. The particles must have a per-atom -mass attribute, as defined by the :doc:`atom_style ` -command. If the atom has a radius attribute (see :doc:`atom_style -sphere `) and its radius is non-zero, its mass is set from -the density and particle volume for 3d systems (the input density is -assumed to be in mass/distance\^3 units). For 2d, the default is for -LAMMPS to model particles with a radius attribute as spheres. However, -if the *density/disc* keyword is used, then they can be modeled as 2d -discs (circles). Their mass is set from the density and particle area -(the input density is assumed to be in mass/distance\^2 units). - -If the atom has a shape attribute (see :doc:`atom_style ellipsoid -`) and its 3 shape parameters are non-zero, then its mass is -set from the density and particle volume (the input density is assumed -to be in mass/distance\^3 units). The *density/disc* keyword has no -effect; it does not (yet) treat 3d ellipsoids as 2d ellipses. - -If the atom has a length attribute (see :doc:`atom_style line -`) and its length is non-zero, then its mass is set from the -density and line segment length (the input density is assumed to be in -mass/distance units). If the atom has an area attribute (see -:doc:`atom_style tri `) and its area is non-zero, then its -mass is set from the density and triangle area (the input density is -assumed to be in mass/distance\^2 units). - -If none of these cases are valid, then the mass is set to the density -value directly (the input density is assumed to be in mass units). - -Keyword *temperature* sets the temperature of a finite-size particle. -Currently, only the GRANULAR package supports this attribute. The -temperature must be added using an instance of -:doc:`fix property/atom ` The values for the -temperature must be positive. - -Keyword *volume* sets the volume of all selected particles. Currently, -only the :doc:`atom_style peri ` command defines particles -with a volume attribute. Note that this command does not adjust the -particle mass. - -Keyword *image* sets which image of the simulation box the atom is -considered to be in. An image of 0 means it is inside the box as -defined. A value of 2 means add 2 box lengths to get the true value. A -value of -1 means subtract 1 box length to get the true value. LAMMPS -updates these flags as atoms cross periodic boundaries during the -simulation. The flags can be output with atom snapshots via the -:doc:`dump ` command. If a value of NULL is specified for any of -nx,ny,nz, then the current image value for that dimension is unchanged. -For non-periodic dimensions only a value of 0 can be specified. This -command can be useful after a system has been equilibrated and atoms -have diffused one or more box lengths in various directions. This -command can then reset the image values for atoms so that they are -effectively inside the simulation box, e.g if a diffusion coefficient is -about to be measured via the :doc:`compute msd ` command. -Care should be taken not to reset the image flags of two atoms in a bond -to the same value if the bond straddles a periodic boundary (rather they -should be different by +/- 1). This will not affect the dynamics of a -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. 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 label, etc). See the :doc:`Howto type labels + Support for type labels was added for setting atom 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 ` command or +the *atom types* field in the header of the data file read by the +:doc:`read_data ` command. When using a type label it must +have been defined previously. See the :doc:`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 ` command. These -keywords do not allow use of an atom-style variable. +and a general discussion of how type labels can be used. -Keywords *rheo/rho* and *rheo/status* set the density and the status of -rheo particles. In particular, one can only set the phase in the status -as described by the :doc:`RHEO howto page `. +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 +many processors are being used. This keyword does 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 -`this PDF guide `_ to using SPH in LAMMPS. +Keywords *type/ratio* and *type/subset* also set the atom type for a +fraction of the selected atoms. The actual number of atoms changed +will be exactly the requested number. For *type/ratio* the specified +fraction (0 <= *fraction* <= 1) determines the number. For +*type/subset*, the specified *Nsubset* is the number. An iterative +algorithm is used which ensures the correct number of atoms are +selected, in a perfectly random fashion. Which atoms are selected +will change with the number of processors used. These keywords do not +allow use of an atom-style variable. -.. note:: +Keyword *volume* sets the volume of all selected particles. +Currently, only the :doc:`atom_style peri ` command +defines particles with a volume attribute. Note that this command +does not adjust the particle mass. - Please note that the SPH PDF guide file has not been updated for - many years and thus does not reflect the current *syntax* of the - SPH package commands. For that please refer to the LAMMPS manual. +Keywords *vx*, *vy*, and *vz* set the velocities of all selected +atoms. -Keyword *smd/mass/density* sets the mass of all selected particles, but -it is only applicable to the Smooth Mach Dynamics package MACHDYN. It -assumes that the particle volume has already been correctly set and -calculates particle mass from the provided mass density value. - -Keyword *smd/contact/radius* only applies to simulations with the Smooth -Mach Dynamics package MACHDYN. Itsets an interaction radius for -computing short-range interactions, e.g. repulsive forces to prevent -different individual physical bodies from penetrating each other. Note -that the SPH smoothing kernel diameter used for computing long range, -nonlocal interactions, is set using the *diameter* keyword. - -Keyword *dpd/theta* sets the internal temperature of a DPD particle as -defined by the DPD-REACT package. If the specified value is a number it -must be >= 0.0. If the specified value is NULL, then the kinetic -temperature Tkin of each particle is computed as 3/2 k Tkin = KE = 1/2 m -v\^2 = 1/2 m (vx\*vx+vy\*vy+vz\*vz). Each particle's internal -temperature is set to Tkin. If the specified value is an atom-style -variable, then the variable is evaluated for each particle. If a value ->= 0.0, the internal temperature is set to that value. If it is < 0.0, -the computation of Tkin is performed and the internal temperature is set -to that value. - -Keywords *edpd/temp* and *edpd/cv* set the temperature and volumetric -heat capacity of an eDPD particle as defined by the DPD-MESO package. -Currently, only :doc:`atom_style edpd ` defines particles -with these attributes. The values for the temperature and heat capacity -must be positive. - -Keyword *cc* sets the chemical concentration of a tDPD particle for a -specified species as defined by the DPD-MESO package. Currently, only -:doc:`atom_style tdpd ` defines particles with this -attribute. An integer for "index" selects a chemical species (1 to -Nspecies) where Nspecies is set by the atom_style command. The value for -the chemical concentration must be >= 0.0. - -Keyword *epsilon* sets the dielectric constant of a particle, precisely -of the medium where the particle resides as defined by the DIELECTRIC -package. Currently, only :doc:`atom_style dielectric ` -defines particles with this attribute. The value for the dielectric -constant must be >= 0.0. Note that the set command with this keyword -will rescale the particle charge accordingly so that the real charge -(e.g., as read from a data file) stays intact. To change the real -charges, one needs to use the set command with the *charge* -keyword. Care must be taken to ensure that the real and scaled charges, -and dielectric constants are consistent. +Keywords *x*, *y*, *z* set the coordinates of all selected atoms. Keywords *i_name*, *d_name*, *i2_name*, *d2_name* refer to custom per-atom integer and floating-point vectors or arrays that have been added via the :doc:`fix property/atom ` command. When that command is used specific names are given to each attribute which are the "name" portion of these keywords. For arrays *i2_name* -and *d2_name*, the column of the array must also be included following -the name in brackets: e.g. d2_xyz[2], i2_mySpin[3]. +and *d2_name*, the column of the array to set must also be included +following the name in brackets: e.g. d2_xyz[2] or i2_mySpin[3]. Restrictions """""""""""" @@ -584,7 +643,7 @@ You cannot set an atom attribute (e.g. *mol* or *q* or *volume*\ ) if the :doc:`atom_style ` does not have that attribute. This command requires inter-processor communication to coordinate the -setting of bond types (angle types, etc). This means that your system +setting of bond types (angle types, etc). This means that the system must be ready to perform a simulation before using one of these keywords (force fields set, atom mass set, etc). This is not necessary for other keywords. diff --git a/doc/src/set2.rst b/doc/src/set2.rst deleted file mode 100644 index 92e6eaf65d..0000000000 --- a/doc/src/set2.rst +++ /dev/null @@ -1,656 +0,0 @@ -.. index:: set - -set command -=========== - -Syntax -"""""" - -.. code-block:: LAMMPS - - set style ID keyword values ... - -* style = *atom* or *type* or *mol* or *group* or *region* -* 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 = *angle* or *angmom* or *bond* or *cc* or *charge* or - *density* or *density/disc* or *diameter* or *dihedral* or *dipole* - or *dipole/random* or *dpd/theta* or *edpd/cv* or *edpd/temp* or - *epsilon* or *image* or *improper* or *length* or *mass* or *mol* or - *omega* or *quat* or *quat/random* or *radius/electron* or *shape* or - *smd/contact/radius* or *smd/mass/density* or *sph/cv* or *sph/e* or - *sph/rho* or *spin/atom* or *spin/atom/random* or *spin/electron* or - *temperature* or *theta* or *theta/random* or *tri* or *type* or - *type/fraction* or *type/ratio* or *type/subset* or *volume* or *vx* - or *vy* or *vz* or *x* or *y* or *z* or *i_name* or *d_name* or - *i2_name* or *d2_name* - - .. parsed-literal:: - - *angle* value = numeric angle type or angle type label, for all angles between selected atoms - *angmom* values = Lx Ly Lz - Lx,Ly,Lz = components of angular momentum vector (distance-mass-velocity units) - any of Lx,Ly,Lz can be an atom-style variable (see below) - *bond* value = numeric bond type or bond type label, for all bonds between selected atoms - *cc* values = index cc - index = index of a chemical species (1 to Nspecies) - cc = chemical concentration of tDPD particles for a species (mole/volume units) - cc can be an atom-style variable (see below) - *charge* value = atomic charge (charge units) - value can be an atom-style variable (see below) - *density* value = particle density for a sphere or ellipsoid (mass/distance\^3 units), or for a triangle (mass/distance\^2 units) or line (mass/distance units) particle - value can be an atom-style variable (see below) - *density/disc* value = particle density for a 2d disc or ellipse (mass/distance\^2 units) - value can be an atom-style variable (see below) - *diameter* value = diameter of spherical particle (distance units) - value can be an atom-style variable (see below) - *dihedral* value = numeric dihedral type or dihedral type label, for all dihedrals between selected atoms - *dipole* values = x y z - x,y,z = orientation of dipole moment vector - any of x,y,z can be an atom-style variable (see below) - *dipole/random* values = seed Dlen - seed = random # seed (positive integer) for dipole moment orientations - Dlen = magnitude of dipole moment (dipole units) - *dpd/theta* value = internal temperature of DPD particles (temperature units) - value can be an atom-style variable (see below) - value can be NULL which sets internal temp of each particle to KE temp - *edpd/cv* value = volumetric heat capacity of eDPD particles (energy/temperature/volume units) - value can be an atom-style variable (see below) - *edpd/temp* value = temperature of eDPD particles (temperature units) - value can be an atom-style variable (see below) - *epsilon* value = dielectric constant of the medium where the atoms reside - value can be an atom-style variable (see below) - *image* values = 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) - *improper* value = numeric improper type or improper type label, for all impropers between selected atoms - *length* value = len - len = length of line segment (distance units) - len can be an atom-style variable (see below) - *mass* value = per-atom mass (mass units) - value can be an atom-style variable (see below) - *mol* value = molecule ID - the moleclue ID can be an atom-style variable (see below) - *omega* values = Wx Wy Wz - Wx,Wy,Wz = components of angular velocity vector (radians/time units) - any of Wx,Wy,Wz can be an atom-style variable (see below) - *quat* values = a b c theta - a,b,c = unit vector to rotate particle around via right-hand rule - theta = rotation angle (degrees) - any of a,b,c,theta values can be an atom-style variable (see below) - *quat/random* value = seed - seed = random # seed (positive integer) for quaternion orientations - *radius/electron* value = eradius - eradius = electron radius (or fixed-core radius) (distance units) - value can be an atom-style variable (see below) - *shape* values = Sx Sy Sz - Sx,Sy,Sz = 3 diameters of ellipsoid (distance units) - any of Sx,Sy,Sz can be an atom-style variable (see below) - *smd/contact/radius* value = radius for short range interactions, i.e. contact and friction - value can be an atom-style variable (see below) - *smd/mass/density* value = set particle mass based on volume by providing a mass density - value can be an atom-style variable (see below) - *sph/cv* value = heat capacity of SPH particles (need units) - value can be an atom-style variable (see below) - *sph/e* value = energy of SPH particles (need units) - value can be an atom-style variable (see below) - *sph/rho* value = density of SPH particles (need units) - value can be an atom-style variable (see below) - *spin/atom* values = g x y z - g = magnitude of magnetic spin vector (in Bohr magneton's unit) - x,y,z = orientation of magnetic spin vector - any of x,y,z can be an atom-style variable (see below) - *spin/atom/random* values = seed Dlen - seed = random # seed (positive integer) for magnetic spin orientations - Dlen = magnitude of magnetic spin vector (in Bohr magneton's unit) - *spin/electron* value = espin - espin = electron spin (+1/-1), 0 = nuclei, 2 = fixed-core, 3 = pseudo-cores (i.e. ECP) - value can be an atom-style variable (see below) - *temperature* value = temperature for finite-size particles (temperature units) - value can be an atom-style variable (see below) - *theta* value = angle (degrees) - angle = orientation of line segment with respect to x-axis - value can be an atom-style variable (see below) - *theta/random* value = seed - seed = random # seed (positive integer) for line segment orienations - *tri* value = side - side = side length of equilateral triangle (distance units) - value can be an atom-style variable (see below) - *type* value = numeric atom type or type label - value can be an atom-style variable (see below) - *type/fraction* values = type fraction seed - 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 = 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 = numeric atom type or type label - Nsubset = exact number of selected atoms to set to new atom type - seed = random # seed (positive integer) - *volume* value = particle volume for Peridynamic particle (distance\^3 units) - value can be an atom-style variable (see below) - *vx*,\ *vy*,\ *vz* value = atom velocity (velocity units) - 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) - *i_name* value = custom integer vector with name - value can be an atom-style variable (see below) - *d_name* value = custom floating-point vector with name - value can be an atom-style variable (see below) - *i2_name* value = custom integer array with name - column specified as i2_name[N] where N is 1 to Ncol - value can be an atom-style variable (see below) - *d2_name* value = custom floating-point array with name - column specified as d2_name[N] where N is 1 to Ncol - value can be an atom-style variable (see below) - -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 - -Description -""""""""""" - -Set one or more properties of one or more atoms. Since atom -properties are initially assigned by the :doc:`read_data `, -:doc:`read_restart ` or :doc:`create_atoms ` -commands, this command changes those assignments. This can be useful -for overriding the default values assigned by the -:doc:`create_atoms ` command (e.g. charge = 0.0). It can -be useful for altering pairwise and molecular force interactions, -since force-field coefficients are defined in terms of types. It can -be used to change the labeling of atoms by atom type or molecule ID -when they are output in :doc:`dump ` files. It can also be useful -for debugging purposes; i.e. positioning an atom at a precise location -to compute subsequent forces or energy. - -Note that the *style* and *ID* arguments determine which atoms have -their properties reset. The remaining keywords specify which -properties to reset and what the new values are. Some strings like -*type* or *mol* can be used as a style and/or a keyword. - ----------- - -This section describes how to select which atoms to change -the properties of, via the *style* and *ID* arguments. - -.. 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 -of values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". For -example, for the style *type*, if N = the number of atom types, then -an asterisk with no numeric values means all types from 1 to N. A -leading asterisk means all types from 1 to n (inclusive). A trailing -asterisk means all types from n to N (inclusive). A middle asterisk -means all types from m to n (inclusive). For all the styles except -*mol*, the lowest value for the wildcard is 1; for *mol* it is 0. - -The style *group* selects all the atoms in the specified group. The -style *region* selects all the atoms in the specified geometric -region. See the :doc:`group ` and :doc:`region ` commands -for details of how to specify a group or region. - ----------- - -The next section describes the keyword options for which properties to -change, for the selected atoms. - -Note that except where explicitly prohibited below, all of the -keywords allow an :doc:`atom-style or atomfile-style variable -` to be used as the specified value(s). If the value is a -variable, it should be specified as v_name, where name is the -variable name. In this case, the variable will be evaluated, and its -resulting per-atom value used to determine the value assigned to each -selected atom. Note that the per-atom value from the variable will be -ignored for atoms that are not selected via the *style* and *ID* -settings explained above. A simple way to use per-atom values from -the variable to reset a property for all atoms is to use style *atom* -with *ID* = "\*"; this selects all atom IDs. - -Atom-style variables can specify formulas with various mathematical -functions, and include :doc:`thermo_style ` command -keywords for the simulation box parameters and timestep and elapsed -time. They can also include per-atom values, such as atom -coordinates. Thus it is easy to specify a time-dependent or -spatially-dependent set of per-atom values. As explained on the -:doc:`variable ` doc page, atomfile-style variables can be -used in place of atom-style variables, and thus as arguments to the -set command. Atomfile-style variables read their per-atoms values -from a file. - -.. note:: - - Atom-style and atomfile-style variables return floating point - per-atom values. If the values are assigned to an integer variable, - 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. - ----------- - -.. versionchanged:: 28Mar2023 - - Support for type labels was added for setting angle types - -Keyword *angle* sets the angle type of all angles of selected atoms to -the specified value. The value can be a numeric type from 1 to -nangletypes. Or it can be a angle type label. See the :doc:`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 angle must be selected atoms in order for -the change to be made. The value of nangletypes was set by the *angle -types* field in the header of the data file read by the -:doc:`read_data ` command. This keyword does not allow use -of an atom-style variable. - -Keyword *angmom* sets the angular momentum of selected atoms. The -particles must be ellipsoids as defined by the :doc:`atom_style -ellipsoid ` command or triangles as defined by the -:doc:`atom_style tri ` command. The angular momentum -vector of the particles is set to the 3 specified components. - -.. versionchanged:: 28Mar2023 - - Support for type labels was added for setting bond types - -Keyword *bond* sets the bond type of all bonds of selected atoms to -the specified value. The value can be a numeric type from 1 to -nbondtypes. Or it can be a bond type label. See the :doc:`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 must be selected atoms in order for the -change to be made. The value of nbondtypes was set by the *bond -types* field in the header of the data file read by the -:doc:`read_data ` command. This keyword does not allow use -of an atom-style variable. - -Keyword *cc* sets the chemical concentration of a tDPD particle for a -specified species as defined by the DPD-MESO package. Currently, only -:doc:`atom_style tdpd ` defines particles with this -attribute. An integer for "index" selects a chemical species (1 to -Nspecies) where Nspecies is set by the atom_style command. The value for -the chemical concentration must be >= 0.0. - -Keyword *charge* set the charge of all selected atoms. The :doc:`atom -style ` being used must support the use of atomic charge. - -Keyword *density* or *density/disc* also sets the mass of all selected -particles, but in a different way. The particles must have a per-atom -mass attribute, as defined by the :doc:`atom_style ` -command. If the atom has a radius attribute (see :doc:`atom_style -sphere `) and its radius is non-zero, its mass is set from -the density and particle volume for 3d systems (the input density is -assumed to be in mass/distance\^3 units). For 2d, the default is for -LAMMPS to model particles with a radius attribute as spheres. However, -if the *density/disc* keyword is used, then they can be modeled as 2d -discs (circles). Their mass is set from the density and particle area -(the input density is assumed to be in mass/distance\^2 units). - -If the atom has a shape attribute (see :doc:`atom_style ellipsoid -`) and its 3 shape parameters are non-zero, then its mass is -set from the density and particle volume (the input density is assumed -to be in mass/distance\^3 units). The *density/disc* keyword has no -effect; it does not (yet) treat 3d ellipsoids as 2d ellipses. - -If the atom has a length attribute (see :doc:`atom_style line -`) and its length is non-zero, then its mass is set from the -density and line segment length (the input density is assumed to be in -mass/distance units). If the atom has an area attribute (see -:doc:`atom_style tri `) and its area is non-zero, then its -mass is set from the density and triangle area (the input density is -assumed to be in mass/distance\^2 units). - -If none of these cases are valid, then the mass is set to the density -value directly (the input density is assumed to be in mass units). - -Keyword *diameter* sets the size of the selected atoms. The particles -must be finite-size spheres as defined by the :doc:`atom_style sphere -` command. The diameter of a particle can be set to 0.0, -which means they will be treated as point particles. Note that this -command does not adjust the particle mass, even if it was defined with -a density, e.g. via the :doc:`read_data ` command. - -.. versionchanged:: 28Mar2023 - - Support for type labels was added for setting dihedral types - -Keyword *dihedral* sets the dihedral type of all dihedrals of selected -atoms to the specified value. The value can be a numeric type from 1 -to ndihedraltypes. Or it can be a dihedral type label. See the -:doc:`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 dihedral must be selected atoms in -order for the change to be made. The value of ndihedraltypes was set -by the *dihedral types* field in the header of the data file read by -the :doc:`read_data ` command. This keyword does not allow -use of an atom-style variable. - -Keyword *dipole* uses the specified x,y,z values as components of a -vector to set as the orientation of the dipole moment vectors of the -selected atoms. The magnitude of the dipole moment is set by the -length of this orientation vector. - -Keyword *dipole/random* randomizes the orientation of the dipole -moment vectors for the selected atoms and sets the magnitude of each -to the specified *Dlen* value. For 2d systems, the z component of the -orientation is set to 0.0. Random numbers are used in such a way that -the orientation of a particular atom is the same, regardless of how -many processors are being used. This keyword does not allow use of an -atom-style variable. - -Keyword *dpd/theta* sets the internal temperature of a DPD particle as -defined by the DPD-REACT package. If the specified value is a number it -must be >= 0.0. If the specified value is NULL, then the kinetic -temperature Tkin of each particle is computed as 3/2 k Tkin = KE = 1/2 m -v\^2 = 1/2 m (vx\*vx+vy\*vy+vz\*vz). Each particle's internal -temperature is set to Tkin. If the specified value is an atom-style -variable, then the variable is evaluated for each particle. If a value ->= 0.0, the internal temperature is set to that value. If it is < 0.0, -the computation of Tkin is performed and the internal temperature is set -to that value. - -Keywords *edpd/temp* and *edpd/cv* set the temperature and volumetric -heat capacity of an eDPD particle as defined by the DPD-MESO package. -Currently, only :doc:`atom_style edpd ` defines particles -with these attributes. The values for the temperature and heat capacity -must be positive. - -Keyword *epsilon* sets the dielectric constant of a particle, precisely -of the medium where the particle resides as defined by the DIELECTRIC -package. Currently, only :doc:`atom_style dielectric ` -defines particles with this attribute. The value for the dielectric -constant must be >= 0.0. Note that the set command with this keyword -will rescale the particle charge accordingly so that the real charge -(e.g., as read from a data file) stays intact. To change the real -charges, one needs to use the set command with the *charge* -keyword. Care must be taken to ensure that the real and scaled charges, -and dielectric constants are consistent. - -Keyword *image* sets which image of the simulation box the atom is -considered to be in. An image of 0 means it is inside the box as -defined. A value of 2 means add 2 box lengths to get the true value. A -value of -1 means subtract 1 box length to get the true value. LAMMPS -updates these flags as atoms cross periodic boundaries during the -simulation. The flags can be output with atom snapshots via the -:doc:`dump ` command. If a value of NULL is specified for any of -nx,ny,nz, then the current image value for that dimension is unchanged. -For non-periodic dimensions only a value of 0 can be specified. This -command can be useful after a system has been equilibrated and atoms -have diffused one or more box lengths in various directions. This -command can then reset the image values for atoms so that they are -effectively inside the simulation box, e.g if a diffusion coefficient is -about to be measured via the :doc:`compute msd ` command. -Care should be taken not to reset the image flags of two atoms in a bond -to the same value if the bond straddles a periodic boundary (rather they -should be different by +/- 1). This will not affect the dynamics of a -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. - -.. versionchanged:: 28Mar2023 - - Support for type labels was added for setting improper types - -Keyword *improper* sets the improper type of all impropers of selected -atoms to the specified value. The value can be a numeric type from 1 -to nimpropertypes. Or it can be a improper type label. See the -:doc:`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 improper must be selected atoms in -order for the change to be made. The value of nimpropertypes was set -by the *improper types* field in the header of the data file read by -the :doc:`read_data ` command. This keyword does not allow -use of an atom-style variable. - -Keyword *length* sets the length of selected atoms. The particles -must be line segments as defined by the :doc:`atom_style line -` command. If the specified value is non-zero the line -segment is (re)set to a length = the specified value, centered around -the particle position, with an orientation along the x-axis. If the -specified value is 0.0, the particle will become a point particle. -Note that this command does not adjust the particle mass, even if it -was defined with a density, e.g. via the :doc:`read_data ` -command. - -Keyword *mass* sets the mass of all selected particles. The particles -must have a per-atom mass attribute, as defined by the :doc:`atom_style -` command. See the "mass" command for how to set mass -values on a per-type basis. - -Keyword *mol* sets the molecule ID for all selected atoms. The -:doc:`atom style ` being used must support the use of -molecule IDs. - -Keyword *omega* sets the angular velocity of selected atoms. The -particles must be spheres as defined by the :doc:`atom_style sphere -` command. The angular velocity vector of the particles is -set to the 3 specified components. - -Keyword *quat* uses the specified values to create a quaternion -(4-vector) that represents the orientation of the selected atoms. The -particles must define a quaternion for their orientation -(e.g. ellipsoids, triangles, body particles) as defined by the -:doc:`atom_style ` command. Note that particles defined by -:doc:`atom_style ellipsoid ` have 3 shape parameters. The 3 -values must be non-zero for each particle set by this command. They -are used to specify the aspect ratios of an ellipsoidal particle, -which is oriented by default with its x-axis along the simulation -box's x-axis, and similarly for y and z. If this body is rotated (via -the right-hand rule) by an angle theta around a unit rotation vector -(a,b,c), then the quaternion that represents its new orientation is -given by (cos(theta/2), a\*sin(theta/2), b\*sin(theta/2), -c\*sin(theta/2)). The theta and a,b,c values are the arguments to the -*quat* keyword. LAMMPS normalizes the quaternion in case (a,b,c) was -not specified as a unit vector. For 2d systems, the a,b,c values are -ignored, since a rotation vector of (0,0,1) is the only valid choice. - -Keyword *quat/random* randomizes the orientation of the quaternion for -the selected atoms. The particles must define a quaternion for their -orientation (e.g. ellipsoids, triangles, body particles) as defined by -the :doc:`atom_style ` command. Random numbers are used in -such a way that the orientation of a particular atom is the same, -regardless of how many processors are being used. For 2d systems, -only orientations in the xy plane are generated. As with keyword -*quat*, for ellipsoidal particles, the 3 shape values must be non-zero -for each particle set by this command. This keyword does not allow -use of an atom-style variable. - -.. versionadded:: 15Sep2022 - -Keyword *radius/electron* uses the specified value to set the radius of -electrons or fixed cores. - -Keyword *shape* sets the size and shape of the selected atoms. The -particles must be ellipsoids as defined by the :doc:`atom_style -ellipsoid ` command. The *Sx*, *Sy*, *Sz* settings -are the 3 diameters of the ellipsoid in each direction. All 3 can be -set to the same value, which means the ellipsoid is effectively a -sphere. They can also all be set to 0.0 which means the particle will -be treated as a point particle. Note that this command does not -adjust the particle mass, even if it was defined with a density, -e.g. via the :doc:`read_data ` command. - -Keyword *smd/contact/radius* only applies to simulations with the Smooth -Mach Dynamics package MACHDYN. Itsets an interaction radius for -computing short-range interactions, e.g. repulsive forces to prevent -different individual physical bodies from penetrating each other. Note -that the SPH smoothing kernel diameter used for computing long range, -nonlocal interactions, is set using the *diameter* keyword. - -Keyword *smd/mass/density* sets the mass of all selected particles, but -it is only applicable to the Smooth Mach Dynamics package MACHDYN. It -assumes that the particle volume has already been correctly set and -calculates particle mass from the provided mass density value. - -Keywords *sph/e*, *sph/cv*, and *sph/rho* set the energy, heat capacity, -and density of smoothed particle hydrodynamics (SPH) particles. See -`this PDF guide `_ to using SPH in LAMMPS. - -.. versionchanged:: 15Sep2022 - -Keyword *spin/atom* uses the specified g value to set the magnitude of the -magnetic spin vectors, and the x,y,z values as components of a vector -to set as the orientation of the magnetic spin vectors of the selected -atoms. This keyword was previously called *spin*. - -.. versionchanged:: 15Sep2022 - -Keyword *spin/atom/random* randomizes the orientation of the magnetic -spin vectors for the selected atoms and sets the magnitude of each to -the specified *Dlen* value. This keyword does not allow use of an -atom-style variable. This keyword was previously called -*spin/random*. - -.. versionadded:: 15Sep2022 - -Keyword *spin/electron* sets the spin of an electron (+/- 1) or indicates -nuclei (=0), fixed-cores (=2), or pseudo-cores (= 3). - -Keyword *temperature* sets the temperature of a finite-size particle. -Currently, only the GRANULAR package supports this attribute. The -temperature must be added using an instance of -:doc:`fix property/atom ` The values for the -temperature must be positive. - -Keyword *theta* sets the orientation of selected atoms. The particles -must be line segments as defined by the :doc:`atom_style line -` command. The specified value is used to set the -orientation angle of the line segments with respect to the x axis. - -Keyword *theta/random* randomizes the orientation of theta for the -selected atoms. The particles must be line segments as defined by the -:doc:`atom_style line ` command. Random numbers are used in -such a way that the orientation of a particular atom is the same, -regardless of how many processors are being used. This keyword does -not allow use of an atom-style variable. - -Keyword *tri* sets the size of selected atoms. The particles must be -triangles as defined by the :doc:`atom_style tri ` command. -If the specified value is non-zero the triangle is (re)set to be an -equilateral triangle in the xy plane with side length = the specified -value, with a centroid at the particle position, with its base -parallel to the x axis, and the y-axis running from the center of the -base to the top point of the triangle. If the specified value is 0.0, -the particle will become a point particle. Note that this command -does not adjust the particle mass, even if it was defined with a -density, e.g. via the :doc:`read_data ` command. - -.. versionchanged:: 28Mar2023 - - Support for type labels was added for setting atom 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 ` command or -the *atom types* field in the header of the data file read by the -:doc:`read_data ` command. When using a type label it must -have been defined previously. See the :doc:`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 -many processors are being used. This keyword does not allow use of an -atom-style variable. - -Keywords *type/ratio* and *type/subset* also set the atom type for a -fraction of the selected atoms. The actual number of atoms changed -will be exactly the requested number. For *type/ratio* the specified -fraction (0 <= *fraction* <= 1) determines the number. For -*type/subset*, the specified *Nsubset* is the number. An iterative -algorithm is used which ensures the correct number of atoms are -selected, in a perfectly random fashion. Which atoms are selected -will change with the number of processors used. These keywords do not -allow use of an atom-style variable. - -Keyword *volume* sets the volume of all selected particles. Currently, -only the :doc:`atom_style peri ` command defines particles -with a volume attribute. Note that this command does not adjust the -particle mass. - -Keywords *vx*, *vy*, and *vz* set the velocities of all selected -atoms. - -Keywords *x*, *y*, *z* set the coordinates of all selected atoms. - -Keywords *i_name*, *d_name*, *i2_name*, *d2_name* refer to custom -per-atom integer and floating-point vectors or arrays that have been -added via the :doc:`fix property/atom ` command. -When that command is used specific names are given to each attribute -which are the "name" portion of these keywords. For arrays *i2_name* -and *d2_name*, the column of the array to set must also be included -following the name in brackets: e.g. d2_xyz[2] or i2_mySpin[3]. - -Restrictions -"""""""""""" - -You cannot set an atom attribute (e.g. *mol* or *q* or *volume*\ ) if -the :doc:`atom_style ` does not have that attribute. - -This command requires inter-processor communication to coordinate the -setting of bond types (angle types, etc). This means that your system -must be ready to perform a simulation before using one of these -keywords (force fields set, atom mass set, etc). This is not -necessary for other keywords. - -Using the *region* style with the bond (angle, etc) keywords can give -unpredictable results if there are bonds (angles, etc) that straddle -periodic boundaries. This is because the region may only extend up to -the boundary and partner atoms in the bond (angle, etc) may have -coordinates outside the simulation box if they are ghost atoms. - -Related commands -"""""""""""""""" - -:doc:`create_box `, :doc:`create_atoms `, -:doc:`read_data ` - -Default -""""""" - -none diff --git a/src/fix_set.cpp b/src/fix_set.cpp new file mode 100644 index 0000000000..2e151a2372 --- /dev/null +++ b/src/fix_set.cpp @@ -0,0 +1,75 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "fix_set.h" + +#include "atom.h" +#include "error.h" +#include "set2.h" + +using namespace LAMMPS_NS; +using namespace FixConst; + +enum{SETCOMMAND,FIXSET}; // also used in Set class + +/* ---------------------------------------------------------------------- */ + +FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) +{ + if (narg < 7) error->all(FLERR, 1, "Illegal fix set command: need at least four arguments"); + + nevery = utils::inumeric(FLERR, arg[3], false, lmp); + if (nevery <= 0) error->all(FLERR, "Fix {} Nevery must be > 0", style); + + // create instance of Set class + + set = new Set2(lmp); + + // pass remaining args to Set class + // only keywords which use per-atom variables are currently allowed + + set->process_args(FIXSET,narg-4,&arg[4]); +} + +/* ---------------------------------------------------------------------- */ + +FixSet::~FixSet() +{ + delete set; +} + +/* ---------------------------------------------------------------------- */ + +int FixSet::setmask() +{ + int mask = 0; + mask |= END_OF_STEP; + return mask; +} + +/* ---------------------------------------------------------------------- + use the Set instance to update per-atom properties + NOTE: could return count of updated atoms from Set and use it as a fix output +---------------------------------------------------------------------- */ + +void FixSet::end_of_step() +{ + // select which atoms to act on + + set->selection(atom->nlocal); + + // loop over list of actions to reset atom attributes + + set->invoke_actions(); +} + diff --git a/src/fix_set.h b/src/fix_set.h new file mode 100644 index 0000000000..9826d764eb --- /dev/null +++ b/src/fix_set.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(set,FixSet); +// clang-format on +#else + +#ifndef LMP_FIX_SET_H +#define LMP_FIX_SET_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixSet : public Fix { + public: + FixSet(class LAMMPS *, int, char **); + ~FixSet() override; + int setmask() override; + void end_of_step() override; + + private: + class Set2 *set; +}; + +} // namespace LAMMPS_NS + +#endif +#endif diff --git a/src/set.cpp b/src/set.cpp index 7ae41e9246..f3b05a1152 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -42,15 +42,45 @@ using namespace LAMMPS_NS; using namespace MathConst; +enum{SETCOMMAND,FIXSET}; // also used in FixSet class + enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; -enum{TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET, - MOLECULE,X,Y,Z,VX,VY,VZ,CHARGE,MASS,SHAPE,LENGTH,TRI, - DIPOLE,DIPOLE_RANDOM,SPIN_ATOM,SPIN_RANDOM,SPIN_ELECTRON,RADIUS_ELECTRON, - QUAT,QUAT_RANDOM,THETA,THETA_RANDOM,ANGMOM,OMEGA,TEMPERATURE, - DIAMETER,RADIUS_ATOM,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER, - RHEO_STATUS,SPH_E,SPH_CV,SPH_RHO,EDPD_TEMP,EDPD_CV,CC,SMD_MASS_DENSITY, - SMD_CONTACT_RADIUS,DPDTHETA,EPSILON,IVEC,DVEC,IARRAY,DARRAY}; +enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, + DIPOLE_RANDOM,DPD_THETA,EDPD_CV,EDPD_TEMP,EPSILON,IMAGE,IMPROPER,LENGTH, + MASS,MOLECULE,OMEGA,QUAT,QUAT_RANDOM,RADIUS_ELECTRON,SHAPE, + SMD_CONTACT_RADIUS,SMD_MASS_DENSITY,SPH_CV,SPH_E,SPH_RHO, + SPIN_ATOM,SPIN_ATOM_RANDOM,SPIN_ELECTRON,TEMPERATURE,THETA,THETA_RANDOM, + TRI,TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET,VOLUME,VX,VY,VZ,X,Y,Z, + IVEC,DVEC,IARRAY,DARRAY}; + +#define DELTA 4 + +/* ---------------------------------------------------------------------- */ + +Set::Set(class LAMMPS *lmp) : Command(lmp) +{ + actions = nullptr; + invoke_choice = nullptr; + + select = nullptr; + vec1 = vec2 = vec3 = vec4 = nullptr; + maxselect = maxvariable = 0; +} + +/* ---------------------------------------------------------------------- */ + +Set::~Set() +{ + memory->sfree(actions); + memory->sfree(invoke_choice); + + memory->destroy(select); + memory->destroy(vec1); + memory->destroy(vec2); + memory->destroy(vec3); + memory->destroy(vec4); +} /* ---------------------------------------------------------------------- */ @@ -63,718 +93,367 @@ void Set::command(int narg, char **arg) error->all(FLERR, Error::NOLASTLINE, "Set command on system without atoms"); if (narg < 4) error->all(FLERR, 1, "Illegal set command: need at least four arguments"); - // style and ID info - - if (strcmp(arg[0],"atom") == 0) style = ATOM_SELECT; - else if (strcmp(arg[0],"mol") == 0) style = MOL_SELECT; - else if (strcmp(arg[0],"type") == 0) style = TYPE_SELECT; - else if (strcmp(arg[0],"group") == 0) style = GROUP_SELECT; - else if (strcmp(arg[0],"region") == 0) style = REGION_SELECT; - else error->all(FLERR, Error::ARGZERO, "Unknown set command style: {}", arg[0]); - - id = utils::strdup(arg[1]); - select = nullptr; - selection(atom->nlocal); - - // loop over keyword/value pairs - // call appropriate routine to reset attributes - + process_args(SETCOMMAND,narg,arg); + if (comm->me == 0) utils::logmesg(lmp,"Setting atom values ...\n"); - int allcount,origarg; + // select which atoms to act on + + selection(atom->nlocal); + + // loop over list of actions to reset atom attributes - int iarg = 2; - while (iarg < narg) { - varflag = varflag1 = varflag2 = varflag3 = varflag4 = 0; - count = 0; - origarg = iarg; + invoke_actions(); - 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::expand_type_int(FLERR, arg[iarg+1], Atom::ATOM, lmp); - set(TYPE); - iarg += 2; + // print stats for each action + // for CC option, include species index - } else if (strcmp(arg[iarg],"type/fraction") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); - newtype = utils::expand_type_int(FLERR, arg[iarg+1], Atom::ATOM, lmp); - fraction = utils::numeric(FLERR, arg[iarg+2], false, lmp); - ivalue = utils::inumeric(FLERR, arg[iarg+3], false, lmp); - if (newtype <= 0 || newtype > atom->ntypes) - error->all(FLERR, iarg + 1, "Invalid type value {} in set type/fraction command", newtype); - if (fraction < 0.0 || fraction > 1.0) - error->all(FLERR, iarg + 2, "Invalid fraction value {} in set type/fraction command", - fraction); - if (ivalue <= 0) - error->all(FLERR, iarg + 3, "Invalid random number seed {} in set type/fraction command", - ivalue); - setrandom(TYPE_FRACTION); - iarg += 4; - - } else if (strcmp(arg[iarg],"type/ratio") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error); - newtype = utils::expand_type_int(FLERR, arg[iarg+1], Atom::ATOM, lmp); - fraction = utils::numeric(FLERR, arg[iarg+2], false, lmp); - ivalue = utils::inumeric(FLERR, arg[iarg+3], false, lmp); - if (newtype <= 0 || newtype > atom->ntypes) - error->all(FLERR, iarg + 1, "Invalid type value {} in set type/ratio command", newtype); - if (fraction < 0.0 || fraction > 1.0) - error->all(FLERR, iarg + 2, "Invalid fraction value {} in set type/ratio command", - fraction); - if (ivalue <= 0) - error->all(FLERR, iarg + 3, "Invalid random number seed {} in set type/ratio command", - ivalue); - setrandom(TYPE_RATIO); - iarg += 4; - - } else if (strcmp(arg[iarg],"type/subset") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error); - newtype = utils::expand_type_int(FLERR, arg[iarg+1], Atom::ATOM, lmp); - nsubset = utils::bnumeric(FLERR, arg[iarg+2], false, lmp); - ivalue = utils::inumeric(FLERR, arg[iarg+3], false, lmp); - if (newtype <= 0 || newtype > atom->ntypes) - error->all(FLERR, iarg + 1, "Invalid type value {} in set type/subset command", newtype); - if (nsubset < 0) - error->all(FLERR, iarg + 2, "Invalid subset size {} in set type/subset command", nsubset); - if (ivalue <= 0) - error->all(FLERR, iarg + 3, "Invalid random number seed {} in set type/subset command", - ivalue); - setrandom(TYPE_SUBSET); - iarg += 4; - - } else if (strcmp(arg[iarg],"mol") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->molecule_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(MOLECULE); - iarg += 2; - - } else if (strcmp(arg[iarg],"x") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - set(X); - iarg += 2; - - } else if (strcmp(arg[iarg],"y") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - set(Y); - iarg += 2; - - } else if (strcmp(arg[iarg],"z") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - set(Z); - iarg += 2; - - } else if (strcmp(arg[iarg],"vx") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vx", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - set(VX); - iarg += 2; - - } else if (strcmp(arg[iarg],"vy") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vy", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - set(VY); - iarg += 2; - - } else if (strcmp(arg[iarg],"vz") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vz", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - set(VZ); - iarg += 2; - - } else if (strcmp(arg[iarg],"charge") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->q_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(CHARGE); - iarg += 2; - - } else if (strcmp(arg[iarg],"mass") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rmass_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(MASS); - iarg += 2; - - } else if (strcmp(arg[iarg],"shape") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->ellipsoid_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SHAPE); - iarg += 4; - - } else if (strcmp(arg[iarg],"length") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->line_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(LENGTH); - iarg += 2; - - } else if (strcmp(arg[iarg],"tri") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->tri_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(TRI); - iarg += 2; - - } else if (strcmp(arg[iarg],"dipole") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->mu_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(DIPOLE); - iarg += 4; - - } else if (strcmp(arg[iarg],"dipole/random") == 0) { - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (!atom->mu_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0) - error->all(FLERR, iarg + 1, "Invalid random number seed in set command"); - if (dvalue <= 0.0) - error->all(FLERR, iarg + 2, "Invalid dipole length in set command"); - setrandom(DIPOLE_RANDOM); - iarg += 3; - - } else if ((strcmp(arg[iarg],"spin") == 0) || (strcmp(arg[iarg],"spin/atom") == 0)) { - if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin is deprecated. Please use spin/atom instead."); - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else xvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else yvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else zvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); - if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) - error->all(FLERR, Error::NOPOINTER, "At least one spin vector component must be non-zero"); - if (!atom->sp_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (dvalue <= 0.0) - error->all(FLERR, iarg + 1, "Invalid spin magnitude {} in set {} command", dvalue, - arg[iarg]); - set(SPIN_ATOM); - iarg += 5; - - } else if ((strcmp(arg[iarg],"spin/random") == 0) || - (strcmp(arg[iarg],"spin/atom/random") == 0)) { - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin/random is deprecated. " - "Please use spin/atom/random instead."); - if (!atom->sp_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0) - error->all(FLERR, iarg + 1, "Invalid random number seed {} in set {} command", ivalue, - arg[iarg]); - if (dvalue <= 0.0) - error->all(FLERR, iarg + 2, "Invalid spin magnitude {} in set {} command", dvalue, - arg[iarg]); - setrandom(SPIN_RANDOM); - iarg += 3; - - } else if (strcmp(arg[iarg],"radius/electron") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->eradius_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(RADIUS_ELECTRON); - iarg += 2; - - } else if (strcmp(arg[iarg],"spin/electron") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->spin_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SPIN_ELECTRON); - iarg += 2; - - } else if (strcmp(arg[iarg],"quat") == 0) { - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else wvalue = utils::numeric(FLERR,arg[iarg+4],false,lmp); - if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(QUAT); - iarg += 5; - - } else if (strcmp(arg[iarg],"quat/random") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0) - error->all(FLERR, iarg + 1, "Invalid random number seed in set command"); - setrandom(QUAT_RANDOM); - iarg += 2; - - } else if (strcmp(arg[iarg],"theta") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->line_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(THETA); - iarg += 2; - - } else if (strcmp(arg[iarg],"theta/random") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); - ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->line_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0) - error->all(FLERR, iarg + 1, "Invalid random number seed in set command"); - set(THETA_RANDOM); - iarg += 2; - - } else if (strcmp(arg[iarg],"angmom") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->angmom_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(ANGMOM); - iarg += 4; - - } else if (strcmp(arg[iarg],"omega") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else xvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (!atom->omega_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(OMEGA); - iarg += 4; - - } else if (strcmp(arg[iarg],"radius/atom") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/atom", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->radius_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(RADIUS_ATOM); - iarg += 2; - - } else if (strcmp(arg[iarg],"diameter") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->radius_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(DIAMETER); - iarg += 2; - - } else if (strcmp(arg[iarg],"density") == 0 || - (strcmp(arg[iarg],"density/disc") == 0)) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rmass_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (dvalue <= 0.0) error->all(FLERR, iarg + 1, "Invalid density in set command"); - discflag = 0; - if (strcmp(arg[iarg],"density/disc") == 0) { - discflag = 1; - if (domain->dimension != 2) - error->all(FLERR, Error::NOLASTLINE, "Density/disc option requires 2d simulation"); - } - set(DENSITY); - iarg += 2; - - } else if (strcmp(arg[iarg],"temperature") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->temperature_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(TEMPERATURE); - iarg += 2; - - } else if (strcmp(arg[iarg],"volume") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->vfrac_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (dvalue <= 0.0) error->all(FLERR, iarg + 1, "Invalid volume in set command"); - set(VOLUME); - iarg += 2; - - } else if (strcmp(arg[iarg],"image") == 0) { - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); - ximageflag = yimageflag = zimageflag = 0; - if (strcmp(arg[iarg+1],"NULL") != 0) { - ximageflag = 1; - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ximage = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - } - if (strcmp(arg[iarg+2],"NULL") != 0) { - yimageflag = 1; - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else yimage = utils::inumeric(FLERR,arg[iarg+2],false,lmp); - } - if (strcmp(arg[iarg+3],"NULL") != 0) { - zimageflag = 1; - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else zimage = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - } - if (ximageflag && ximage && !domain->xperiodic) - error->all(FLERR, iarg + 1,"Cannot set non-zero image flag for non-periodic dimension"); - if (yimageflag && yimage && !domain->yperiodic) - error->all(FLERR, iarg + 2, "Cannot set non-zero image flag for non-periodic dimension"); - if (zimageflag && zimage && !domain->zperiodic) - error->all(FLERR, iarg + 3, "Cannot set non-zero image flag for non-periodic dimension"); - set(IMAGE); - iarg += 4; - - } else if (strcmp(arg[iarg],"bond") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); - ivalue = utils::expand_type_int(FLERR, arg[iarg+1], Atom::BOND, lmp); - if (atom->avec->bonds_allow == 0) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0 || ivalue > atom->nbondtypes) - error->all(FLERR, iarg + 1, "Invalid value {} in set bond command", ivalue); - topology(BOND); - iarg += 2; - - } else if (strcmp(arg[iarg],"angle") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); - ivalue = utils::expand_type_int(FLERR, arg[iarg+1], Atom::ANGLE, lmp); - if (atom->avec->angles_allow == 0) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0 || ivalue > atom->nangletypes) - error->all(FLERR, iarg + 1, "Invalid value {} in set angle command", ivalue); - topology(ANGLE); - iarg += 2; - - } else if (strcmp(arg[iarg],"dihedral") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); - ivalue = utils::expand_type_int(FLERR, arg[iarg+1], Atom::DIHEDRAL, lmp); - if (atom->avec->dihedrals_allow == 0) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0 || ivalue > atom->ndihedraltypes) - error->all(FLERR, iarg + 1, "Invalid value {} in set dihedral command", ivalue); - topology(DIHEDRAL); - iarg += 2; - - } else if (strcmp(arg[iarg],"improper") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); - ivalue = utils::expand_type_int(FLERR, arg[iarg+1], Atom::IMPROPER, lmp); - if (atom->avec->impropers_allow == 0) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - if (ivalue <= 0 || ivalue > atom->nimpropertypes) - error->all(FLERR, iarg + 1, "Invalid value {} in set improper command", ivalue); - topology(IMPROPER); - iarg += 2; - - } else if (strcmp(arg[iarg],"rheo/rho") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set rheo/rho", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rho_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SPH_RHO); - iarg += 2; - - } else if (strcmp(arg[iarg],"rheo/status") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set rheo/status", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rheo_status_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(RHEO_STATUS); - iarg += 2; - - } else if (strcmp(arg[iarg],"sph/e") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->esph_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SPH_E); - iarg += 2; - - } else if (strcmp(arg[iarg],"sph/cv") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->cv_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SPH_CV); - iarg += 2; - - } else if (strcmp(arg[iarg],"sph/rho") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->rho_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SPH_RHO); - iarg += 2; - - } else if (strcmp(arg[iarg],"edpd/temp") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) - error->all(FLERR, iarg + 1, "Invalid value {} in set edpd/temp command", dvalue); - } - if (!atom->edpd_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(EDPD_TEMP); - iarg += 2; - - } else if (strcmp(arg[iarg],"edpd/cv") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) - error->all(FLERR, iarg + 1, "Invalid value {} in set edpd/cv command", dvalue); - } - if (!atom->edpd_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(EDPD_CV); - iarg += 2; - - } else if (strcmp(arg[iarg],"cc") == 0) { - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - cc_index = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - dvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (cc_index < 1) error->all(FLERR,"Illegal set command"); - error->all(FLERR, iarg + 1, "Invalid index value {} in set cc command", cc_index); - } - if (!atom->tdpd_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(CC); - iarg += 3; - - } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->smd_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SMD_MASS_DENSITY); - iarg += 2; - - } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (!atom->smd_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(SMD_CONTACT_RADIUS); - iarg += 2; - - } else if (strcmp(arg[iarg],"dpd/theta") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) - error->all(FLERR, iarg + 1, "Invalid value {} in set dpd/theta command", dvalue); - } - if (!atom->dpd_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(DPDTHETA); - iarg += 2; - - } else if (strcmp(arg[iarg],"epsilon") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); - if (strcmp(arg[iarg+1],"NULL") == 0) dvalue = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dvalue < 0.0) - error->all(FLERR, iarg + 1, "Invalid value {} in set epsilon command", dvalue); - } - if (!atom->dielectric_flag) - error->all(FLERR, iarg, "Cannot set attribute {} for atom style {}", arg[iarg], - atom->get_style()); - set(EPSILON); - iarg += 2; - - } else { - - // set custom per-atom vector or array or error out - - int flag,cols; - ArgInfo argi(arg[iarg],ArgInfo::DNAME|ArgInfo::INAME); - const char *pname = argi.get_name(); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set", error); - index_custom = atom->find_custom(argi.get_name(),flag,cols); - if (index_custom < 0) - error->all(FLERR, iarg, "Set keyword or custom property {} does not exist", pname); - - switch (argi.get_type()) { - - case ArgInfo::INAME: - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else ivalue = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (flag != 0) - error->all(FLERR, iarg + 1, "Set command custom property {} is not integer", pname); - - if (argi.get_dim() == 0) { - if (cols > 0) - error->all(FLERR, iarg, "Set command custom integer property {} is not a vector", - pname); - set(IVEC); - } else if (argi.get_dim() == 1) { - if (cols == 0) - error->all(FLERR, iarg, "Set command custom integer property {} is not an array", - pname); - icol_custom = argi.get_index1(); - if (icol_custom <= 0 || icol_custom > cols) - error->all(FLERR, iarg, "Set command per-atom custom integer array {} is accessed " - "out-of-range{}", pname, utils::errorurl(20)); - set(IARRAY); - } else error->all(FLERR,"Illegal set command"); - break; - - case ArgInfo::DNAME: - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else dvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (flag != 1) error->all(FLERR,"Custom property {} is not floating-point",argi.get_name()); - - if (argi.get_dim() == 0) { - if (cols > 0) - error->all(FLERR, iarg, "Set command custom double property {} is not a vector", pname); - set(DVEC); - } else if (argi.get_dim() == 1) { - if (cols == 0) - error->all(FLERR, iarg, "Set command custom double property {} is not an array", pname); - icol_custom = argi.get_index1(); - if (icol_custom <= 0 || icol_custom > cols) - error->all(FLERR, iarg, "Set command per-atom custom double array {} is accessed " - "out-of-range{}", pname, utils::errorurl(20)); - set(DARRAY); - } else error->all(FLERR,"Illegal set command"); - break; - - default: - error->all(FLERR,"Illegal set command"); - break; - } - iarg += 2; - } - - // statistics - // for CC option, include species index - - MPI_Allreduce(&count,&allcount,1,MPI_INT,MPI_SUM,world); + bigint bcount,allcount; + for (int i = 0; i < naction; i++) { + Action *action = &actions[i]; + int iarg = action->argindex; + + if (action->count_action < 0) bcount = action->count_select; + else bcount = action->count_action; + MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); + if (comm->me == 0) { - if (strcmp(arg[origarg],"cc") == 0) + if (strcmp(arg[iarg],"cc") == 0) utils::logmesg(lmp," {} settings made for {} index {}\n", - allcount,arg[origarg],arg[origarg+1]); + allcount,arg[iarg],arg[iarg+1]); else utils::logmesg(lmp," {} settings made for {}\n", - allcount,arg[origarg]); + allcount,arg[iarg]); + } + } +} + +/* ---------------------------------------------------------------------- + process args of set command or fix set command +------------------------------------------------------------------------- */ + +void Set::process_args(int caller_flag, int narg, char **arg) +{ + caller = caller_flag; + + // style and ID info + + id = utils::strdup(arg[1]); + + if (strcmp(arg[0],"atom") == 0) { + style = ATOM_SELECT; + if (atom->tag_enable == 0) + error->all(FLERR,"Cannot use set atom with no atom IDs defined"); + utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); + + } else if (strcmp(arg[0],"mol") == 0) { + style = MOL_SELECT; + if (atom->molecule_flag == 0) + error->all(FLERR,"Cannot use set mol with no molecule IDs defined"); + utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); + + } else if (strcmp(arg[0],"type") == 0) { + 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); + + } else if (strcmp(arg[0],"group") == 0) { + style = GROUP_SELECT; + int igroup = group->find(id); + if (igroup == -1) error->all(FLERR,"Could not find set group ID {}", id); + groupbit = group->bitmask[igroup]; + + } else if (strcmp(arg[0],"region") == 0) { + style = REGION_SELECT; + region = domain->get_region_by_id(id); + if (!region) error->all(FLERR,"Set region {} does not exist", id); + + } else error->all(FLERR,"Unknown set or fix set command style: {}", arg[0]); + + delete [] id; + + // loop over remaining keyword/value pairs to create list of actions + // one action = keyword/value pair + + naction = maxaction = 0; + actions = nullptr; + Action *action; + + int iarg = 2; + while (iarg < narg) { + + // grow list of actions if needed + + if (naction == maxaction) { + maxaction += DELTA; + actions = (Action *) memory->srealloc(actions,maxaction*sizeof(Action),"set:actions"); + invoke_choice = (FnPtrPack *) + memory->srealloc(invoke_choice,maxaction*sizeof(FnPtrPack),"set:invoke_choice"); + } + + action = &actions[naction]; + action->argindex = iarg; + action->varflag = 0; + action->varflag1 = action->varflag2 = action->varflag3 = action->varflag4 = 0; + + if (strcmp(arg[iarg],"angle") == 0) { + action->keyword = ANGLE; + process_angle(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_angle; + } else if (strcmp(arg[iarg],"angmom") == 0) { + action->keyword = ANGMOM; + process_angmom(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_angmom; + } else if (strcmp(arg[iarg],"bond") == 0) { + action->keyword = BOND; + process_bond(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_bond; + } else if (strcmp(arg[iarg],"cc") == 0) { + action->keyword = CC; + process_cc(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_cc; + } else if (strcmp(arg[iarg],"charge") == 0) { + action->keyword = CHARGE; + process_charge(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_charge; + } else if (strcmp(arg[iarg],"density") == 0 ||(strcmp(arg[iarg],"density/disc") == 0)) { + action->keyword = DENSITY; + process_density(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_density; + } else if (strcmp(arg[iarg],"diameter") == 0) { + action->keyword = DIAMETER; + process_diameter(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_diameter; + } else if (strcmp(arg[iarg],"dihedral") == 0) { + action->keyword = DIHEDRAL; + process_dihedral(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_dihedral; + } else if (strcmp(arg[iarg],"dipole") == 0) { + action->keyword = DIPOLE; + process_dipole(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_dipole; + } else if (strcmp(arg[iarg],"dipole/random") == 0) { + action->keyword = DIPOLE_RANDOM; + process_dipole_random(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_dipole_random; + } else if (strcmp(arg[iarg],"dpd/theta") == 0) { + action->keyword = DPD_THETA; + process_dpd_theta(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_dpd_theta; + } else if (strcmp(arg[iarg],"edpd/cv") == 0) { + action->keyword = EDPD_CV; + process_edpd_cv(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_edpd_cv; + } else if (strcmp(arg[iarg],"edpd/temp") == 0) { + action->keyword = EDPD_TEMP; + process_edpd_temp(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_edpd_temp; + } else if (strcmp(arg[iarg],"epsilon") == 0) { + action->keyword = EPSILON; + process_epsilon(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_epsilon; + } else if (strcmp(arg[iarg],"image") == 0) { + action->keyword = IMAGE; + process_image(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_image; + } else if (strcmp(arg[iarg],"improper") == 0) { + action->keyword = IMPROPER; + process_improper(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_improper; + } else if (strcmp(arg[iarg],"length") == 0) { + action->keyword = LENGTH; + process_length(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_length; + } else if (strcmp(arg[iarg],"mass") == 0) { + action->keyword = MASS; + process_mass(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_mass; + } else if (strcmp(arg[iarg],"mol") == 0) { + action->keyword = MOLECULE; + process_mol(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_mol; + } else if (strcmp(arg[iarg],"omega") == 0) { + action->keyword = OMEGA; + process_omega(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_omega; + } else if (strcmp(arg[iarg],"quat") == 0) { + action->keyword = QUAT; + process_quat(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_quat; + } else if (strcmp(arg[iarg],"quat/random") == 0) { + action->keyword = QUAT_RANDOM; + process_quat_random(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_quat_random; + } else if (strcmp(arg[iarg],"radius/electron") == 0) { + action->keyword = RADIUS_ELECTRON; + process_radius_election(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_radius_election; + } else if (strcmp(arg[iarg],"shape") == 0) { + action->keyword = SHAPE; + process_shape(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_shape; + } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { + action->keyword = SMD_CONTACT_RADIUS; + process_smd_contact_radius(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_smd_contact_radius; + } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { + action->keyword = SMD_MASS_DENSITY; + process_smd_mass_density(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_density; + } else if (strcmp(arg[iarg],"sph/cv") == 0) { + action->keyword = SPH_CV; + process_sph_cv(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_sph_cv; + } else if (strcmp(arg[iarg],"sph/e") == 0) { + action->keyword = SPH_E; + process_sph_e(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_sph_e; + } else if (strcmp(arg[iarg],"sph/rho") == 0) { + action->keyword = SPH_RHO; + process_sph_rho(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_sph_rho; + } else if ((strcmp(arg[iarg],"spin/atom") == 0) || (strcmp(arg[iarg],"spin") == 0)) { + action->keyword = SPIN_ATOM; + process_spin_atom(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_spin_atom; + } else if ((strcmp(arg[iarg],"spin/atom/random") == 0) || (strcmp(arg[iarg],"spin/random") == 0)) { + action->keyword = SPIN_ATOM_RANDOM; + process_spin_atom_random(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_spin_atom_random; + } else if (strcmp(arg[iarg],"spin/electron") == 0) { + action->keyword = SPIN_ELECTRON; + process_spin_electron(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_spin_electron; + } else if (strcmp(arg[iarg],"temperature") == 0) { + action->keyword = TEMPERATURE; + process_temperature(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_temperature; + } else if (strcmp(arg[iarg],"theta") == 0) { + action->keyword = THETA; + process_theta(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_theta; + } else if (strcmp(arg[iarg],"theta/random") == 0) { + action->keyword = THETA_RANDOM; + process_theta_random(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_theta_random; + } else if (strcmp(arg[iarg],"tri") == 0) { + action->keyword = TRI; + process_tri(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_tri; + } else if (strcmp(arg[iarg],"type") == 0) { + action->keyword = TYPE; + process_type(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_type; + } else if (strcmp(arg[iarg],"type/fraction") == 0) { + action->keyword = TYPE_FRACTION; + process_type_fraction(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_type_fraction; + } else if (strcmp(arg[iarg],"type/ratio") == 0) { + action->keyword = TYPE_RATIO; + process_type_ratio(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_type_ratio; + } else if (strcmp(arg[iarg],"type/subset") == 0) { + action->keyword = TYPE_SUBSET; + process_type_subset(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_type_subset; + } else if (strcmp(arg[iarg],"volume") == 0) { + action->keyword = VOLUME; + process_volume(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_volume; + } else if (strcmp(arg[iarg],"vx") == 0) { + action->keyword = VX; + process_vx(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_vx; + } else if (strcmp(arg[iarg],"vy") == 0) { + action->keyword = VY; + process_vy(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_vy; + } else if (strcmp(arg[iarg],"vz") == 0) { + action->keyword = VZ; + process_vz(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_vz; + } else if (strcmp(arg[iarg],"x") == 0) { + action->keyword = X; + process_x(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_x; + } else if (strcmp(arg[iarg],"y") == 0) { + action->keyword = Y; + process_y(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_y; + } else if (strcmp(arg[iarg],"z") == 0) { + action->keyword = Z; + process_z(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_z; + + } else if (utils::strmatch(arg[iarg],"^[id]2?_")) { + process_custom(iarg,narg,arg,action); + invoke_choice[naction++] = &Set::invoke_custom; + + // unrecognized keyword + + } else error->all(FLERR,"Unrecognized set or fix set comand keyword {}",arg[iarg]); + } + + // varflag = 1 if any action uses a per-atom variable + // varflag1234 = 1 if any action uses a specific per-atom variable + + varflag = 0; + varflag1 = varflag2 = varflag3 = varflag4 = 0; + for (int i = 0; i < naction; i++) { + action = &actions[i]; + if (action->varflag) varflag = 1; + if (action->varflag1) varflag1 = 1; + if (action->varflag2) varflag2 = 1; + if (action->varflag3) varflag3 = 1; + if (action->varflag4) varflag4 = 1; + } + + // error if any action of fix set command does not use a per-atom variable + // b/c fix set is then effectivly a no-op + + if (caller == FIXSET) { + for (int i = 0; i < naction; i++) { + action = &actions[i]; + if (!action->varflag) + error->all(FLERR,"Fix set command keyword {} does not invoke a per-atom variable", + arg[action->argindex]); } } - // free local memory + // warn if a keyword sets properties for atoms in rigid bodies + // assume no conflict for properties not in this list of cases + + for (int i = 0; i < naction; i++) { + switch (actions[i].keyword) { + case X: + case Y: + case Z: + case MOLECULE: + case MASS: + case ANGMOM: + case SHAPE: + case DIAMETER: + case DENSITY: + case TEMPERATURE: + case QUAT: + case IMAGE: + if (modify->check_rigid_list_overlap(select)) + error->warning(FLERR,"Setting a property of atoms in rigid bodies " + "that has no effect unless rigid bodies are re-initialized"); + break; + default: + break; + } + } - delete[] id; - delete[] select; + // in future, could return index to next arg to process + // i.e. if fix set command appends its own options + + // return iarg; } /* ---------------------------------------------------------------------- @@ -784,468 +463,143 @@ void Set::command(int narg, char **arg) void Set::selection(int n) { - delete[] select; - select = new int[n]; - int nlo,nhi; + // reallocate select vector if needed + // this method could be called many times by fix set command + + if (n > maxselect) { + memory->destroy(select); + memory->create(select,n,"set:select"); + maxselect = n; + } if (style == ATOM_SELECT) { - if (atom->tag_enable == 0) - error->all(FLERR, Error::NOLASTLINE, "Cannot use set atom with no atom IDs defined"); - bigint nlobig,nhibig; - utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); - tagint *tag = atom->tag; for (int i = 0; i < n; i++) if (tag[i] >= nlobig && tag[i] <= nhibig) select[i] = 1; else select[i] = 0; } else if (style == MOL_SELECT) { - if (atom->molecule_flag == 0) - error->all(FLERR, Error::NOLASTLINE, "Cannot use set mol with no molecule IDs defined"); - bigint nlobig,nhibig; - utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); - tagint *molecule = atom->molecule; for (int i = 0; i < n; i++) if (molecule[i] >= nlobig && molecule[i] <= nhibig) select[i] = 1; else select[i] = 0; } else if (style == TYPE_SELECT) { - utils::bounds_typelabel(FLERR,id,1,atom->ntypes,nlo,nhi,lmp,Atom::ATOM); - int *type = atom->type; for (int i = 0; i < n; i++) if (type[i] >= nlo && type[i] <= nhi) select[i] = 1; else select[i] = 0; } else if (style == GROUP_SELECT) { - int igroup = group->find(id); - if (igroup == -1) error->all(FLERR, Error::NOLASTLINE, "Could not find set group ID {}", id); - int groupbit = group->bitmask[igroup]; - int *mask = atom->mask; for (int i = 0; i < n; i++) if (mask[i] & groupbit) select[i] = 1; else select[i] = 0; } else if (style == REGION_SELECT) { - auto region = domain->get_region_by_id(id); - if (!region) error->all(FLERR, Error::NOLASTLINE, "Set region {} does not exist", id); region->prematch(); - double **x = atom->x; for (int i = 0; i < n; i++) - if (region->match(x[i][0],x[i][1],x[i][2])) - select[i] = 1; + if (region->match(x[i][0],x[i][1],x[i][2])) select[i] = 1; else select[i] = 0; } + + // count_select = count of selected owned atoms + + count_select = 0; + for (int i = 0; i < n; i++) + if (select[i]) count_select++; } /* ---------------------------------------------------------------------- - set owned atom properties directly - either scalar or per-atom values from atom-style variable(s) + loop over list of actions + perform each action on all selected atoms via call to invoke_choice() method ------------------------------------------------------------------------- */ -void Set::set(int keyword) +void Set::invoke_actions() { - // evaluate atom-style variable(s) if necessary - - vec1 = vec2 = vec3 = vec4 = nullptr; - - if (varflag) { - int nlocal = atom->nlocal; + // reallocate per-atom variable storage if needed + + if (varflag && atom->nlocal > maxvariable) { + maxvariable = atom->nlocal; if (varflag1) { - memory->create(vec1,nlocal,"set:vec1"); - input->variable->compute_atom(ivar1,0,vec1,1,0); + memory->destroy(vec1); + memory->create(vec1,maxvariable,"set:var1"); } if (varflag2) { - memory->create(vec2,nlocal,"set:vec2"); - input->variable->compute_atom(ivar2,0,vec2,1,0); + memory->destroy(vec2); + memory->create(vec2,maxvariable,"set:var2"); } if (varflag3) { - memory->create(vec3,nlocal,"set:vec3"); - input->variable->compute_atom(ivar3,0,vec3,1,0); + memory->destroy(vec3); + memory->create(vec3,maxvariable,"set:var3"); } if (varflag4) { - memory->create(vec4,nlocal,"set:vec4"); - input->variable->compute_atom(ivar4,0,vec4,1,0); + memory->destroy(vec4); + memory->create(vec4,maxvariable,"set:var4"); } } - // check if properties of atoms in rigid bodies are updated - // that are cached as per-body data. - switch (keyword) { - case X: - case Y: - case Z: - case MOLECULE: - case MASS: - case ANGMOM: - case SHAPE: - case DIAMETER: - case DENSITY: - case TEMPERATURE: - case QUAT: - case IMAGE: - if (modify->check_rigid_list_overlap(select)) - error->warning(FLERR,"Changing a property of atoms in rigid bodies " - "that has no effect unless rigid bodies are rebuild"); - break; - default: // assume no conflict for all other properties - break; - } + // loop over actions + + for (int i = 0; i < naction; i++) { - // loop over selected atoms + Action *action = &actions[i]; - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - auto avec_line = dynamic_cast(atom->style_match("line")); - auto avec_tri = dynamic_cast(atom->style_match("tri")); - auto avec_body = dynamic_cast(atom->style_match("body")); + // use count_action to optionally override count_select + // if stays -1, count_select is used by caller + // if overwritten by an invoke method, count_action is used + // only a handful of invoke methods tally their own count + + count_action = -1; + + // evaluate atom-style variable(s) if necessary - int nlocal = atom->nlocal; - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - // overwrite dvalue, ivalue, xyzw value if variables defined - // else the input script scalar value remains in place - - if (varflag) { - if (varflag1) { - dvalue = xvalue = vec1[i]; - ivalue = static_cast (dvalue); + if (action->varflag) { + if (action->varflag1) { + input->variable->compute_atom(action->ivar1,0,vec1,1,0); } - if (varflag2) yvalue = vec2[i]; - if (varflag3) zvalue = vec3[i]; - if (varflag4) wvalue = vec4[i]; - } - - // set values in per-atom arrays - // error check here in case atom-style variables generated bogus value - - if (keyword == TYPE) { - if (ivalue <= 0 || ivalue > atom->ntypes) - error->one(FLERR, Error::NOLASTLINE, "Invalid value {} in set type command", ivalue); - atom->type[i] = ivalue; - } - else if (keyword == MOLECULE) atom->molecule[i] = ivalue; - else if (keyword == X) atom->x[i][0] = dvalue; - else if (keyword == Y) atom->x[i][1] = dvalue; - else if (keyword == Z) atom->x[i][2] = dvalue; - else if (keyword == VX) atom->v[i][0] = dvalue; - else if (keyword == VY) atom->v[i][1] = dvalue; - else if (keyword == VZ) atom->v[i][2] = dvalue; - else if (keyword == CHARGE) { - atom->q[i] = dvalue; - // ensure that scaled charges are consistent the new charge value - if (atom->epsilon) atom->q_scaled[i] = dvalue / atom->epsilon[i]; - } else if (keyword == MASS) { - if (dvalue <= 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid mass {} in set command", dvalue); - atom->rmass[i] = dvalue; - } - else if (keyword == DIAMETER) { - if (dvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid diameter {} in set command", dvalue); - atom->radius[i] = 0.5 * dvalue; - } - else if (keyword == VOLUME) { - if (dvalue <= 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid volume {} in set command", dvalue); - atom->vfrac[i] = dvalue; - } - - else if (keyword == RHEO_STATUS) { - if (ivalue != 0 && ivalue != 1) - error->one(FLERR, Error::NOLASTLINE, "Invalid value {} in set command for rheo/status", - ivalue); - atom->rheo_status[i] = ivalue; - } - - else if (keyword == SPH_E) atom->esph[i] = dvalue; - else if (keyword == SPH_CV) atom->cv[i] = dvalue; - else if (keyword == SPH_RHO) atom->rho[i] = dvalue; - - else if (keyword == EDPD_TEMP) atom->edpd_temp[i] = dvalue; - else if (keyword == EDPD_CV) atom->edpd_cv[i] = dvalue; - else if (keyword == CC) atom->cc[i][cc_index-1] = dvalue; - - else if (keyword == SMD_MASS_DENSITY) { - // set mass from volume and supplied mass density - atom->rmass[i] = atom->vfrac[i] * dvalue; - } - else if (keyword == SMD_CONTACT_RADIUS) atom->contact_radius[i] = dvalue; - - else if (keyword == DPDTHETA) { - if (dvalue >= 0.0) atom->dpdTheta[i] = dvalue; - else { - double onemass; - if (atom->rmass) onemass = atom->rmass[i]; - else onemass = atom->mass[atom->type[i]]; - double vx = atom->v[i][0]; - double vy = atom->v[i][1]; - double vz = atom->v[i][2]; - double tfactor = force->mvv2e / (domain->dimension * force->boltz); - atom->dpdTheta[i] = tfactor * onemass * (vx*vx + vy*vy + vz*vz); + if (action->varflag2) { + input->variable->compute_atom(action->ivar2,0,vec2,1,0); + } + if (action->varflag3) { + input->variable->compute_atom(action->ivar3,0,vec3,1,0); + } + if (action->varflag4) { + input->variable->compute_atom(action->ivar4,0,vec4,1,0); } } - // set shape of ellipsoidal particle + // invoke the action to reset per-atom or per-topology values + + (this->*invoke_choice[i])(action); - else if (keyword == SHAPE) { - if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid ellipsoid shape {} {} {} in set command", - xvalue, yvalue, zvalue); - if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) { - if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid ellipsoid shape {} {} {} in set command", - xvalue, yvalue, zvalue); - } - avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); - } - - // set length of line particle - - else if (keyword == LENGTH) { - if (dvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid length {} in set command", dvalue); - avec_line->set_length(i,dvalue); - } - - // set corners of tri particle - - else if (keyword == TRI) { - if (dvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid length {} in set command", dvalue); - avec_tri->set_equilateral(i,dvalue); - } - - // set rmass via density - // if radius > 0.0, treat as sphere or disc - // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) - // if length > 0.0, treat as line - // if area > 0.0, treat as tri - // else set rmass to density directly - - else if (keyword == DENSITY) { - if (dvalue <= 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid density {} in set command", dvalue); - if (atom->radius_flag && atom->radius[i] > 0.0) - if (discflag) - atom->rmass[i] = MY_PI*atom->radius[i]*atom->radius[i] * dvalue; - else - atom->rmass[i] = 4.0*MY_PI/3.0 * - atom->radius[i]*atom->radius[i]*atom->radius[i] * dvalue; - else if (atom->ellipsoid_flag && atom->ellipsoid[i] >= 0) { - double *shape = avec_ellipsoid->bonus[atom->ellipsoid[i]].shape; - // enable 2d ellipse (versus 3d ellipsoid) when time integration - // options (fix nve/asphere, fix nh/asphere) are also implemented - // if (discflag) - // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; - // else - atom->rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue; - } else if (atom->line_flag && atom->line[i] >= 0) { - double length = avec_line->bonus[atom->line[i]].length; - atom->rmass[i] = length * dvalue; - } else if (atom->tri_flag && atom->tri[i] >= 0) { - double *c1 = avec_tri->bonus[atom->tri[i]].c1; - double *c2 = avec_tri->bonus[atom->tri[i]].c2; - double *c3 = avec_tri->bonus[atom->tri[i]].c3; - double c2mc1[3],c3mc1[3]; - MathExtra::sub3(c2,c1,c2mc1); - MathExtra::sub3(c3,c1,c3mc1); - double norm[3]; - MathExtra::cross3(c2mc1,c3mc1,norm); - double area = 0.5 * MathExtra::len3(norm); - atom->rmass[i] = area * dvalue; - } else atom->rmass[i] = dvalue; - } - - // set dipole moment - - else if (keyword == DIPOLE) { - double **mu = atom->mu; - mu[i][0] = xvalue; - mu[i][1] = yvalue; - mu[i][2] = zvalue; - mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + - mu[i][2]*mu[i][2]); - } - - // set magnetic moments - - else if (keyword == SPIN_ATOM) { - if (dvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Incorrect value for atomic spin magnitude: {}", - dvalue); - double **sp = atom->sp; - double inorm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); - sp[i][0] = inorm*xvalue; - sp[i][1] = inorm*yvalue; - sp[i][2] = inorm*zvalue; - sp[i][3] = dvalue; - } - - // set electron radius - - else if (keyword == RADIUS_ELECTRON) { - atom->eradius[i] = dvalue; - if (dvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Incorrect value for electron radius: {}", dvalue); - } - - // set electron spin - - else if (keyword == SPIN_ELECTRON) { - if ((dvalue == -1) || (dvalue == 1) || (dvalue == 0) || (dvalue == 2) || (dvalue == 3)) - atom->spin[i] = (int)dvalue; - else - error->one(FLERR, Error::NOLASTLINE, "Incorrect value for electron spin: {}", dvalue); - } - - // set quaternion orientation of ellipsoid or tri or body particle or sphere/bpm - // enforce quat rotation vector in z dir for 2d systems - - else if (keyword == QUAT) { - double *quat = nullptr; - double **quat2 = nullptr; - if (avec_ellipsoid && atom->ellipsoid[i] >= 0) - quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; - else if (avec_tri && atom->tri[i] >= 0) - quat = avec_tri->bonus[atom->tri[i]].quat; - else if (avec_body && atom->body[i] >= 0) - quat = avec_body->bonus[atom->body[i]].quat; - else if (atom->quat_flag) - quat2 = atom->quat; - else - error->one(FLERR, Error::NOLASTLINE, "Cannot set quaternion for atom that has none"); - if (domain->dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) - error->one(FLERR, Error::NOLASTLINE, - "Cannot set quaternion with xy components for 2d system"); - - const double theta2 = MY_PI2 * wvalue/180.0; - const double sintheta2 = sin(theta2); - double temp[4]; - temp[0] = cos(theta2); - temp[1] = xvalue * sintheta2; - temp[2] = yvalue * sintheta2; - temp[3] = zvalue * sintheta2; - MathExtra::qnormalize(temp); - if (atom->quat_flag) { - quat2[i][0] = temp[0]; - quat2[i][1] = temp[1]; - quat2[i][2] = temp[2]; - quat2[i][3] = temp[3]; - } else { - quat[0] = temp[0]; - quat[1] = temp[1]; - quat[2] = temp[2]; - quat[3] = temp[3]; - } - } - - // set theta of line particle - - else if (keyword == THETA) { - if (atom->line[i] < 0) - error->one(FLERR, Error::NOLASTLINE, "Cannot set theta for atom that is not a line"); - avec_line->bonus[atom->line[i]].theta = dvalue; - } - - // set angmom or omega of particle - - else if (keyword == ANGMOM) { - atom->angmom[i][0] = xvalue; - atom->angmom[i][1] = yvalue; - atom->angmom[i][2] = zvalue; - } - - else if (keyword == OMEGA) { - atom->omega[i][0] = xvalue; - atom->omega[i][1] = yvalue; - atom->omega[i][2] = zvalue; - } - - // set temperature of particle - - else if (keyword == TEMPERATURE) { - if (dvalue < 0.0) - error->one(FLERR, Error::NOLASTLINE, "Invalid temperature {} in set command", dvalue); - atom->temperature[i] = dvalue; - } - - // reset any or all of 3 image flags - - else if (keyword == IMAGE) { - int xbox = (atom->image[i] & IMGMASK) - IMGMAX; - int ybox = (atom->image[i] >> IMGBITS & IMGMASK) - IMGMAX; - int zbox = (atom->image[i] >> IMG2BITS) - IMGMAX; - if (varflag1) ximage = static_cast(xvalue); - if (varflag2) yimage = static_cast(yvalue); - if (varflag3) zimage = static_cast(zvalue); - if (ximageflag) xbox = ximage; - if (yimageflag) ybox = yimage; - if (zimageflag) zbox = zimage; - atom->image[i] = ((imageint) (xbox + IMGMAX) & IMGMASK) | - (((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) | - (((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS); - } - - // set the local dielectric constant - - else if (keyword == EPSILON) { - if (dvalue >= 0.0) { - - // assign the new local dielectric constant - // update both the scaled charge value - - atom->epsilon[i] = dvalue; - atom->q_scaled[i] = atom->q[i] / dvalue; - } - } - - // set value for custom property vector or array - - else if (keyword == IVEC) { - atom->ivector[index_custom][i] = ivalue; - } - - else if (keyword == DVEC) { - atom->dvector[index_custom][i] = dvalue; - } - - else if (keyword == IARRAY) { - atom->iarray[index_custom][i][icol_custom-1] = ivalue; - } - - else if (keyword == DARRAY) { - atom->darray[index_custom][i][icol_custom-1] = dvalue; - } - - count++; + action->count_select = count_select; + action->count_action = count_action; } +} - // update bonus data numbers +/* ---------------------------------------------------------------------- */ - if (keyword == SHAPE) { - bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->nellipsoids,1, - MPI_LMP_BIGINT,MPI_SUM,world); +void Set::varparse(const char *name, int m, Action *action) +{ + int ivar = input->variable->find(name+2); + if (ivar < 0) + error->all(FLERR,"Variable name {} for set command does not exist", name); + if (!input->variable->atomstyle(ivar)) + error->all(FLERR,"Variable {} for set command is invalid style", name); + + action->varflag = 1; + + if (m == 1) { + action->varflag1 = 1; action->ivar1 = ivar; + } else if (m == 2) { + action->varflag2 = 1; action->ivar2 = ivar; + } else if (m == 3) { + action->varflag3 = 1; action->ivar3 = ivar; + } else if (m == 4) { + action->varflag4 = 1; action->ivar4 = ivar; } - if (keyword == LENGTH) { - bigint nlocal_bonus = avec_line->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->nlines,1,MPI_LMP_BIGINT,MPI_SUM,world); - } - if (keyword == TRI) { - bigint nlocal_bonus = avec_tri->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); - } - - // clear up per-atom memory if allocated - - memory->destroy(vec1); - memory->destroy(vec2); - memory->destroy(vec3); - memory->destroy(vec4); } /* ---------------------------------------------------------------------- @@ -1254,7 +608,7 @@ void Set::set(int keyword) make atom result independent of what proc owns it ------------------------------------------------------------------------- */ -void Set::setrandom(int keyword) +void Set::setrandom(int keyword, Action *action) { int i; @@ -1264,7 +618,10 @@ void Set::setrandom(int keyword) auto avec_body = dynamic_cast(atom->style_match("body")); double **x = atom->x; - int seed = ivalue; + + // seed is always set to ivalue1 in process() methods + + int seed = action->ivalue1; auto ranpark = new RanPark(lmp,1); auto ranmars = new RanMars(lmp,seed + comm->me); @@ -1273,7 +630,10 @@ void Set::setrandom(int keyword) if (keyword == TYPE_FRACTION) { int nlocal = atom->nlocal; - + double fraction = action->dvalue1; + int newtype = action->ivalue2; + int count = 0; + for (i = 0; i < nlocal; i++) if (select[i]) { ranpark->reset(seed,x[i]); @@ -1281,6 +641,8 @@ void Set::setrandom(int keyword) atom->type[i] = newtype; count++; } + + count_action = count; // set exact count of atom types to newtype // for TYPE_RATIO, exact = fraction out of total eligible @@ -1288,38 +650,37 @@ void Set::setrandom(int keyword) } else if (keyword == TYPE_RATIO || keyword == TYPE_SUBSET) { int nlocal = atom->nlocal; + int newtype = action->ivalue2; - // count = number of eligible atoms I own + // convert specified fraction to nsubset of all selected atoms - count = 0; - for (i = 0; i < nlocal; i++) - if (select[i]) count++; - - // convert specified fraction to nsubset - - bigint bcount = count; + bigint bcount = count_select; bigint allcount; MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); + bigint nsubset; if (keyword == TYPE_RATIO) { + double fraction = action->dvalue1; nsubset = static_cast (fraction * allcount); } else if (keyword == TYPE_SUBSET) { + nsubset = action->bvalue1; if (nsubset > allcount) - error->all(FLERR, Error::NOLASTLINE, "Set type/subset value exceeds eligible atoms"); + error->all(FLERR,"Set type/subset value exceeds eligible atoms"); } // make selection - int *flag = memory->create(flag,count,"set:flag"); - int *work = memory->create(work,count,"set:work"); + int *flag = memory->create(flag,count_select,"set:flag"); + int *work = memory->create(work,count_select,"set:work"); - ranmars->select_subset(nsubset,count,flag,work); + ranmars->select_subset(nsubset,count_select,flag,work); // change types of selected atoms // flag vector from select_subset() is only for eligible atoms - count = 0; + int count = 0; int eligible = 0; + for (i = 0; i < nlocal; i++) { if (!select[i]) continue; if (flag[eligible]) { @@ -1328,7 +689,9 @@ void Set::setrandom(int keyword) } eligible++; } - + + count_action = count; + // clean up memory->destroy(flag); @@ -1340,7 +703,7 @@ void Set::setrandom(int keyword) } else if (keyword == DIPOLE_RANDOM) { double **mu = atom->mu; int nlocal = atom->nlocal; - + double dmag = action->dvalue1; double msq,scale; if (domain->dimension == 3) { @@ -1351,12 +714,11 @@ void Set::setrandom(int keyword) mu[i][1] = ranpark->uniform() - 0.5; mu[i][2] = ranpark->uniform() - 0.5; msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]; - scale = dvalue/sqrt(msq); + scale = dmag/sqrt(msq); mu[i][0] *= scale; mu[i][1] *= scale; mu[i][2] *= scale; - mu[i][3] = dvalue; - count++; + mu[i][3] = dmag; } } else { @@ -1367,24 +729,22 @@ void Set::setrandom(int keyword) mu[i][1] = ranpark->uniform() - 0.5; mu[i][2] = 0.0; msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1]; - scale = dvalue/sqrt(msq); + scale = dmag/sqrt(msq); mu[i][0] *= scale; mu[i][1] *= scale; - mu[i][3] = dvalue; - count++; + mu[i][3] = dmag; } } - // set spin moments to random orientations in 3d or 2d // spin length is fixed to unity - } else if (keyword == SPIN_RANDOM) { + } else if (keyword == SPIN_ATOM_RANDOM) { double **sp = atom->sp; int nlocal = atom->nlocal; - + double dlen = action->dvalue1; double sp_sq,scale; - + if (domain->dimension == 3) { for (i = 0; i < nlocal; i++) if (select[i]) { @@ -1397,8 +757,7 @@ void Set::setrandom(int keyword) sp[i][0] *= scale; sp[i][1] *= scale; sp[i][2] *= scale; - sp[i][3] = dvalue; - count++; + sp[i][3] = dlen; } } else { @@ -1412,32 +771,35 @@ void Set::setrandom(int keyword) scale = 1.0/sqrt(sp_sq); sp[i][0] *= scale; sp[i][1] *= scale; - sp[i][3] = dvalue; - count++; + sp[i][3] = dlen; } } // set quaternions to random orientations in 3d and 2d } else if (keyword == QUAT_RANDOM) { + int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; + int *body = atom->body; + double **quat = atom->quat; int nlocal = atom->nlocal; - double *quat; - double **quat2; - + int quat_flag = atom->quat_flag; + double *quat_one; + if (domain->dimension == 3) { double s,t1,t2,theta1,theta2; for (i = 0; i < nlocal; i++) if (select[i]) { - if (avec_ellipsoid && atom->ellipsoid[i] >= 0) - quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; - else if (avec_tri && atom->tri[i] >= 0) - quat = avec_tri->bonus[atom->tri[i]].quat; - else if (avec_body && atom->body[i] >= 0) - quat = avec_body->bonus[atom->body[i]].quat; - else if (atom->quat_flag) - quat2 = atom->quat; + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_tri && tri[i] >= 0) + quat_one = avec_tri->bonus[tri[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; else - error->one(FLERR, Error::NOLASTLINE, "Cannot set quaternion for atom that has none"); + error->one(FLERR,"Cannot set quaternion for atom that has none"); ranpark->reset(seed,x[i]); s = ranpark->uniform(); @@ -1445,61 +807,46 @@ void Set::setrandom(int keyword) t2 = sqrt(s); theta1 = 2.0*MY_PI*ranpark->uniform(); theta2 = 2.0*MY_PI*ranpark->uniform(); - if (atom->quat_flag) { - quat2[i][0] = cos(theta2)*t2; - quat2[i][1] = sin(theta1)*t1; - quat2[i][2] = cos(theta1)*t1; - quat2[i][3] = sin(theta2)*t2; - } else { - quat[0] = cos(theta2)*t2; - quat[1] = sin(theta1)*t1; - quat[2] = cos(theta1)*t1; - quat[3] = sin(theta2)*t2; - } - count++; + quat_one[0] = cos(theta2)*t2; + quat_one[1] = sin(theta1)*t1; + quat_one[2] = cos(theta1)*t1; + quat_one[3] = sin(theta2)*t2; } } else { double theta2; for (i = 0; i < nlocal; i++) if (select[i]) { - if (avec_ellipsoid && atom->ellipsoid[i] >= 0) - quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; - else if (avec_body && atom->body[i] >= 0) - quat = avec_body->bonus[atom->body[i]].quat; - else if (atom->quat_flag) - quat2 = atom->quat; + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; else - error->one(FLERR, Error::NOLASTLINE, "Cannot set quaternion for atom that has none"); + error->one(FLERR,"Cannot set quaternion for atom that has none"); ranpark->reset(seed,x[i]); theta2 = MY_PI*ranpark->uniform(); - if (atom->quat_flag) { - quat2[i][0] = cos(theta2); - quat2[i][1] = 0.0; - quat2[i][2] = 0.0; - quat2[i][3] = sin(theta2); - } else { - quat[0] = cos(theta2); - quat[1] = 0.0; - quat[2] = 0.0; - quat[3] = sin(theta2); - } - count++; + quat_one[0] = cos(theta2); + quat_one[1] = 0.0; + quat_one[2] = 0.0; + quat_one[3] = sin(theta2); } } // set theta to random orientation in 2d } else if (keyword == THETA_RANDOM) { + int *line = atom->line; int nlocal = atom->nlocal; + for (i = 0; i < nlocal; i++) { if (select[i]) { - if (atom->line[i] < 0) - error->one(FLERR, Error::NOLASTLINE, "Cannot set theta for atom that is not a line"); + if (line[i] < 0) + error->one(FLERR,"Cannot set theta for atom that is not a line"); ranpark->reset(seed,x[i]); - avec_line->bonus[atom->line[i]].theta = MY_2PI*ranpark->uniform(); - count++; + avec_line->bonus[line[i]].theta = MY_2PI*ranpark->uniform(); } } } @@ -1510,14 +857,14 @@ void Set::setrandom(int keyword) /* ---------------------------------------------------------------------- */ -void Set::topology(int keyword) +void Set::topology(int keyword, Action *action) { int m,atom1,atom2,atom3,atom4; // error check if (atom->molecular == Atom::TEMPLATE) - error->all(FLERR, Error::NOLASTLINE, "Cannot set bond topology types for atom style template"); + error->all(FLERR,"Cannot set bond topology types for atom style template"); // border swap to acquire ghost atom info // enforce PBC before in case atoms are outside box @@ -1539,18 +886,23 @@ void Set::topology(int keyword) selection(atom->nlocal + atom->nghost); + int count = 0; + // for BOND, each of 2 atoms must be in group if (keyword == BOND) { + int *num_bond = atom->num_bond; + int **bond_type = atom->bond_type; + tagint **bond_atom = atom->bond_atom; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_bond[i]; m++) { - atom1 = atom->map(atom->bond_atom[i][m]); - if (atom1 == -1) - error->one(FLERR, Error::NOLASTLINE, "Bond atom missing in set command" - + utils::errorurl(5)); + for (m = 0; m < num_bond[i]; m++) { + atom1 = atom->map(bond_atom[i][m]); + if (atom1 == -1) error->one(FLERR,"Bond atom missing in set command"); if (select[i] && select[atom1]) { - atom->bond_type[i][m] = ivalue; + bond_type[i][m] = itype; count++; } } @@ -1558,18 +910,24 @@ void Set::topology(int keyword) // for ANGLE, each of 3 atoms must be in group - if (keyword == ANGLE) { + if (keyword == ANGLE) { + int *num_angle = atom->num_angle; + int **angle_type = atom->angle_type; + tagint **angle_atom1 = atom->angle_atom1; + tagint **angle_atom2 = atom->angle_atom2; + tagint **angle_atom3 = atom->angle_atom3; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_angle[i]; m++) { - atom1 = atom->map(atom->angle_atom1[i][m]); - atom2 = atom->map(atom->angle_atom2[i][m]); - atom3 = atom->map(atom->angle_atom3[i][m]); + for (m = 0; m < num_angle[i]; m++) { + atom1 = atom->map(angle_atom1[i][m]); + atom2 = atom->map(angle_atom2[i][m]); + atom3 = atom->map(angle_atom3[i][m]); if (atom1 == -1 || atom2 == -1 || atom3 == -1) - error->one(FLERR, Error::NOLASTLINE, "Angle atom missing in set command" - + utils::errorurl(5)); + error->one(FLERR,"Angle atom missing in set command"); if (select[atom1] && select[atom2] && select[atom3]) { - atom->angle_type[i][m] = ivalue; + angle_type[i][m] = itype; count++; } } @@ -1578,18 +936,25 @@ void Set::topology(int keyword) // for DIHEDRAL, each of 4 atoms must be in group if (keyword == DIHEDRAL) { + int *num_dihedral = atom->num_dihedral; + int **dihedral_type = atom->dihedral_type; + tagint **dihedral_atom1 = atom->dihedral_atom1; + tagint **dihedral_atom2 = atom->dihedral_atom2; + tagint **dihedral_atom3 = atom->dihedral_atom3; + tagint **dihedral_atom4 = atom->dihedral_atom4; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_dihedral[i]; m++) { - atom1 = atom->map(atom->dihedral_atom1[i][m]); - atom2 = atom->map(atom->dihedral_atom2[i][m]); - atom3 = atom->map(atom->dihedral_atom3[i][m]); - atom4 = atom->map(atom->dihedral_atom4[i][m]); + for (m = 0; m < num_dihedral[i]; m++) { + atom1 = atom->map(dihedral_atom1[i][m]); + atom2 = atom->map(dihedral_atom2[i][m]); + atom3 = atom->map(dihedral_atom3[i][m]); + atom4 = atom->map(dihedral_atom4[i][m]); if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) - error->one(FLERR, Error::NOLASTLINE, "Dihedral atom missing in set command" - + utils::errorurl(5)); + error->one(FLERR,"Dihedral atom missing in set command"); if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { - atom->dihedral_type[i][m] = ivalue; + dihedral_type[i][m] = itype; count++; } } @@ -1598,43 +963,1963 @@ void Set::topology(int keyword) // for IMPROPER, each of 4 atoms must be in group if (keyword == IMPROPER) { + int *num_improper = atom->num_improper; + int **improper_type = atom->improper_type; + tagint **improper_atom1 = atom->improper_atom1; + tagint **improper_atom2 = atom->improper_atom2; + tagint **improper_atom3 = atom->improper_atom3; + tagint **improper_atom4 = atom->improper_atom4; int nlocal = atom->nlocal; + + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) - for (m = 0; m < atom->num_improper[i]; m++) { - atom1 = atom->map(atom->improper_atom1[i][m]); - atom2 = atom->map(atom->improper_atom2[i][m]); - atom3 = atom->map(atom->improper_atom3[i][m]); - atom4 = atom->map(atom->improper_atom4[i][m]); + for (m = 0; m < num_improper[i]; m++) { + atom1 = atom->map(improper_atom1[i][m]); + atom2 = atom->map(improper_atom2[i][m]); + atom3 = atom->map(improper_atom3[i][m]); + atom4 = atom->map(improper_atom4[i][m]); if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) - error->one(FLERR, Error::NOLASTLINE, "Improper atom missing in set command" - + utils::errorurl(5)); + error->one(FLERR,"Improper atom missing in set command"); if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { - atom->improper_type[i][m] = ivalue; + improper_type[i][m] = itype; count++; } } } + + // set count_action for all topology actions + + count_action = count; +} + +// ---------------------------------------------------------------------- +// pairs of process/invoke methods for each keyword +// process method reads args, stores parameters in Action instance +// invoke method resets atoms properties using Action instance +// separate two operations so can be called by either set or fix set command +// ---------------------------------------------------------------------- + +void Set::process_angle(int &iarg, int narg, char **arg, Action *action) +{ + if (atom->avec->angles_allow == 0) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ANGLE,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->nangletypes) + error->all(FLERR,"Invalid angle type in set command"); + iarg += 2; +} + +void Set::invoke_angle(Action *action) +{ + topology(ANGLE,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_angmom(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->angmom_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + + iarg += 4; +} + +void Set::invoke_angmom(Action *action) +{ + int nlocal = atom->nlocal; + double **angmom = atom->angmom; + + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; + } + + angmom[i][0] = xvalue; + angmom[i][1] = yvalue; + angmom[i][2] = zvalue; + } } /* ---------------------------------------------------------------------- */ -void Set::varparse(const char *name, int m) +void Set::process_bond(int &iarg, int narg, char **arg, Action *action) { - varflag = 1; - int ivar = input->variable->find(name+2); + if (atom->avec->bonds_allow == 0) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); - if (ivar < 0) - error->all(FLERR, Error::NOLASTLINE, "Variable name {} for set command does not exist", name); - if (!input->variable->atomstyle(ivar)) - error->all(FLERR, Error::NOLASTLINE, "Variable {} for set command is invalid style", name); + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::BOND,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->nbondtypes) + error->all(FLERR,"Invalid bond type in set command"); + + iarg += 2; +} - if (m == 1) { - varflag1 = 1; ivar1 = ivar; - } else if (m == 2) { - varflag2 = 1; ivar2 = ivar; - } else if (m == 3) { - varflag3 = 1; ivar3 = ivar; - } else if (m == 4) { - varflag4 = 1; ivar4 = ivar; +void Set::invoke_bond(Action *action) +{ + topology(BOND,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_cc(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->tdpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 < 1) error->all(FLERR,"Invalid cc index in set command"); + + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid cc value in set command"); + } + + iarg += 3; +} + +void Set::invoke_cc(Action *action) +{ + int nlocal = atom->nlocal; + double **cc = atom->cc; + + int cc_index = action->ivalue1 - 1; + // NOTE: need to check if cc_index exceeds cc array allocation + + int varflag = action->varflag; + double ccvalue; + if (!action->varflag1) ccvalue = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + ccvalue = vec1[i]; + if (ccvalue < 0.0) error->all(FLERR,"Invalid cc value in set command"); + } + + cc[i][cc_index] = ccvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_charge(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->q_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_charge(Action *action) +{ + int nlocal = atom->nlocal; + double *q = atom->q; + double *q_scaled = atom->q_scaled; + double *epsilon = atom->epsilon; + + int varflag = action->varflag; + double qvalue; + if (!action->varflag1) qvalue = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) qvalue = vec1[i]; + q[i] = qvalue; + + // ensure scaled charges are consistent with new charge value + + if (epsilon) q_scaled[i] = qvalue / epsilon[i]; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_density(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->rmass_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid density in set command"); + } + + action->ivalue1 = 0; + if (strcmp(arg[iarg],"density/disc") == 0) { + action->ivalue1 = 1; + if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); + } + + iarg += 2; +} + +void Set::invoke_density(Action *action) +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + double *radius = atom->radius; + int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; + + int radius_flag = atom->radius_flag; + int ellipsoid_flag = atom->ellipsoid_flag; + int line_flag = atom->line_flag; + int tri_flag = atom->tri_flag; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_line = dynamic_cast(atom->style_match("line")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + + int varflag = action->varflag; + double density; + if (!action->varflag1) density = action->dvalue1; + int discflag = action->ivalue1; + + // set rmass via density + // if radius > 0.0, treat as sphere or disc + // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) + // if length > 0.0, treat as line + // if area > 0.0, treat as tri + // else set rmass to density directly + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + density = vec1[i]; + if (density <= 0.0) error->one(FLERR,"Invalid density in set command"); + } + + if (radius_flag && radius[i] > 0.0) + if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * density; + else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * density; + + else if (ellipsoid_flag && ellipsoid[i] >= 0) { + double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; + // could enable 2d ellipse (versus 3d ellipsoid) when time integration + // options (fix nve/asphere, fix nh/asphere) are also implemented + // if (discflag) + // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; + // else + rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * density; + + } else if (line_flag && line[i] >= 0) { + double length = avec_line->bonus[line[i]].length; + rmass[i] = length * density; + + } else if (tri_flag && tri[i] >= 0) { + double *c1 = avec_tri->bonus[tri[i]].c1; + double *c2 = avec_tri->bonus[tri[i]].c2; + double *c3 = avec_tri->bonus[tri[i]].c3; + double c2mc1[3],c3mc1[3]; + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c1,c3mc1); + double norm[3]; + MathExtra::cross3(c2mc1,c3mc1,norm); + double area = 0.5 * MathExtra::len3(norm); + rmass[i] = area * density; + + } else rmass[i] = density; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_diameter(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->radius_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid diameter in set command"); + } + + iarg += 2; +} + +void Set::invoke_diameter(Action *action) +{ + int nlocal = atom->nlocal; + double *radius = atom->radius; + + int varflag = action->varflag; + double diam; + if (!action->varflag1) diam = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + diam = vec1[i]; + if (diam < 0.0) error->one(FLERR,"Invalid diameter in set command"); + } + + radius[i] = 0.5 * diam; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_dihedral(int &iarg, int narg, char **arg, Action *action) +{ + if (atom->avec->dihedrals_allow == 0) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::DIHEDRAL,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->ndihedraltypes) + error->all(FLERR,"Invalid dihedral type in set command"); + + iarg += 2; +} + +void Set::invoke_dihedral(Action *action) +{ + topology(DIHEDRAL,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_dipole(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->mu_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + + iarg += 4; +} + +void Set::invoke_dipole(Action *action) +{ + int nlocal = atom->nlocal; + double **mu = atom->mu; + + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; + } + + mu[i][0] = xvalue; + mu[i][1] = yvalue; + mu[i][2] = zvalue; + mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_dipole_random(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->mu_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + if (action->dvalue1 <= 0.0) + error->all(FLERR,"Invalid dipole length in set command"); + + iarg += 3; +} + +void Set::invoke_dipole_random(Action *action) +{ + setrandom(DIPOLE_RANDOM,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_dpd_theta(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->dpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); + + if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; + else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid dpd/theta value in set command"); + } + + iarg += 2; +} + +void Set::invoke_dpd_theta(Action *action) +{ + int nlocal = atom->nlocal; + int *type = atom->type; + double **v = atom->v; + double *mass = atom->mass; + double *rmass = atom->rmass; + double *dpdTheta = atom->dpdTheta; + + double tfactor = force->mvv2e / (domain->dimension * force->boltz); + double onemass; + double vx,vy,vz; + + int varflag = action->varflag; + double theta; + if (!action->varflag1) theta = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + theta = vec1[i]; + if (theta < 0.0) error->one(FLERR,"Invalid dpd/theta value in set command"); + } + + // if theta is negative, NULL was used, set dpdTheta to KE of particle + + if (theta >= 0.0) dpdTheta[i] = theta; + else { + if (rmass) onemass = rmass[i]; + else onemass = mass[type[i]]; + vx = v[i][0]; + vy = v[i][1]; + vz = v[i][2]; + dpdTheta[i] = tfactor * onemass * (vx*vx + vy*vy + vz*vz); + } + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_edpd_cv(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/cv value in set command"); + } + + iarg += 2; +} + +void Set::invoke_edpd_cv(Action *action) +{ + int nlocal = atom->nlocal; + double *edpd_cv = atom->edpd_cv; + + int varflag = action->varflag; + double cv; + if (!action->varflag1) cv = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + cv = vec1[i]; + if (cv < 0.0) error->one(FLERR,"Invalid edpd/cv value in set command"); + } + + edpd_cv[i] = cv; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_edpd_temp(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->edpd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/temp value in set command"); + } + iarg += 2; +} + +void Set::invoke_edpd_temp(Action *action) +{ + int nlocal = atom->nlocal; + double *edpd_temp = atom->edpd_temp; + + int varflag = action->varflag; + double temp; + if (!action->varflag1) temp = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + temp = vec1[i]; + if (temp < 0.0) error->one(FLERR,"Invalid edpd/temp value in set command"); + } + + edpd_temp[i] = temp; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_epsilon(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->dielectric_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid epsilon in set command"); + } + + iarg += 2; +} + +void Set::invoke_epsilon(Action *action) +{ + int nlocal = atom->nlocal; + double *epsilon = atom->epsilon; + double *q = atom->q; + double *q_scaled = atom->q_scaled; + + int varflag = action->varflag; + double eps; + if (!action->varflag1) eps = action->dvalue1; + + // assign local dielectric constant + // also update scaled charge value + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + eps = vec1[i]; + if (eps <= 0.0) error->one(FLERR,"Invalid epsilon in set command"); + } + + epsilon[i] = eps; + q_scaled[i] = q[i] / eps; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_image(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); + + if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue4 = 0; + else { + action->ivalue4 = 1; + if (utils::strmatch(arg[iarg+1],"^v_")) { + if (!domain->xperiodic) + error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); + varparse(arg[iarg+1],1,action); + } else { + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 && !domain->xperiodic) + error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); + } + } + + if (strcmp(arg[iarg+2],"NULL") == 0) action->ivalue5 = 0; + else { + action->ivalue5 = 1; + if (utils::strmatch(arg[iarg+2],"^v_")) { + if (!domain->yperiodic) + error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); + varparse(arg[iarg+2],2,action); + } else { + action->ivalue2 = utils::inumeric(FLERR,arg[iarg+2],false,lmp); + if (action->ivalue2 && !domain->yperiodic) + error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); + } + } + + if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue6 = 0; + else { + action->ivalue6 = 1; + if (utils::strmatch(arg[iarg+3],"^v_")) { + if (!domain->zperiodic) + error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); + varparse(arg[iarg+3],3,action); + } else { + action->ivalue3 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue3 && !domain->zperiodic) + error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); + } + } + + iarg += 4; +} + +void Set::invoke_image(Action *action) +{ + int nlocal = atom->nlocal; + imageint *image = atom->image; + int xbox,ybox,zbox; + + int ximageflag = action->ivalue4; + int yimageflag = action->ivalue5; + int zimageflag = action->ivalue6; + + int varflag = action->varflag; + int ximage,yimage,zimage; + if (!action->varflag1) ximage = action->ivalue1; + if (!action->varflag2) yimage = action->ivalue2; + if (!action->varflag3) zimage = action->ivalue3; + + // reset any or all of 3 image flags + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) ximage = static_cast (vec1[i]); + if (action->varflag2) yimage = static_cast (vec2[i]); + if (action->varflag3) zimage = static_cast (vec3[i]); + } + + xbox = (image[i] & IMGMASK) - IMGMAX; + ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; + zbox = (image[i] >> IMG2BITS) - IMGMAX; + if (ximageflag) xbox = ximage; + if (yimageflag) ybox = yimage; + if (zimageflag) zbox = zimage; + image[i] = ((imageint) (xbox + IMGMAX) & IMGMASK) | + (((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) | + (((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_improper(int &iarg, int narg, char **arg, Action *action) +{ + if (atom->avec->impropers_allow == 0) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::IMPROPER,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->nimpropertypes) + error->all(FLERR,"Invalid value in set command"); + + iarg += 2; +} + +void Set::invoke_improper(Action *action) +{ + topology(IMPROPER,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_length(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid length in set command"); + } + + iarg += 2; +} + +void Set::invoke_length(Action *action) +{ + int nlocal = atom->nlocal; + auto avec_line = dynamic_cast(atom->style_match("line")); + + int varflag = action->varflag; + double length; + if (!action->varflag1) length = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + length = vec1[i]; + if (length < 0.0) error->one(FLERR,"Invalid length in set command"); + } + + avec_line->set_length(i,length); + } + + // update global line count + + bigint nlocal_bonus = avec_line->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->nlines,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_mass(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->rmass_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid mass in set command"); + } + + iarg += 2; +} + +void Set::invoke_mass(Action *action) +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + + int varflag = action->varflag; + double mass_one; + if (!action->varflag1) mass_one = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + mass_one = vec1[i]; + if (mass_one < 0.0) error->one(FLERR,"Invalid mass in set command"); + } + + rmass[i] = mass_one; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_mol(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->molecule_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->tvalue1 = utils::tnumeric(FLERR,arg[iarg+1],false,lmp); + if (action->tvalue1 < 0) error->one(FLERR,"Invalid molecule ID in set command"); + } + + iarg += 2; +} + +void Set::invoke_mol(Action *action) +{ + int nlocal = atom->nlocal; + int *molecule = atom->molecule; + + int varflag = action->varflag; + tagint molID; + if (!action->varflag1) molID = action->tvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + molID = vec1[i]; + if (molID < 0) error->one(FLERR,"Invalid molecule ID in set command"); + } + + molecule[i] = molID; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_omega(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->omega_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + + iarg += 4; +} + +void Set::invoke_omega(Action *action) +{ + int nlocal = atom->nlocal; + double **omega = atom->angmom; + + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag2) yvalue = vec2[i]; + if (action->varflag3) zvalue = vec3[i]; + } + + omega[i][0] = xvalue; + omega[i][1] = yvalue; + omega[i][2] = zvalue; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_quat(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); + int dimension = domain->dimension; + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (dimension == 2 && action->dvalue1 != 0.0) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + } + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); + else { + action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (dimension == 2 && action->dvalue2 != 0.0) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + } + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4,action); + else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); + + iarg += 5; +} + +void Set::invoke_quat(Action *action) +{ + int nlocal = atom->nlocal; + int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; + int *body = atom->body; + double **quat = atom->quat; + int quat_flag = atom->quat_flag; + + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + auto avec_tri = dynamic_cast(atom->style_match("tri")); + auto avec_body = dynamic_cast(atom->style_match("body")); + + int dimension = domain->dimension; + double radians,sintheta; + double *quat_one; + + int varflag = action->varflag; + double xvalue,yvalue,zvalue,theta; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + if (!action->varflag4) theta = action->dvalue4; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (avec_ellipsoid && ellipsoid[i] >= 0) + quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; + else if (avec_tri && tri[i] >= 0) + quat_one = avec_tri->bonus[tri[i]].quat; + else if (avec_body && body[i] >= 0) + quat_one = avec_body->bonus[body[i]].quat; + else if (quat_flag) + quat_one = quat[i]; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag2) yvalue = vec2[i]; + if (action->varflag3) zvalue = vec3[i]; + if (action->varflag4) theta = vec4[i]; + if (dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) + error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); + } + + radians = MY_PI2 * theta/180.0; + sintheta = sin(radians); + quat_one[0] = cos(radians); + quat_one[1] = xvalue * sintheta; + quat_one[2] = yvalue * sintheta; + quat_one[3] = zvalue * sintheta; + MathExtra::qnormalize(quat_one); + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_quat_random(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); + + iarg += 2; +} + +void Set::invoke_quat_random(Action *action) +{ + setrandom(QUAT_RANDOM,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_radius_election(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->eradius_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid electron radius in set command"); + } + + iarg += 2; +} + +void Set::invoke_radius_election(Action *action) +{ + int nlocal = atom->nlocal; + double *eradius = atom->eradius; + + int varflag = action->varflag; + double radius; + if (!action->varflag1) radius = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + radius = vec1[i]; + if (radius < 0.0) error->one(FLERR,"Invalid electron radius in set command"); + } + + eradius[i] = radius; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_shape(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->ellipsoid_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid shape in set command"); + } + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); + else { + action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue2 < 0.0) error->one(FLERR,"Invalid shape in set command"); + } + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); + else { + action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (action->dvalue3 < 0.0) error->one(FLERR,"Invalid shape in set command"); + } + + iarg += 4; +} + +void Set::invoke_shape(Action *action) +{ + int nlocal = atom->nlocal; + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); + + int varflag = action->varflag; + double xvalue,yvalue,zvalue; + if (!action->varflag1) xvalue = action->dvalue1; + if (!action->varflag2) yvalue = action->dvalue2; + if (!action->varflag3) zvalue = action->dvalue3; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) xvalue = vec1[i]; + if (action->varflag1) yvalue = vec2[i]; + if (action->varflag1) zvalue = vec3[i]; + if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) + error->one(FLERR,"Invalid shape in set command"); + } + + if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) + if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) + error->one(FLERR,"Invalid shape in set command"); + + avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); + } + + // update global ellipsoid count + + bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->nellipsoids,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_smd_contact_radius(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->smd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid smd/contact/radius in set command"); + } + + iarg += 2; +} + +void Set::invoke_smd_contact_radius(Action *action) +{ + int nlocal = atom->nlocal; + double *contact_radius = atom->contact_radius; + + int varflag = action->varflag; + double radius; + if (!action->varflag1) radius = action->dvalue1; + + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + radius = vec1[i]; + if (radius < 0.0) error->one(FLERR,"Invalid smd/contact/radius in set command"); + } + + contact_radius[i] = radius; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_smd_mass_density(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->smd_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); + } + + iarg += 2; +} + +void Set::invoke_smd_mass_density(Action *action) +{ + int nlocal = atom->nlocal; + double *rmass = atom->rmass; + double *vfrac = atom->vfrac; + + int varflag = action->varflag; + double density; + if (!action->varflag1) density = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + density = vec1[i]; + if (density < 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); + } + + rmass[i] = vfrac[i] * density; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_sph_cv(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->cv_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_sph_cv(Action *action) +{ + int nlocal = atom->nlocal; + double *cv = atom->cv; + + int varflag = action->varflag; + double sph_cv; + if (!action->varflag1) sph_cv = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) sph_cv = vec1[i]; + cv[i] = sph_cv; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_sph_e(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->esph_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_sph_e(Action *action) +{ + int nlocal = atom->nlocal; + double *esph = atom->esph; + + int varflag = action->varflag; + double sph_e; + if (!action->varflag1) sph_e = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) sph_e = vec1[i]; + esph[i] = sph_e; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_sph_rho(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->rho_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_sph_rho(Action *action) +{ + int nlocal = atom->nlocal; + double *rho = atom->rho; + + int varflag = action->varflag; + double sph_rho; + if (!action->varflag1) sph_rho = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) sph_rho = vec1[i]; + rho[i] = sph_rho; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_spin_atom(int &iarg, int narg, char **arg, Action *action) +{ + if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin is deprecated -- use spin/atom instead"); + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); + } + + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); + else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); + else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); + if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4,action); + else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); + + iarg += 5; +} + +void Set::invoke_spin_atom(Action *action) +{ + int nlocal = atom->nlocal; + double **sp = atom->sp; + double norm; + + int varflag = action->varflag; + double magnitude,xvalue,yvalue,zvalue; + if (!action->varflag1) magnitude = action->dvalue1; + if (!action->varflag2) xvalue = action->dvalue2; + if (!action->varflag3) yvalue = action->dvalue3; + if (!action->varflag4) zvalue = action->dvalue4; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + if (action->varflag1) magnitude = vec1[i]; + if (magnitude < 0.0) + error->one(FLERR,"Invalid spin magnitude in set command"); + if (action->varflag2) xvalue = vec2[i]; + if (action->varflag3) yvalue = vec3[i]; + if (action->varflag4) zvalue = vec4[i]; + } + + if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) + error->all(FLERR,"At least one spin vector component must be non-zero"); + + norm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); + sp[i][0] = norm*xvalue; + sp[i][1] = norm*yvalue; + sp[i][2] = norm*zvalue; + sp[i][3] = magnitude; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_spin_atom_random(int &iarg, int narg, char **arg, Action *action) +{ + if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) + error->warning(FLERR, "Set attribute spin/random is deprecated -- use spin/atom/random instead"); + if (!atom->sp_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); + + iarg += 3; +} + +void Set::invoke_spin_atom_random(Action *action) +{ + setrandom(SPIN_ATOM_RANDOM,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_spin_electron(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->spin_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 < -1 || action->ivalue1 > 3) + error->one(FLERR,"Invalid electron spin in set command"); + } + + iarg += 2; +} + +void Set::invoke_spin_electron(Action *action) +{ + int nlocal = atom->nlocal; + int *spin = atom->spin; + + int varflag = action->varflag; + int ispin; + if (!action->varflag1) ispin = action->ivalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + ispin = static_cast (vec1[i]); + if (ispin < -1 || ispin > 3) + error->one(FLERR,"Invalid electron spin in set command"); + } + + atom->spin[i] = ispin; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_temperature(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->temperature_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid temperature in set command"); + } + + iarg += 2; +} + +void Set::invoke_temperature(Action *action) +{ + int nlocal = atom->nlocal; + double *temperature = atom->temperature; + + int varflag = action->varflag; + double temp; + if (!action->varflag1) temp = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + temp = vec1[i]; + if (temp < 0.0) error->one(FLERR,"Invalid temperature in set command"); + } + + temperature[i] = temp; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_theta(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_theta(Action *action) +{ + int nlocal = atom->nlocal; + int *line = atom->line; + + auto avec_line = dynamic_cast(atom->style_match("line")); + + int varflag = action->varflag; + double theta; + if (!action->varflag1) theta = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (line[i] < 0) error->one(FLERR,"Cannot set theta for atom which is not a line"); + if (varflag) theta = vec1[i]; + avec_line->bonus[atom->line[i]].theta = theta; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_theta_random(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->line_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); + + iarg += 2; +} + +void Set::invoke_theta_random(Action *action) +{ + setrandom(THETA_RANDOM,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_tri(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->tri_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid tri size in set command"); + } + + iarg += 2; +} + +void Set::invoke_tri(Action *action) +{ + int nlocal = atom->nlocal; + int *tri = atom->tri; + + auto avec_tri = dynamic_cast(atom->style_match("tri")); + + int varflag = action->varflag; + double trisize; + if (!action->varflag1) trisize = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (tri[i] < 0) error->one(FLERR,"Cannot set tri for atom which is not a triangle"); + + if (varflag) { + trisize = vec1[i]; + if (trisize < 0.0) error->one(FLERR,"Invalid tri size in set command"); + } + + avec_tri->set_equilateral(i,trisize); + } + + // update bonus tri count + + bigint nlocal_bonus = avec_tri->nlocal_bonus; + MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_type(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set type", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); + action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue1 <= 0 || action->ivalue1 > atom->ntypes) + error->one(FLERR,"Invalid atom type in set command"); + } + + iarg += 2; +} + +void Set::invoke_type(Action *action) +{ + int nlocal = atom->nlocal; + int *type = atom->type; + + int varflag = action->varflag; + int itype; + if (!action->varflag1) itype = action->ivalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (action->varflag) { + itype = static_cast (vec1[i]); + if (itype <= 0 || itype > atom->ntypes) + error->one(FLERR,"Invalid atom type in set command"); + } + + type[i] = itype; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_type_fraction(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); + + // random seed must be ivalue1 for use in setrandom() + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); + action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) + error->one(FLERR,"Invalid atom type in set command"); + + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) + error->all(FLERR,"Invalid fraction in set command"); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + + iarg += 4; +} + +void Set::invoke_type_fraction(Action *action) +{ + setrandom(TYPE_FRACTION,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_type_ratio(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error); + + // random seed must be ivalue1 for use in setrandom() + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); + action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) + error->all(FLERR,"Invalid atom type in set command"); + + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); + if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) + error->all(FLERR,"Invalid fraction in set command"); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + + iarg += 4; +} + +void Set::invoke_type_ratio(Action *action) +{ + setrandom(TYPE_RATIO,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_type_subset(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error); + + // random seed must be ivalue1 for use in setrandom() + + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); + action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); + delete[] typestr; + if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) + error->all(FLERR,"Invalid atom type in set command"); + + action->bvalue1 = utils::bnumeric(FLERR,arg[iarg+2],false,lmp); + if (action->bvalue1 < 0) + error->all(FLERR,"Invalid subset size in set command"); + + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); + if (action->ivalue1 <= 0) + error->all(FLERR,"Invalid random number seed in set command"); + + iarg += 4; +} + +void Set::invoke_type_subset(Action *action) +{ + setrandom(TYPE_SUBSET,action); +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_volume(int &iarg, int narg, char **arg, Action *action) +{ + if (!atom->vfrac_flag) + error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else { + action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid volume in set command"); + } + + iarg += 2; +} + +void Set::invoke_volume(Action *action) +{ + int nlocal = atom->nlocal; + double *vfrac = atom->vfrac; + + int varflag = action->varflag; + double vol; + if (!action->varflag1) vol = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + + if (varflag) { + vol = vec1[i]; + if (vol < 0.0) error->one(FLERR,"Invalid volume in set command"); + } + + vfrac[i] = vol; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_vx(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vx", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_vx(Action *action) +{ + int nlocal = atom->nlocal; + double **v = atom->v; + + int varflag = action->varflag; + double vx; + if (!action->varflag1) vx = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) vx = vec1[i]; + v[i][0] = vx; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_vy(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vy", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_vy(Action *action) +{ + int nlocal = atom->nlocal; + double **v = atom->v; + + int varflag = action->varflag; + double vy; + if (!action->varflag1) vy = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) vy = vec1[i]; + v[i][1] = vy; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_vz(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vz", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_vz(Action *action) +{ + int nlocal = atom->nlocal; + double **v = atom->v; + + int varflag = action->varflag; + double vz; + if (!action->varflag1) vz = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) vz = vec1[i]; + v[i][2] = vz; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_x(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_x(Action *action) +{ + int nlocal = atom->nlocal; + double **x = atom->x; + + int varflag = action->varflag; + double coord; + if (!action->varflag1) coord = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) coord = vec1[i]; + x[i][0] = coord; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_y(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_y(Action *action) +{ + int nlocal = atom->nlocal; + double **x = atom->x; + + int varflag = action->varflag; + double coord; + if (!action->varflag1) coord = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) coord = vec1[i]; + x[i][1] = coord; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_z(int &iarg, int narg, char **arg, Action *action) +{ + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); + + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + iarg += 2; +} + +void Set::invoke_z(Action *action) +{ + int nlocal = atom->nlocal; + double **x = atom->x; + + int varflag = action->varflag; + double coord; + if (!action->varflag1) coord = action->dvalue1; + + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) coord = vec1[i]; + x[i][2] = coord; + } +} + +/* ---------------------------------------------------------------------- */ + +void Set::process_custom(int &iarg, int narg, char **arg, Action *action) +{ + int flag,cols; + ArgInfo argi(arg[iarg],ArgInfo::DNAME|ArgInfo::INAME); + const char *pname = argi.get_name(); + + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set", error); + int index_custom = atom->find_custom(argi.get_name(),flag,cols); + if (index_custom < 0) + error->all(FLERR,"Set keyword or custom property {} does not exist",pname); + action->ivalue2 = index_custom; + + switch (argi.get_type()) { + + case ArgInfo::INAME: + if (flag != 0) error->all(FLERR,"Set command custom property {} is not integer",pname); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); + + if (argi.get_dim() == 0) { + if (cols > 0) + error->all(FLERR,"Set command custom integer property {} is not a vector",pname); + action->keyword = IVEC; + } else if (argi.get_dim() == 1) { + if (cols == 0) + error->all(FLERR,"Set command custom integer property {} is not an array",pname); + int icol_custom = argi.get_index1(); + if (icol_custom <= 0 || icol_custom > cols) + error->all(FLERR,"Set command per-atom custom integer array {} is accessed " + "out-of-range",pname); + action->ivalue3 = icol_custom; + action->keyword = IARRAY; + } else error->all(FLERR,"Illegal set command"); + break; + + case ArgInfo::DNAME: + if (flag != 1) error->all(FLERR,"Custom property {} is not floating-point",argi.get_name()); + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); + + if (argi.get_dim() == 0) { + if (cols > 0) + error->all(FLERR,"Set command custom double property {} is not a vector",pname); + action->keyword = DVEC; + } else if (argi.get_dim() == 1) { + if (cols == 0) + error->all(FLERR,"Set command custom double property {} is not an array",pname); + int icol_custom = argi.get_index1(); + if (icol_custom <= 0 || icol_custom > cols) + error->all(FLERR,"Set command per-atom custom double array {} is " + "accessed out-of-range",pname); + action->ivalue3 = icol_custom; + action->keyword = DARRAY; + } else error->all(FLERR,"Illegal set command"); + break; + + default: + error->all(FLERR,"Illegal set command"); + break; + } + + iarg += 2; +} + +void Set::invoke_custom(Action *action) +{ + int nlocal = atom->nlocal; + int ivalue; + double dvalue; + + int varflag = action->varflag; + int index_custom = action->ivalue2; + + if (action->keyword == IVEC) { + if (!varflag) ivalue = action->ivalue1; + int *ivector = atom->ivector[index_custom]; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) ivalue = static_cast (vec1[i]); + ivector[i] = ivalue; + } + + } else if (action->keyword == DVEC) { + if (!varflag) dvalue = action->dvalue1; + double *dvector = atom->dvector[index_custom]; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) dvalue = vec1[i]; + dvector[i] = dvalue; + } + + } else if (action->keyword == IARRAY) { + if (!varflag) ivalue = action->ivalue1; + int **iarray = atom->iarray[index_custom]; + int icol_custom = action->ivalue3 - 1; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) ivalue = static_cast (vec1[i]); + iarray[i][icol_custom] = ivalue; + } + + } else if (action->keyword == DARRAY) { + if (!varflag) dvalue = action->dvalue1; + double **darray = atom->darray[index_custom]; + int icol_custom = action->ivalue3 - 1; + for (int i = 0; i < nlocal; i++) { + if (!select[i]) continue; + if (varflag) dvalue = vec1[i]; + darray[i][icol_custom] = dvalue; + } } } diff --git a/src/set.h b/src/set.h index e2be5d5c1e..67f0b83fd8 100644 --- a/src/set.h +++ b/src/set.h @@ -26,32 +26,172 @@ namespace LAMMPS_NS { class Set : public Command { public: - Set(class LAMMPS *lmp) : Command(lmp) {}; + Set(class LAMMPS *lmp); + ~Set(); + void command(int, char **) override; - private: - char *id; - int *select; - int style, ivalue, newtype, count, index_custom, icol_custom; - int ximage, yimage, zimage, ximageflag, yimageflag, zimageflag; - int cc_index; - bigint nsubset; - double dvalue, xvalue, yvalue, zvalue, wvalue, fraction; - - int varflag, varflag1, varflag2, varflag3, varflag4; - int ivar1, ivar2, ivar3, ivar4; - double *vec1, *vec2, *vec3, *vec4; - - int discflag; - + void process_args(int, int, char **); void selection(int); - void set(int); - void setrandom(int); - void topology(int); - void varparse(const char *, int); + void invoke_actions(); + + private: + int caller; // SETCOMMAND or FIXSET + + // params for atom selection + + int style; + char *id; + int nlo,nhi; + bigint nlobig,nhibig; + int groupbit; + class Region *region; + + // one Action = one keyword/value pair + + struct Action { + int keyword; + int argindex; + int count_select,count_action; + int varflag; + int varflag1, varflag2, varflag3, varflag4; + int ivar1, ivar2, ivar3, ivar4; + int ivalue1, ivalue2, ivalue3, ivalue4, ivalue5, ivalue6; + tagint tvalue1; + bigint bvalue1; + double dvalue1,dvalue2,dvalue3,dvalue4; + }; + + int naction,maxaction; + Action *actions; + + typedef void (Set::*FnPtrPack)(Action *); + FnPtrPack *invoke_choice; // list of ptrs to invoke functions + + double *vec1, *vec2, *vec3, *vec4; // storage for evaluated peratom variables + int varflag; // 1 if any action uses a per-atom variable + int varflag1,varflag2,varflag3,varflag4; // 1 if any action uses this variable + int maxvariable; // size of peratom variable vectors + + int *select; // flag for selected atoms + int maxselect; // size of select vector + + int count_select; // count of selected atoms on this proc + int count_action; // count of actions on this proc, only if different than selected + + // private functions + + void varparse(const char *, int, Action *); + void setrandom(int, Action *); + void topology(int, Action *); + + // customize by adding a process method + + void process_angle(int &, int, char **, Action *); + void process_angmom(int &, int, char **, Action *); + void process_bond(int &, int, char **, Action *); + void process_cc(int &, int, char **, Action *); + void process_charge(int &, int, char **, Action *); + void process_density(int &, int, char **, Action *); + void process_diameter(int &, int, char **, Action *); + void process_dihedral(int &, int, char **, Action *); + void process_dipole(int &, int, char **, Action *); + void process_dipole_random(int &, int, char **, Action *); + void process_dpd_theta(int &, int, char **, Action *); + void process_edpd_cv(int &, int, char **, Action *); + void process_edpd_temp(int &, int, char **, Action *); + void process_epsilon(int &, int, char **, Action *); + void process_image(int &, int, char **, Action *); + void process_improper(int &, int, char **, Action *); + void process_length(int &, int, char **, Action *); + void process_mass(int &, int, char **, Action *); + void process_mol(int &, int, char **, Action *); + void process_omega(int &, int, char **, Action *); + void process_quat(int &, int, char **, Action *); + void process_quat_random(int &, int, char **, Action *); + void process_radius_election(int &, int, char **, Action *); + void process_shape(int &, int, char **, Action *); + void process_smd_contact_radius(int &, int, char **, Action *); + void process_smd_mass_density(int &, int, char **, Action *); + void process_sph_cv(int &, int, char **, Action *); + void process_sph_e(int &, int, char **, Action *); + void process_sph_rho(int &, int, char **, Action *); + void process_spin_atom(int &, int, char **, Action *); + void process_spin_atom_random(int &, int, char **, Action *); + void process_spin_electron(int &, int, char **, Action *); + void process_temperature(int &, int, char **, Action *); + void process_theta(int &, int, char **, Action *); + void process_theta_random(int &, int, char **, Action *); + void process_tri(int &, int, char **, Action *); + void process_type(int &, int, char **, Action *); + void process_type_fraction(int &, int, char **, Action *); + void process_type_ratio(int &, int, char **, Action *); + void process_type_subset(int &, int, char **, Action *); + void process_volume(int &, int, char **, Action *); + void process_vx(int &, int, char **, Action *); + void process_vy(int &, int, char **, Action *); + void process_vz(int &, int, char **, Action *); + void process_x(int &, int, char **, Action *); + void process_y(int &, int, char **, Action *); + void process_z(int &, int, char **, Action *); + + void process_custom(int &, int, char **, Action *); + + // customize by adding an invoke method + + void invoke_angle(Action *); + void invoke_angmom(Action *); + void invoke_bond(Action *); + void invoke_cc(Action *); + void invoke_charge(Action *); + void invoke_density(Action *); + void invoke_diameter(Action *); + void invoke_dihedral(Action *); + void invoke_dipole(Action *); + void invoke_dipole_random(Action *); + void invoke_dpd_theta(Action *); + void invoke_edpd_cv(Action *); + void invoke_edpd_temp(Action *); + void invoke_epsilon(Action *); + void invoke_image(Action *); + void invoke_improper(Action *); + void invoke_length(Action *); + void invoke_mass(Action *); + void invoke_mol(Action *); + void invoke_omega(Action *); + void invoke_quat(Action *); + void invoke_quat_random(Action *); + void invoke_radius_election(Action *); + void invoke_shape(Action *); + void invoke_smd_contact_radius(Action *); + void invoke_smd_mass_density(Action *); + void invoke_sph_cv(Action *); + void invoke_sph_e(Action *); + void invoke_sph_rho(Action *); + void invoke_spin_atom(Action *); + void invoke_spin_atom_random(Action *); + void invoke_spin_electron(Action *); + void invoke_temperature(Action *); + void invoke_theta(Action *); + void invoke_theta_random(Action *); + void invoke_tri(Action *); + void invoke_type(Action *); + void invoke_type_fraction(Action *); + void invoke_type_ratio(Action *); + void invoke_type_subset(Action *); + void invoke_volume(Action *); + void invoke_vx(Action *); + void invoke_vy(Action *); + void invoke_vz(Action *); + void invoke_x(Action *); + void invoke_y(Action *); + void invoke_z(Action *); + + void invoke_custom(Action *); }; } // namespace LAMMPS_NS #endif #endif + diff --git a/src/set2.cpp b/src/set2.cpp deleted file mode 100644 index 5c9548498c..0000000000 --- a/src/set2.cpp +++ /dev/null @@ -1,2871 +0,0 @@ -// clang-format off -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - https://www.lammps.org/, Sandia National Laboratories - LAMMPS development team: developers@lammps.org - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#include "set2.h" - -#include "arg_info.h" -#include "atom.h" -#include "atom_vec.h" -#include "atom_vec_body.h" -#include "atom_vec_ellipsoid.h" -#include "atom_vec_line.h" -#include "atom_vec_tri.h" -#include "comm.h" -#include "domain.h" -#include "error.h" -#include "force.h" -#include "group.h" -#include "input.h" -#include "math_const.h" -#include "math_extra.h" -#include "memory.h" -#include "modify.h" -#include "random_mars.h" -#include "random_park.h" -#include "region.h" -#include "variable.h" - -#include -#include - -using namespace LAMMPS_NS; -using namespace MathConst; - -enum{SETCOMMAND,FIXSET}; - -enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; - -enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, - DIPOLE_RANDOM,DPD_THETA,EDPD_CV,EDPD_TEMP,EPSILON,IMAGE,IMPROPER,LENGTH, - MASS,MOLECULE,OMEGA,QUAT,QUAT_RANDOM,RADIUS_ELECTRON,SHAPE, - SMD_CONTACT_RADIUS,SMD_MASS_DENSITY,SPH_CV,SPH_E,SPH_RHO, - SPIN_ATOM,SPIN_ATOM_RANDOM,SPIN_ELECTRON,TEMPERATURE,THETA,THETA_RANDOM, - TRI,TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET,VOLUME,VX,VY,VZ,X,Y,Z, - IVEC,DVEC,IARRAY,DARRAY}; - -#define BIG INT_MAX -#define DELTA 4 - -/* ---------------------------------------------------------------------- */ - -Set2::Set2(class LAMMPS *lmp) : Command(lmp) -{ - select = nullptr; -} - -/* ---------------------------------------------------------------------- */ - -Set2::~Set2() -{ - memory->destroy(select); - - // DELELTE Actions - - memory->destroy(vec1); - memory->destroy(vec2); - memory->destroy(vec3); - memory->destroy(vec4); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::command(int narg, char **arg) -{ - if (domain->box_exist == 0) - error->all(FLERR,"Set command before simulation box is defined"); - if (atom->natoms == 0) - error->all(FLERR,"Set command on system without atoms"); - - int iarg = process_args(SETCOMMAND,narg-3,&arg[3]); - if (iarg + 3 != narg) error->all(FLERR,"Illegal set command keyword"); - - if (comm->me == 0) utils::logmesg(lmp,"Setting atom values ...\n"); - - selection(atom->nlocal); - - // loop over list of actions to reset attributes - - invoke_actions(); - - // print stats for each action - // for CC option, include species index - - bigint bcount,allcount; - - for (int i = 0; i < naction; i++) { - Action *action = &actions[i]; - int iarg = action->argindex; - - if (action->count_action < 0) bcount = action->count_select; - else bcount = action->count_action; - MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); - - if (comm->me == 0) { - if (strcmp(arg[iarg],"cc") == 0) - utils::logmesg(lmp," {} settings made for {} index {}\n", - allcount,arg[iarg],arg[iarg+1]); - else - utils::logmesg(lmp," {} settings made for {}\n", - allcount,arg[iarg]); - } - } -} - -/* ---------------------------------------------------------------------- - set an owned atom property randomly - set seed based on atom coordinates - make atom result independent of what proc owns it - return iarg = index of next arg to process (could be none left) -------------------------------------------------------------------------- */ - -int Set2::process_args(int caller_flag, int narg, char **arg) -{ - caller = caller_flag; - - if (narg < 3) error->all(FLERR,"Illegal set command"); - - // style and ID info - - id = utils::strdup(arg[1]); - - if (strcmp(arg[0],"atom") == 0) { - style = ATOM_SELECT; - if (atom->tag_enable == 0) - error->all(FLERR,"Cannot use set atom with no atom IDs defined"); - utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); - - } else if (strcmp(arg[0],"mol") == 0) { - style = MOL_SELECT; - if (atom->molecule_flag == 0) - error->all(FLERR,"Cannot use set mol with no molecule IDs defined"); - utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); - - } else if (strcmp(arg[0],"type") == 0) { - 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); - - } else if (strcmp(arg[0],"group") == 0) { - style = GROUP_SELECT; - int igroup = group->find(id); - if (igroup == -1) error->all(FLERR,"Could not find set group ID {}", id); - groupbit = group->bitmask[igroup]; - - } else if (strcmp(arg[0],"region") == 0) { - style = REGION_SELECT; - region = domain->get_region_by_id(id); - if (!region) error->all(FLERR,"Set region {} does not exist", id); - - } else error->all(FLERR,"Unknown set command style: {}", arg[0]); - - delete [] id; - - // loop over keyword/value pairs to create list of actions - // one action = keyword/value pair - - naction = maxaction = 0; - actions = nullptr; - Action *action; - - int iarg = 2; - while (iarg < narg) { - if (naction == maxaction) { - maxaction += DELTA; - actions = (Action *) memory->srealloc(actions,maxaction*sizeof(Action),"set:actions"); - invoke_choice = (FnPtrPack *) - memory->srealloc(invoke_choice,maxaction*sizeof(FnPtrPack),"set:invoke_choice"); - } - - action = &actions[naction]; - action->argindex = iarg; - action->varflag = 0; - action->varflag1 = action->varflag2 = action->varflag3 = action->varflag4 = 0; - - if (strcmp(arg[iarg],"angle") == 0) { - action->keyword = ANGLE; - process_angle(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_angle; - } else if (strcmp(arg[iarg],"angmom") == 0) { - action->keyword = ANGMOM; - process_angmom(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_angmom; - } else if (strcmp(arg[iarg],"bond") == 0) { - action->keyword = BOND; - process_bond(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_bond; - } else if (strcmp(arg[iarg],"cc") == 0) { - action->keyword = CC; - process_cc(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_cc; - } else if (strcmp(arg[iarg],"charge") == 0) { - action->keyword = CHARGE; - process_charge(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_charge; - } else if (strcmp(arg[iarg],"density") == 0 ||(strcmp(arg[iarg],"density/disc") == 0)) { - action->keyword = DENSITY; - process_density(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_density; - } else if (strcmp(arg[iarg],"diameter") == 0) { - action->keyword = DIAMETER; - process_diameter(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_diameter; - } else if (strcmp(arg[iarg],"dihedral") == 0) { - action->keyword = DIHEDRAL; - process_dihedral(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_dihedral; - } else if (strcmp(arg[iarg],"dipole") == 0) { - action->keyword = DIPOLE; - process_dipole(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_dipole; - } else if (strcmp(arg[iarg],"dipole/random") == 0) { - action->keyword = DIPOLE_RANDOM; - process_dipole_random(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_dipole_random; - } else if (strcmp(arg[iarg],"dpd/theta") == 0) { - action->keyword = DPD_THETA; - process_dpd_theta(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_dpd_theta; - } else if (strcmp(arg[iarg],"edpd/cv") == 0) { - action->keyword = EDPD_CV; - process_edpd_cv(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_edpd_cv; - } else if (strcmp(arg[iarg],"edpd/temp") == 0) { - action->keyword = EDPD_TEMP; - process_edpd_temp(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_edpd_temp; - } else if (strcmp(arg[iarg],"epsilon") == 0) { - action->keyword = EPSILON; - process_epsilon(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_epsilon; - } else if (strcmp(arg[iarg],"image") == 0) { - action->keyword = IMAGE; - process_image(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_image; - } else if (strcmp(arg[iarg],"improper") == 0) { - action->keyword = IMPROPER; - process_improper(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_improper; - } else if (strcmp(arg[iarg],"length") == 0) { - action->keyword = LENGTH; - process_length(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_length; - } else if (strcmp(arg[iarg],"mass") == 0) { - action->keyword = MASS; - process_mass(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_mass; - } else if (strcmp(arg[iarg],"mol") == 0) { - action->keyword = MOLECULE; - process_mol(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_mol; - } else if (strcmp(arg[iarg],"omega") == 0) { - action->keyword = OMEGA; - process_omega(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_omega; - } else if (strcmp(arg[iarg],"quat") == 0) { - action->keyword = QUAT; - process_quat(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_quat; - } else if (strcmp(arg[iarg],"quat/random") == 0) { - action->keyword = QUAT_RANDOM; - process_quat_random(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_quat_random; - } else if (strcmp(arg[iarg],"radius/electron") == 0) { - action->keyword = RADIUS_ELECTRON; - process_radius_election(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_radius_election; - } else if (strcmp(arg[iarg],"shape") == 0) { - action->keyword = SHAPE; - process_shape(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_shape; - } else if (strcmp(arg[iarg],"smd/contact/radius") == 0) { - action->keyword = SMD_CONTACT_RADIUS; - process_smd_contact_radius(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_smd_contact_radius; - } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { - action->keyword = SMD_MASS_DENSITY; - process_smd_mass_density(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_density; - } else if (strcmp(arg[iarg],"sph/cv") == 0) { - action->keyword = SPH_CV; - process_sph_cv(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_sph_cv; - } else if (strcmp(arg[iarg],"sph/e") == 0) { - action->keyword = SPH_E; - process_sph_e(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_sph_e; - } else if (strcmp(arg[iarg],"sph/rho") == 0) { - action->keyword = SPH_RHO; - process_sph_rho(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_sph_rho; - } else if ((strcmp(arg[iarg],"spin/atom") == 0) || (strcmp(arg[iarg],"spin") == 0)) { - action->keyword = SPIN_ATOM; - process_spin_atom(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_spin_atom; - } else if ((strcmp(arg[iarg],"spin/atom/random") == 0) || (strcmp(arg[iarg],"spin/random") == 0)) { - action->keyword = SPIN_ATOM_RANDOM; - process_spin_atom_random(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_spin_atom_random; - } else if (strcmp(arg[iarg],"spin/electron") == 0) { - action->keyword = SPIN_ELECTRON; - process_spin_electron(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_spin_electron; - } else if (strcmp(arg[iarg],"temperature") == 0) { - action->keyword = TEMPERATURE; - process_temperature(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_temperature; - } else if (strcmp(arg[iarg],"theta") == 0) { - action->keyword = THETA; - process_theta(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_theta; - } else if (strcmp(arg[iarg],"theta/random") == 0) { - action->keyword = THETA_RANDOM; - process_theta_random(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_theta_random; - } else if (strcmp(arg[iarg],"tri") == 0) { - action->keyword = TRI; - process_tri(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_tri; - } else if (strcmp(arg[iarg],"type") == 0) { - action->keyword = TYPE; - process_type(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_type; - } else if (strcmp(arg[iarg],"type/fraction") == 0) { - action->keyword = TYPE_FRACTION; - process_type_fraction(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_type_fraction; - } else if (strcmp(arg[iarg],"type/ratio") == 0) { - action->keyword = TYPE_RATIO; - process_type_ratio(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_type_ratio; - } else if (strcmp(arg[iarg],"type/subset") == 0) { - action->keyword = TYPE_SUBSET; - process_type_subset(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_type_subset; - } else if (strcmp(arg[iarg],"volume") == 0) { - action->keyword = VOLUME; - process_volume(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_volume; - } else if (strcmp(arg[iarg],"vx") == 0) { - action->keyword = VX; - process_vx(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_vx; - } else if (strcmp(arg[iarg],"vy") == 0) { - action->keyword = VY; - process_vy(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_vy; - } else if (strcmp(arg[iarg],"vz") == 0) { - action->keyword = VZ; - process_vz(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_vz; - } else if (strcmp(arg[iarg],"x") == 0) { - action->keyword = X; - process_x(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_x; - } else if (strcmp(arg[iarg],"y") == 0) { - action->keyword = Y; - process_y(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_y; - } else if (strcmp(arg[iarg],"z") == 0) { - action->keyword = Z; - process_z(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_z; - - } else if (utils::strmatch(arg[iarg],"^[id]2?_")) { - process_custom(iarg,narg,arg,action); - invoke_choice[naction++] = &Set2::invoke_custom; - - // just exit with unrecognized keyword - - } else break; - } - - // check keywords for properties that are part of rigid body data - // error if selection includes atoms in rigid bodies - // assume no conflict for properties not in list of cases - - for (int i = 0; i < naction; i++) { - switch (actions[i].keyword) { - case X: - case Y: - case Z: - case MOLECULE: - case MASS: - case ANGMOM: - case SHAPE: - case DIAMETER: - case DENSITY: - case TEMPERATURE: - case QUAT: - case IMAGE: - if (modify->check_rigid_list_overlap(select)) - error->warning(FLERR,"Setting a property of atoms in rigid bodies " - "that has no effect unless rigid bodies are re-initialized"); - break; - default: - break; - } - } - - // return index to next arg to process - // fix set command may append its own options - - return iarg; -} - -/* ---------------------------------------------------------------------- - select atoms according to ATOM, MOLECULE, TYPE, GROUP, REGION style - n = nlocal or nlocal+nghost depending on keyword -------------------------------------------------------------------------- */ - -void Set2::selection(int n) -{ - memory->destroy(select); - memory->create(select,n,"set:select"); - - if (style == ATOM_SELECT) { - tagint *tag = atom->tag; - for (int i = 0; i < n; i++) - if (tag[i] >= nlobig && tag[i] <= nhibig) select[i] = 1; - else select[i] = 0; - - } else if (style == MOL_SELECT) { - tagint *molecule = atom->molecule; - for (int i = 0; i < n; i++) - if (molecule[i] >= nlobig && molecule[i] <= nhibig) select[i] = 1; - else select[i] = 0; - - } else if (style == TYPE_SELECT) { - int *type = atom->type; - for (int i = 0; i < n; i++) - if (type[i] >= nlo && type[i] <= nhi) select[i] = 1; - else select[i] = 0; - - } else if (style == GROUP_SELECT) { - int *mask = atom->mask; - for (int i = 0; i < n; i++) - if (mask[i] & groupbit) select[i] = 1; - else select[i] = 0; - - } else if (style == REGION_SELECT) { - region->prematch(); - double **x = atom->x; - for (int i = 0; i < n; i++) - if (region->match(x[i][0],x[i][1],x[i][2])) select[i] = 1; - else select[i] = 0; - } - - // count_select = count of selected owned atoms - - count_select = 0; - for (int i = 0; i < n; i++) - if (select[i]) count_select++; -} - -/* ---------------------------------------------------------------------- - loop over list of actions - perform each on all selected atoms via call to invoke_choice() method -------------------------------------------------------------------------- */ - -void Set2::invoke_actions() -{ - int nlocal = atom->nlocal; - - // NOTE: need to create vec1234 ahead of time - - for (int i = 0; i < naction; i++) { - - Action *action = &actions[i]; - - // use count_action to optionally override count_select - // if stays -1, count_select is used by caller - // if overwritten by an invoke method, count_action is used - // only a handful of invoke methods tally their own count - - count_action = -1; - - // evaluate atom-style variable(s) if necessary - - if (action->varflag) { - if (action->varflag1) { - input->variable->compute_atom(action->ivar1,0,vec1,1,0); - } - if (action->varflag2) { - input->variable->compute_atom(action->ivar2,0,vec2,1,0); - } - if (action->varflag3) { - input->variable->compute_atom(action->ivar3,0,vec3,1,0); - } - if (action->varflag4) { - input->variable->compute_atom(action->ivar4,0,vec4,1,0); - } - } - - // invoke the action to reset per-atom or per-topology values - - (this->*invoke_choice[i])(action); - - action->count_select = count_select; - action->count_action = count_action; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::varparse(const char *name, int m) -{ - int ivar = input->variable->find(name+2); - if (ivar < 0) - error->all(FLERR,"Variable name {} for set command does not exist", name); - if (!input->variable->atomstyle(ivar)) - error->all(FLERR,"Variable {} for set command is invalid style", name); - - Action *action = &actions[naction]; - action->varflag = 1; - - if (m == 1) { - action->varflag1 = 1; action->ivar1 = ivar; - } else if (m == 2) { - action->varflag2 = 1; action->ivar2 = ivar; - } else if (m == 3) { - action->varflag3 = 1; action->ivar3 = ivar; - } else if (m == 4) { - action->varflag4 = 1; action->ivar4 = ivar; - } -} - -/* ---------------------------------------------------------------------- - set an owned atom property randomly - set seed based on atom coordinates - make atom result independent of what proc owns it -------------------------------------------------------------------------- */ - -void Set2::setrandom(int keyword, Action *action) -{ - int i; - - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - auto avec_line = dynamic_cast(atom->style_match("line")); - auto avec_tri = dynamic_cast(atom->style_match("tri")); - auto avec_body = dynamic_cast(atom->style_match("body")); - - double **x = atom->x; - - // seed is always set to ivalue1 in process() methods - - int seed = action->ivalue1; - - auto ranpark = new RanPark(lmp,1); - auto ranmars = new RanMars(lmp,seed + comm->me); - - // set approx fraction of atom types to newtype - - if (keyword == TYPE_FRACTION) { - int nlocal = atom->nlocal; - double fraction = action->dvalue1; - int newtype = action->ivalue2; - int count = 0; - - for (i = 0; i < nlocal; i++) - if (select[i]) { - ranpark->reset(seed,x[i]); - if (ranpark->uniform() > fraction) continue; - atom->type[i] = newtype; - count++; - } - - count_action = count; - - // set exact count of atom types to newtype - // for TYPE_RATIO, exact = fraction out of total eligible - // for TYPE_SUBSET, exact = nsubset out of total eligible - - } else if (keyword == TYPE_RATIO || keyword == TYPE_SUBSET) { - int nlocal = atom->nlocal; - int newtype = action->ivalue2; - - // convert specified fraction to nsubset of all selected atoms - - bigint bcount = count_select; - bigint allcount; - MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); - - bigint nsubset; - if (keyword == TYPE_RATIO) { - double fraction = action->dvalue1; - nsubset = static_cast (fraction * allcount); - } else if (keyword == TYPE_SUBSET) { - nsubset = action->bvalue1; - if (nsubset > allcount) - error->all(FLERR,"Set type/subset value exceeds eligible atoms"); - } - - // make selection - - int *flag = memory->create(flag,count_select,"set:flag"); - int *work = memory->create(work,count_select,"set:work"); - - ranmars->select_subset(nsubset,count_select,flag,work); - - // change types of selected atoms - // flag vector from select_subset() is only for eligible atoms - - int count = 0; - int eligible = 0; - - for (i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (flag[eligible]) { - atom->type[i] = newtype; - count++; - } - eligible++; - } - - count_action = count; - - // clean up - - memory->destroy(flag); - memory->destroy(work); - - // set dipole moments to random orientations in 3d or 2d - // dipole length is determined by dipole type array - - } else if (keyword == DIPOLE_RANDOM) { - double **mu = atom->mu; - int nlocal = atom->nlocal; - double dmag = action->dvalue1; - double msq,scale; - - if (domain->dimension == 3) { - for (i = 0; i < nlocal; i++) - if (select[i]) { - ranpark->reset(seed,x[i]); - mu[i][0] = ranpark->uniform() - 0.5; - mu[i][1] = ranpark->uniform() - 0.5; - mu[i][2] = ranpark->uniform() - 0.5; - msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]; - scale = dmag/sqrt(msq); - mu[i][0] *= scale; - mu[i][1] *= scale; - mu[i][2] *= scale; - mu[i][3] = dmag; - } - - } else { - for (i = 0; i < nlocal; i++) - if (select[i]) { - ranpark->reset(seed,x[i]); - mu[i][0] = ranpark->uniform() - 0.5; - mu[i][1] = ranpark->uniform() - 0.5; - mu[i][2] = 0.0; - msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1]; - scale = dmag/sqrt(msq); - mu[i][0] *= scale; - mu[i][1] *= scale; - mu[i][3] = dmag; - } - } - - // set spin moments to random orientations in 3d or 2d - // spin length is fixed to unity - - } else if (keyword == SPIN_ATOM_RANDOM) { - double **sp = atom->sp; - int nlocal = atom->nlocal; - double dlen = action->dvalue1; - double sp_sq,scale; - - if (domain->dimension == 3) { - for (i = 0; i < nlocal; i++) - if (select[i]) { - ranpark->reset(seed,x[i]); - sp[i][0] = ranpark->uniform() - 0.5; - sp[i][1] = ranpark->uniform() - 0.5; - sp[i][2] = ranpark->uniform() - 0.5; - sp_sq = sp[i][0]*sp[i][0] + sp[i][1]*sp[i][1] + sp[i][2]*sp[i][2]; - scale = 1.0/sqrt(sp_sq); - sp[i][0] *= scale; - sp[i][1] *= scale; - sp[i][2] *= scale; - sp[i][3] = dlen; - } - - } else { - for (i = 0; i < nlocal; i++) - if (select[i]) { - ranpark->reset(seed,x[i]); - sp[i][0] = ranpark->uniform() - 0.5; - sp[i][1] = ranpark->uniform() - 0.5; - sp[i][2] = 0.0; - sp_sq = sp[i][0]*sp[i][0] + sp[i][1]*sp[i][1]; - scale = 1.0/sqrt(sp_sq); - sp[i][0] *= scale; - sp[i][1] *= scale; - sp[i][3] = dlen; - } - } - - // set quaternions to random orientations in 3d and 2d - - } else if (keyword == QUAT_RANDOM) { - int *ellipsoid = atom->ellipsoid; - int *tri = atom->tri; - int *body = atom->body; - double **quat = atom->quat; - int nlocal = atom->nlocal; - int quat_flag = atom->quat_flag; - double *quat_one; - - if (domain->dimension == 3) { - double s,t1,t2,theta1,theta2; - for (i = 0; i < nlocal; i++) - if (select[i]) { - if (avec_ellipsoid && ellipsoid[i] >= 0) - quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; - else if (avec_tri && tri[i] >= 0) - quat_one = avec_tri->bonus[tri[i]].quat; - else if (avec_body && body[i] >= 0) - quat_one = avec_body->bonus[body[i]].quat; - else if (quat_flag) - quat_one = quat[i]; - else - error->one(FLERR,"Cannot set quaternion for atom that has none"); - - ranpark->reset(seed,x[i]); - s = ranpark->uniform(); - t1 = sqrt(1.0-s); - t2 = sqrt(s); - theta1 = 2.0*MY_PI*ranpark->uniform(); - theta2 = 2.0*MY_PI*ranpark->uniform(); - quat_one[0] = cos(theta2)*t2; - quat_one[1] = sin(theta1)*t1; - quat_one[2] = cos(theta1)*t1; - quat_one[3] = sin(theta2)*t2; - } - - } else { - double theta2; - for (i = 0; i < nlocal; i++) - if (select[i]) { - if (avec_ellipsoid && ellipsoid[i] >= 0) - quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; - else if (avec_body && body[i] >= 0) - quat_one = avec_body->bonus[body[i]].quat; - else if (quat_flag) - quat_one = quat[i]; - else - error->one(FLERR,"Cannot set quaternion for atom that has none"); - - ranpark->reset(seed,x[i]); - theta2 = MY_PI*ranpark->uniform(); - quat_one[0] = cos(theta2); - quat_one[1] = 0.0; - quat_one[2] = 0.0; - quat_one[3] = sin(theta2); - } - } - - // set theta to random orientation in 2d - - } else if (keyword == THETA_RANDOM) { - int *line = atom->line; - int nlocal = atom->nlocal; - - for (i = 0; i < nlocal; i++) { - if (select[i]) { - if (line[i] < 0) - error->one(FLERR,"Cannot set theta for atom that is not a line"); - ranpark->reset(seed,x[i]); - avec_line->bonus[line[i]].theta = MY_2PI*ranpark->uniform(); - } - } - } - - delete ranpark; - delete ranmars; -} - -/* ---------------------------------------------------------------------- */ - -void Set2::topology(int keyword, Action *action) -{ - int m,atom1,atom2,atom3,atom4; - - // error check - - if (atom->molecular == Atom::TEMPLATE) - error->all(FLERR,"Cannot set bond topology types for atom style template"); - - // border swap to acquire ghost atom info - // enforce PBC before in case atoms are outside box - // init entire system since comm->exchange is done - // comm::init needs neighbor::init needs pair::init needs kspace::init, etc - - if (comm->me == 0) utils::logmesg(lmp," system init for set ...\n"); - lmp->init(); - - if (domain->triclinic) domain->x2lamda(atom->nlocal); - domain->pbc(); - domain->reset_box(); - comm->setup(); - comm->exchange(); - comm->borders(); - if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); - - // select both owned and ghost atoms - - selection(atom->nlocal + atom->nghost); - - int count = 0; - - // for BOND, each of 2 atoms must be in group - - if (keyword == BOND) { - int *num_bond = atom->num_bond; - int **bond_type = atom->bond_type; - tagint **bond_atom = atom->bond_atom; - int nlocal = atom->nlocal; - - int itype = action->ivalue1; - for (int i = 0; i < nlocal; i++) - for (m = 0; m < num_bond[i]; m++) { - atom1 = atom->map(bond_atom[i][m]); - if (atom1 == -1) error->one(FLERR,"Bond atom missing in set command"); - if (select[i] && select[atom1]) { - bond_type[i][m] = itype; - count++; - } - } - } - - // for ANGLE, each of 3 atoms must be in group - - if (keyword == ANGLE) { - int *num_angle = atom->num_angle; - int **angle_type = atom->angle_type; - tagint **angle_atom1 = atom->angle_atom1; - tagint **angle_atom2 = atom->angle_atom2; - tagint **angle_atom3 = atom->angle_atom3; - int nlocal = atom->nlocal; - - int itype = action->ivalue1; - for (int i = 0; i < nlocal; i++) - for (m = 0; m < num_angle[i]; m++) { - atom1 = atom->map(angle_atom1[i][m]); - atom2 = atom->map(angle_atom2[i][m]); - atom3 = atom->map(angle_atom3[i][m]); - if (atom1 == -1 || atom2 == -1 || atom3 == -1) - error->one(FLERR,"Angle atom missing in set command"); - if (select[atom1] && select[atom2] && select[atom3]) { - angle_type[i][m] = itype; - count++; - } - } - } - - // for DIHEDRAL, each of 4 atoms must be in group - - if (keyword == DIHEDRAL) { - int *num_dihedral = atom->num_dihedral; - int **dihedral_type = atom->dihedral_type; - tagint **dihedral_atom1 = atom->dihedral_atom1; - tagint **dihedral_atom2 = atom->dihedral_atom2; - tagint **dihedral_atom3 = atom->dihedral_atom3; - tagint **dihedral_atom4 = atom->dihedral_atom4; - int nlocal = atom->nlocal; - - int itype = action->ivalue1; - for (int i = 0; i < nlocal; i++) - for (m = 0; m < num_dihedral[i]; m++) { - atom1 = atom->map(dihedral_atom1[i][m]); - atom2 = atom->map(dihedral_atom2[i][m]); - atom3 = atom->map(dihedral_atom3[i][m]); - atom4 = atom->map(dihedral_atom4[i][m]); - if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) - error->one(FLERR,"Dihedral atom missing in set command"); - if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { - dihedral_type[i][m] = itype; - count++; - } - } - } - - // for IMPROPER, each of 4 atoms must be in group - - if (keyword == IMPROPER) { - int *num_improper = atom->num_improper; - int **improper_type = atom->improper_type; - tagint **improper_atom1 = atom->improper_atom1; - tagint **improper_atom2 = atom->improper_atom2; - tagint **improper_atom3 = atom->improper_atom3; - tagint **improper_atom4 = atom->improper_atom4; - int nlocal = atom->nlocal; - - int itype = action->ivalue1; - for (int i = 0; i < nlocal; i++) - for (m = 0; m < num_improper[i]; m++) { - atom1 = atom->map(improper_atom1[i][m]); - atom2 = atom->map(improper_atom2[i][m]); - atom3 = atom->map(improper_atom3[i][m]); - atom4 = atom->map(improper_atom4[i][m]); - if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) - error->one(FLERR,"Improper atom missing in set command"); - if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) { - improper_type[i][m] = itype; - count++; - } - } - } - - // set count_action for all topology actions - - count_action = count; -} - -// ---------------------------------------------------------------------- -// pairs of process/invoke methods for each keyword -// process method reads args, stores parameters in Action instance -// invoke method resets atoms properties using Action instance -// separate two operations so can be called by either set or fix set command -// ---------------------------------------------------------------------- - -void Set2::process_angle(int &iarg, int narg, char **arg, Action *action) -{ - if (atom->avec->angles_allow == 0) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set angle", error); - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ANGLE,lmp); - action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue1 <= 0 || action->ivalue1 > atom->nangletypes) - error->all(FLERR,"Invalid angle type in set command"); - iarg += 2; -} - -void Set2::invoke_angle(Action *action) -{ - topology(ANGLE,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_angmom(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->angmom_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); - - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - - iarg += 4; -} - -void Set2::invoke_angmom(Action *action) -{ - int nlocal = atom->nlocal; - double **angmom = atom->angmom; - - int varflag = action->varflag; - double xvalue,yvalue,zvalue; - if (!action->varflag1) xvalue = action->dvalue1; - if (!action->varflag2) yvalue = action->dvalue2; - if (!action->varflag3) zvalue = action->dvalue3; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - if (action->varflag1) xvalue = vec1[i]; - if (action->varflag1) yvalue = vec2[i]; - if (action->varflag1) zvalue = vec3[i]; - } - - angmom[i][0] = xvalue; - angmom[i][1] = yvalue; - angmom[i][2] = zvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_bond(int &iarg, int narg, char **arg, Action *action) -{ - if (atom->avec->bonds_allow == 0) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set bond", error); - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::BOND,lmp); - action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue1 <= 0 || action->ivalue1 > atom->nbondtypes) - error->all(FLERR,"Invalid bond type in set command"); - - iarg += 2; -} - -void Set2::invoke_bond(Action *action) -{ - topology(BOND,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_cc(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->tdpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set cc", error); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (action->ivalue1 < 1) error->all(FLERR,"Invalid cc index in set command"); - - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid cc value in set command"); - } - - iarg += 3; -} - -void Set2::invoke_cc(Action *action) -{ - int nlocal = atom->nlocal; - double **cc = atom->cc; - - int cc_index = action->ivalue1 - 1; - // NOTE: need to check if cc_index exceeds cc array allocation - - int varflag = action->varflag; - double ccvalue; - if (!action->varflag1) ccvalue = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - ccvalue = vec1[i]; - if (ccvalue < 0.0) error->all(FLERR,"Invalid cc value in set command"); - } - - cc[i][cc_index] = ccvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_charge(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->q_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set charge", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_charge(Action *action) -{ - int nlocal = atom->nlocal; - double *q = atom->q; - double *q_scaled = atom->q_scaled; - double *epsilon = atom->epsilon; - - int varflag = action->varflag; - double qvalue; - if (!action->varflag1) qvalue = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) qvalue = vec1[i]; - q[i] = qvalue; - - // ensure scaled charges are consistent with new charge value - - if (epsilon) q_scaled[i] = qvalue / epsilon[i]; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_density(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->rmass_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set density", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid density in set command"); - } - - action->ivalue1 = 0; - if (strcmp(arg[iarg],"density/disc") == 0) { - action->ivalue1 = 1; - if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); - } - - iarg += 2; -} - -void Set2::invoke_density(Action *action) -{ - int nlocal = atom->nlocal; - double *rmass = atom->rmass; - double *radius = atom->radius; - int *ellipsoid = atom->ellipsoid; - int *line = atom->line; - int *tri = atom->tri; - - int radius_flag = atom->radius_flag; - int ellipsoid_flag = atom->ellipsoid_flag; - int line_flag = atom->line_flag; - int tri_flag = atom->tri_flag; - - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - auto avec_line = dynamic_cast(atom->style_match("line")); - auto avec_tri = dynamic_cast(atom->style_match("tri")); - - int varflag = action->varflag; - double density; - if (!action->varflag1) density = action->dvalue1; - int discflag = action->ivalue1; - - // set rmass via density - // if radius > 0.0, treat as sphere or disc - // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) - // if length > 0.0, treat as line - // if area > 0.0, treat as tri - // else set rmass to density directly - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - density = vec1[i]; - if (density <= 0.0) error->one(FLERR,"Invalid density in set command"); - } - - if (radius_flag && radius[i] > 0.0) - if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * density; - else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * density; - - else if (ellipsoid_flag && ellipsoid[i] >= 0) { - double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; - // could enable 2d ellipse (versus 3d ellipsoid) when time integration - // options (fix nve/asphere, fix nh/asphere) are also implemented - // if (discflag) - // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; - // else - rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * density; - - } else if (line_flag && line[i] >= 0) { - double length = avec_line->bonus[line[i]].length; - rmass[i] = length * density; - - } else if (tri_flag && tri[i] >= 0) { - double *c1 = avec_tri->bonus[tri[i]].c1; - double *c2 = avec_tri->bonus[tri[i]].c2; - double *c3 = avec_tri->bonus[tri[i]].c3; - double c2mc1[3],c3mc1[3]; - MathExtra::sub3(c2,c1,c2mc1); - MathExtra::sub3(c3,c1,c3mc1); - double norm[3]; - MathExtra::cross3(c2mc1,c3mc1,norm); - double area = 0.5 * MathExtra::len3(norm); - rmass[i] = area * density; - - } else rmass[i] = density; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_diameter(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->radius_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set diameter", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid diameter in set command"); - } - - iarg += 2; -} - -void Set2::invoke_diameter(Action *action) -{ - int nlocal = atom->nlocal; - double *radius = atom->radius; - - int varflag = action->varflag; - double diam; - if (!action->varflag1) diam = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - diam = vec1[i]; - if (diam < 0.0) error->one(FLERR,"Invalid diameter in set command"); - } - - radius[i] = 0.5 * diam; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dihedral(int &iarg, int narg, char **arg, Action *action) -{ - if (atom->avec->dihedrals_allow == 0) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dihedral", error); - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::DIHEDRAL,lmp); - action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue1 <= 0 || action->ivalue1 > atom->ndihedraltypes) - error->all(FLERR,"Invalid dihedral type in set command"); - - iarg += 2; -} - -void Set2::invoke_dihedral(Action *action) -{ - topology(DIHEDRAL,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dipole(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->mu_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set dipole", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - - iarg += 4; -} - -void Set2::invoke_dipole(Action *action) -{ - int nlocal = atom->nlocal; - double **mu = atom->mu; - - int varflag = action->varflag; - double xvalue,yvalue,zvalue; - if (!action->varflag1) xvalue = action->dvalue1; - if (!action->varflag2) yvalue = action->dvalue2; - if (!action->varflag3) zvalue = action->dvalue3; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - if (action->varflag1) xvalue = vec1[i]; - if (action->varflag1) yvalue = vec2[i]; - if (action->varflag1) zvalue = vec3[i]; - } - - mu[i][0] = xvalue; - mu[i][1] = yvalue; - mu[i][2] = zvalue; - mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]); - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dipole_random(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->mu_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (action->ivalue1 <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - if (action->dvalue1 <= 0.0) - error->all(FLERR,"Invalid dipole length in set command"); - - iarg += 3; -} - -void Set2::invoke_dipole_random(Action *action) -{ - setrandom(DIPOLE_RANDOM,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_dpd_theta(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->dpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); - - if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; - else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid dpd/theta value in set command"); - } - - iarg += 2; -} - -void Set2::invoke_dpd_theta(Action *action) -{ - int nlocal = atom->nlocal; - int *type = atom->type; - double **v = atom->v; - double *mass = atom->mass; - double *rmass = atom->rmass; - double *dpdTheta = atom->dpdTheta; - - double tfactor = force->mvv2e / (domain->dimension * force->boltz); - double onemass; - double vx,vy,vz; - - int varflag = action->varflag; - double theta; - if (!action->varflag1) theta = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - theta = vec1[i]; - if (theta < 0.0) error->one(FLERR,"Invalid dpd/theta value in set command"); - } - - // if theta is negative, NULL was used, set dpdTheta to KE of particle - - if (theta >= 0.0) dpdTheta[i] = theta; - else { - if (rmass) onemass = rmass[i]; - else onemass = mass[type[i]]; - vx = v[i][0]; - vy = v[i][1]; - vz = v[i][2]; - dpdTheta[i] = tfactor * onemass * (vx*vx + vy*vy + vz*vz); - } - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_edpd_cv(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->edpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/cv", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/cv value in set command"); - } - - iarg += 2; -} - -void Set2::invoke_edpd_cv(Action *action) -{ - int nlocal = atom->nlocal; - double *edpd_cv = atom->edpd_cv; - - int varflag = action->varflag; - double cv; - if (!action->varflag1) cv = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - cv = vec1[i]; - if (cv < 0.0) error->one(FLERR,"Invalid edpd/cv value in set command"); - } - - edpd_cv[i] = cv; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_edpd_temp(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->edpd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set edpd/temp", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/temp value in set command"); - } - iarg += 2; -} - -void Set2::invoke_edpd_temp(Action *action) -{ - int nlocal = atom->nlocal; - double *edpd_temp = atom->edpd_temp; - - int varflag = action->varflag; - double temp; - if (!action->varflag1) temp = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - temp = vec1[i]; - if (temp < 0.0) error->one(FLERR,"Invalid edpd/temp value in set command"); - } - - edpd_temp[i] = temp; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_epsilon(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->dielectric_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set epsilon", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid epsilon in set command"); - } - - iarg += 2; -} - -void Set2::invoke_epsilon(Action *action) -{ - int nlocal = atom->nlocal; - double *epsilon = atom->epsilon; - double *q = atom->q; - double *q_scaled = atom->q_scaled; - - int varflag = action->varflag; - double eps; - if (!action->varflag1) eps = action->dvalue1; - - // assign local dielectric constant - // also update scaled charge value - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - eps = vec1[i]; - if (eps <= 0.0) error->one(FLERR,"Invalid epsilon in set command"); - } - - epsilon[i] = eps; - q_scaled[i] = q[i] / eps; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_image(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); - - if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue4 = 0; - else { - action->ivalue4 = 1; - if (utils::strmatch(arg[iarg+1],"^v_")) { - if (!domain->xperiodic) - error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); - varparse(arg[iarg+1],1); - } else { - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (action->ivalue1 && !domain->xperiodic) - error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); - } - } - - if (strcmp(arg[iarg+2],"NULL") == 0) action->ivalue5 = 0; - else { - action->ivalue5 = 1; - if (utils::strmatch(arg[iarg+2],"^v_")) { - if (!domain->yperiodic) - error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); - varparse(arg[iarg+2],2); - } else { - action->ivalue2 = utils::inumeric(FLERR,arg[iarg+2],false,lmp); - if (action->ivalue2 && !domain->yperiodic) - error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); - } - } - - if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue6 = 0; - else { - action->ivalue6 = 1; - if (utils::strmatch(arg[iarg+3],"^v_")) { - if (!domain->zperiodic) - error->all(FLERR,"Cannot set variable image flag for non-periodic dimension"); - varparse(arg[iarg+3],3); - } else { - action->ivalue3 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - if (action->ivalue3 && !domain->zperiodic) - error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); - } - } - - iarg += 4; -} - -void Set2::invoke_image(Action *action) -{ - int nlocal = atom->nlocal; - imageint *image = atom->image; - int xbox,ybox,zbox; - - int ximageflag = action->ivalue4; - int yimageflag = action->ivalue5; - int zimageflag = action->ivalue6; - - int varflag = action->varflag; - int ximage,yimage,zimage; - if (!action->varflag1) ximage = action->ivalue1; - if (!action->varflag2) yimage = action->ivalue2; - if (!action->varflag3) zimage = action->ivalue3; - - // reset any or all of 3 image flags - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - if (action->varflag1) ximage = static_cast (vec1[i]); - if (action->varflag2) yimage = static_cast (vec2[i]); - if (action->varflag3) zimage = static_cast (vec3[i]); - } - - xbox = (image[i] & IMGMASK) - IMGMAX; - ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; - zbox = (image[i] >> IMG2BITS) - IMGMAX; - if (ximageflag) xbox = ximage; - if (yimageflag) ybox = yimage; - if (zimageflag) zbox = zimage; - image[i] = ((imageint) (xbox + IMGMAX) & IMGMASK) | - (((imageint) (ybox + IMGMAX) & IMGMASK) << IMGBITS) | - (((imageint) (zbox + IMGMAX) & IMGMASK) << IMG2BITS); - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_improper(int &iarg, int narg, char **arg, Action *action) -{ - if (atom->avec->impropers_allow == 0) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set improper", error); - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::IMPROPER,lmp); - action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue1 <= 0 || action->ivalue1 > atom->nimpropertypes) - error->all(FLERR,"Invalid value in set command"); - - iarg += 2; -} - -void Set2::invoke_improper(Action *action) -{ - topology(IMPROPER,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_length(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->line_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set length", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid length in set command"); - } - - iarg += 2; -} - -void Set2::invoke_length(Action *action) -{ - int nlocal = atom->nlocal; - auto avec_line = dynamic_cast(atom->style_match("line")); - - int varflag = action->varflag; - double length; - if (!action->varflag1) length = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - length = vec1[i]; - if (length < 0.0) error->one(FLERR,"Invalid length in set command"); - } - - avec_line->set_length(i,length); - } - - // update global line count - - bigint nlocal_bonus = avec_line->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->nlines,1,MPI_LMP_BIGINT,MPI_SUM,world); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_mass(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->rmass_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mass", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid mass in set command"); - } - - iarg += 2; -} - -void Set2::invoke_mass(Action *action) -{ - int nlocal = atom->nlocal; - double *rmass = atom->rmass; - - int varflag = action->varflag; - double mass_one; - if (!action->varflag1) mass_one = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - mass_one = vec1[i]; - if (mass_one < 0.0) error->one(FLERR,"Invalid mass in set command"); - } - - rmass[i] = mass_one; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_mol(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->molecule_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set mol", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->tvalue1 = utils::tnumeric(FLERR,arg[iarg+1],false,lmp); - if (action->tvalue1 < 0) error->one(FLERR,"Invalid molecule ID in set command"); - } - - iarg += 2; -} - -void Set2::invoke_mol(Action *action) -{ - int nlocal = atom->nlocal; - int *molecule = atom->molecule; - - int varflag = action->varflag; - tagint molID; - if (!action->varflag1) molID = action->tvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - molID = vec1[i]; - if (molID < 0) error->one(FLERR,"Invalid molecule ID in set command"); - } - - molecule[i] = molID; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_omega(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->omega_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set omega", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - - iarg += 4; -} - -void Set2::invoke_omega(Action *action) -{ - int nlocal = atom->nlocal; - double **omega = atom->angmom; - - int varflag = action->varflag; - double xvalue,yvalue,zvalue; - if (!action->varflag1) xvalue = action->dvalue1; - if (!action->varflag2) yvalue = action->dvalue2; - if (!action->varflag3) zvalue = action->dvalue3; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - if (action->varflag1) xvalue = vec1[i]; - if (action->varflag2) yvalue = vec2[i]; - if (action->varflag3) zvalue = vec3[i]; - } - - omega[i][0] = xvalue; - omega[i][1] = yvalue; - omega[i][2] = zvalue; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_quat(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set quat", error); - int dimension = domain->dimension; - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (dimension == 2 && action->dvalue1 != 0.0) - error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); - } - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else { - action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (dimension == 2 && action->dvalue2 != 0.0) - error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); - } - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); - - iarg += 5; -} - -void Set2::invoke_quat(Action *action) -{ - int nlocal = atom->nlocal; - int *ellipsoid = atom->ellipsoid; - int *tri = atom->tri; - int *body = atom->body; - double **quat = atom->quat; - int quat_flag = atom->quat_flag; - - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - auto avec_tri = dynamic_cast(atom->style_match("tri")); - auto avec_body = dynamic_cast(atom->style_match("body")); - - int dimension = domain->dimension; - double radians,sintheta; - double *quat_one; - - int varflag = action->varflag; - double xvalue,yvalue,zvalue,theta; - if (!action->varflag1) xvalue = action->dvalue1; - if (!action->varflag2) yvalue = action->dvalue2; - if (!action->varflag3) zvalue = action->dvalue3; - if (!action->varflag4) theta = action->dvalue4; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (avec_ellipsoid && ellipsoid[i] >= 0) - quat_one = avec_ellipsoid->bonus[ellipsoid[i]].quat; - else if (avec_tri && tri[i] >= 0) - quat_one = avec_tri->bonus[tri[i]].quat; - else if (avec_body && body[i] >= 0) - quat_one = avec_body->bonus[body[i]].quat; - else if (quat_flag) - quat_one = quat[i]; - else - error->one(FLERR,"Cannot set quaternion for atom that has none"); - - if (varflag) { - if (action->varflag1) xvalue = vec1[i]; - if (action->varflag2) yvalue = vec2[i]; - if (action->varflag3) zvalue = vec3[i]; - if (action->varflag4) theta = vec4[i]; - if (dimension == 2 && (xvalue != 0.0 || yvalue != 0.0)) - error->one(FLERR,"Cannot set quaternion with xy components for 2d system"); - } - - radians = MY_PI2 * theta/180.0; - sintheta = sin(radians); - quat_one[0] = cos(radians); - quat_one[1] = xvalue * sintheta; - quat_one[2] = yvalue * sintheta; - quat_one[3] = zvalue * sintheta; - MathExtra::qnormalize(quat_one); - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_quat_random(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->ellipsoid_flag && !atom->tri_flag && !atom->body_flag && !atom->quat_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set quat/random", error); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - - iarg += 2; -} - -void Set2::invoke_quat_random(Action *action) -{ - setrandom(QUAT_RANDOM,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_radius_election(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->eradius_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid electron radius in set command"); - } - - iarg += 2; -} - -void Set2::invoke_radius_election(Action *action) -{ - int nlocal = atom->nlocal; - double *eradius = atom->eradius; - - int varflag = action->varflag; - double radius; - if (!action->varflag1) radius = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - radius = vec1[i]; - if (radius < 0.0) error->one(FLERR,"Invalid electron radius in set command"); - } - - eradius[i] = radius; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_shape(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->ellipsoid_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set shape", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid shape in set command"); - } - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else { - action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (action->dvalue2 < 0.0) error->one(FLERR,"Invalid shape in set command"); - } - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else { - action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (action->dvalue3 < 0.0) error->one(FLERR,"Invalid shape in set command"); - } - - iarg += 4; -} - -void Set2::invoke_shape(Action *action) -{ - int nlocal = atom->nlocal; - auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); - - int varflag = action->varflag; - double xvalue,yvalue,zvalue; - if (!action->varflag1) xvalue = action->dvalue1; - if (!action->varflag2) yvalue = action->dvalue2; - if (!action->varflag3) zvalue = action->dvalue3; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - if (action->varflag1) xvalue = vec1[i]; - if (action->varflag1) yvalue = vec2[i]; - if (action->varflag1) zvalue = vec3[i]; - if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0) - error->one(FLERR,"Invalid shape in set command"); - } - - if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) - if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) - error->one(FLERR,"Invalid shape in set command"); - - avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); - } - - // update global ellipsoid count - - bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->nellipsoids,1,MPI_LMP_BIGINT,MPI_SUM,world); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_smd_contact_radius(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->smd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/contact/radius", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid smd/contact/radius in set command"); - } - - iarg += 2; -} - -void Set2::invoke_smd_contact_radius(Action *action) -{ - int nlocal = atom->nlocal; - double *contact_radius = atom->contact_radius; - - int varflag = action->varflag; - double radius; - if (!action->varflag1) radius = action->dvalue1; - - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - radius = vec1[i]; - if (radius < 0.0) error->one(FLERR,"Invalid smd/contact/radius in set command"); - } - - contact_radius[i] = radius; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_smd_mass_density(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->smd_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set smd/mass/density", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); - } - - iarg += 2; -} - -void Set2::invoke_smd_mass_density(Action *action) -{ - int nlocal = atom->nlocal; - double *rmass = atom->rmass; - double *vfrac = atom->vfrac; - - int varflag = action->varflag; - double density; - if (!action->varflag1) density = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - density = vec1[i]; - if (density < 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); - } - - rmass[i] = vfrac[i] * density; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_sph_cv(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->cv_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/cv", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_sph_cv(Action *action) -{ - int nlocal = atom->nlocal; - double *cv = atom->cv; - - int varflag = action->varflag; - double sph_cv; - if (!action->varflag1) sph_cv = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) sph_cv = vec1[i]; - cv[i] = sph_cv; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_sph_e(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->esph_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/e", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_sph_e(Action *action) -{ - int nlocal = atom->nlocal; - double *esph = atom->esph; - - int varflag = action->varflag; - double sph_e; - if (!action->varflag1) sph_e = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) sph_e = vec1[i]; - esph[i] = sph_e; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_sph_rho(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->rho_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set sph/rho", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_sph_rho(Action *action) -{ - int nlocal = atom->nlocal; - double *rho = atom->rho; - - int varflag = action->varflag; - double sph_rho; - if (!action->varflag1) sph_rho = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) sph_rho = vec1[i]; - rho[i] = sph_rho; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_spin_atom(int &iarg, int narg, char **arg, Action *action) -{ - if ((strcmp(arg[iarg],"spin") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin is deprecated -- use spin/atom instead"); - if (!atom->sp_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+5 > narg) utils::missing_cmd_args(FLERR, "set spin/atom", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); - } - - if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2); - else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3); - else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4); - else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); - - iarg += 5; -} - -void Set2::invoke_spin_atom(Action *action) -{ - int nlocal = atom->nlocal; - double **sp = atom->sp; - double norm; - - int varflag = action->varflag; - double magnitude,xvalue,yvalue,zvalue; - if (!action->varflag1) magnitude = action->dvalue1; - if (!action->varflag2) xvalue = action->dvalue2; - if (!action->varflag3) yvalue = action->dvalue3; - if (!action->varflag4) zvalue = action->dvalue4; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - if (action->varflag1) magnitude = vec1[i]; - if (magnitude < 0.0) - error->one(FLERR,"Invalid spin magnitude in set command"); - if (action->varflag2) xvalue = vec2[i]; - if (action->varflag3) yvalue = vec3[i]; - if (action->varflag4) zvalue = vec4[i]; - } - - if ((xvalue == 0.0) && (yvalue == 0.0) && (zvalue == 0.0)) - error->all(FLERR,"At least one spin vector component must be non-zero"); - - norm = 1.0/sqrt(xvalue*xvalue+yvalue*yvalue+zvalue*zvalue); - sp[i][0] = norm*xvalue; - sp[i][1] = norm*yvalue; - sp[i][2] = norm*zvalue; - sp[i][3] = magnitude; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_spin_atom_random(int &iarg, int narg, char **arg, Action *action) -{ - if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin/random is deprecated -- use spin/atom/random instead"); - if (!atom->sp_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - - if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); - - iarg += 3; -} - -void Set2::invoke_spin_atom_random(Action *action) -{ - setrandom(SPIN_ATOM_RANDOM,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_spin_electron(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->spin_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set spin/electron", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (action->ivalue1 < -1 || action->ivalue1 > 3) - error->one(FLERR,"Invalid electron spin in set command"); - } - - iarg += 2; -} - -void Set2::invoke_spin_electron(Action *action) -{ - int nlocal = atom->nlocal; - int *spin = atom->spin; - - int varflag = action->varflag; - int ispin; - if (!action->varflag1) ispin = action->ivalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - ispin = static_cast (vec1[i]); - if (ispin < -1 || ispin > 3) - error->one(FLERR,"Invalid electron spin in set command"); - } - - atom->spin[i] = ispin; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_temperature(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->temperature_flag) - error->all(FLERR,"Cannot set this attribute for this atom style"); - if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid temperature in set command"); - } - - iarg += 2; -} - -void Set2::invoke_temperature(Action *action) -{ - int nlocal = atom->nlocal; - double *temperature = atom->temperature; - - int varflag = action->varflag; - double temp; - if (!action->varflag1) temp = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - temp = vec1[i]; - if (temp < 0.0) error->one(FLERR,"Invalid temperature in set command"); - } - - temperature[i] = temp; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_theta(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->line_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_theta(Action *action) -{ - int nlocal = atom->nlocal; - int *line = atom->line; - - auto avec_line = dynamic_cast(atom->style_match("line")); - - int varflag = action->varflag; - double theta; - if (!action->varflag1) theta = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (line[i] < 0) error->one(FLERR,"Cannot set theta for atom which is not a line"); - if (varflag) theta = vec1[i]; - avec_line->bonus[atom->line[i]].theta = theta; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_theta_random(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->line_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - - iarg += 2; -} - -void Set2::invoke_theta_random(Action *action) -{ - setrandom(THETA_RANDOM,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_tri(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->tri_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid tri size in set command"); - } - - iarg += 2; -} - -void Set2::invoke_tri(Action *action) -{ - int nlocal = atom->nlocal; - int *tri = atom->tri; - - auto avec_tri = dynamic_cast(atom->style_match("tri")); - - int varflag = action->varflag; - double trisize; - if (!action->varflag1) trisize = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (tri[i] < 0) error->one(FLERR,"Cannot set tri for atom which is not a triangle"); - - if (varflag) { - trisize = vec1[i]; - if (trisize < 0.0) error->one(FLERR,"Invalid tri size in set command"); - } - - avec_tri->set_equilateral(i,trisize); - } - - // update bonus tri count - - bigint nlocal_bonus = avec_tri->nlocal_bonus; - MPI_Allreduce(&nlocal_bonus,&atom->ntris,1,MPI_LMP_BIGINT,MPI_SUM,world); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_type(int &iarg, int narg, char **arg, Action *action) -{ - 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 { - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - action->ivalue1 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue1 <= 0 || action->ivalue1 > atom->ntypes) - error->one(FLERR,"Invalid atom type in set command"); - } - - iarg += 2; -} - -void Set2::invoke_type(Action *action) -{ - int nlocal = atom->nlocal; - int *type = atom->type; - - int varflag = action->varflag; - int itype; - if (!action->varflag1) itype = action->ivalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (action->varflag) { - itype = static_cast (vec1[i]); - if (itype <= 0 || itype > atom->ntypes) - error->one(FLERR,"Invalid atom type in set command"); - } - - type[i] = itype; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_type_fraction(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); - - // random seed must be ivalue1 for use in setrandom() - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) - error->one(FLERR,"Invalid atom type in set command"); - - action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) - error->all(FLERR,"Invalid fraction in set command"); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - if (action->ivalue1 <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - - iarg += 4; -} - -void Set2::invoke_type_fraction(Action *action) -{ - setrandom(TYPE_FRACTION,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_type_ratio(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/ratio", error); - - // random seed must be ivalue1 for use in setrandom() - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) - error->all(FLERR,"Invalid atom type in set command"); - - action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) - error->all(FLERR,"Invalid fraction in set command"); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - if (action->ivalue1 <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - - iarg += 4; -} - -void Set2::invoke_type_ratio(Action *action) -{ - setrandom(TYPE_RATIO,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_type_subset(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/subset", error); - - // random seed must be ivalue1 for use in setrandom() - - char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); - action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); - delete[] typestr; - if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) - error->all(FLERR,"Invalid atom type in set command"); - - action->bvalue1 = utils::bnumeric(FLERR,arg[iarg+2],false,lmp); - if (action->bvalue1 < 0) - error->all(FLERR,"Invalid subset size in set command"); - - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); - if (action->ivalue1 <= 0) - error->all(FLERR,"Invalid random number seed in set command"); - - iarg += 4; -} - -void Set2::invoke_type_subset(Action *action) -{ - setrandom(TYPE_SUBSET,action); -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_volume(int &iarg, int narg, char **arg, Action *action) -{ - if (!atom->vfrac_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set volume", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid volume in set command"); - } - - iarg += 2; -} - -void Set2::invoke_volume(Action *action) -{ - int nlocal = atom->nlocal; - double *vfrac = atom->vfrac; - - int varflag = action->varflag; - double vol; - if (!action->varflag1) vol = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - - if (varflag) { - vol = vec1[i]; - if (vol < 0.0) error->one(FLERR,"Invalid volume in set command"); - } - - vfrac[i] = vol; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_vx(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vx", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_vx(Action *action) -{ - int nlocal = atom->nlocal; - double **v = atom->v; - - int varflag = action->varflag; - double vx; - if (!action->varflag1) vx = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) vx = vec1[i]; - v[i][0] = vx; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_vy(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vy", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_vy(Action *action) -{ - int nlocal = atom->nlocal; - double **v = atom->v; - - int varflag = action->varflag; - double vy; - if (!action->varflag1) vy = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) vy = vec1[i]; - v[i][1] = vy; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_vz(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set vz", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_vz(Action *action) -{ - int nlocal = atom->nlocal; - double **v = atom->v; - - int varflag = action->varflag; - double vz; - if (!action->varflag1) vz = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) vz = vec1[i]; - v[i][2] = vz; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_x(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set x", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_x(Action *action) -{ - int nlocal = atom->nlocal; - double **x = atom->x; - - int varflag = action->varflag; - double coord; - if (!action->varflag1) coord = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) coord = vec1[i]; - x[i][0] = coord; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_y(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set y", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_y(Action *action) -{ - int nlocal = atom->nlocal; - double **x = atom->x; - - int varflag = action->varflag; - double coord; - if (!action->varflag1) coord = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) coord = vec1[i]; - x[i][1] = coord; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_z(int &iarg, int narg, char **arg, Action *action) -{ - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set z", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - iarg += 2; -} - -void Set2::invoke_z(Action *action) -{ - int nlocal = atom->nlocal; - double **x = atom->x; - - int varflag = action->varflag; - double coord; - if (!action->varflag1) coord = action->dvalue1; - - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) coord = vec1[i]; - x[i][2] = coord; - } -} - -/* ---------------------------------------------------------------------- */ - -void Set2::process_custom(int &iarg, int narg, char **arg, Action *action) -{ - int flag,cols; - ArgInfo argi(arg[iarg],ArgInfo::DNAME|ArgInfo::INAME); - const char *pname = argi.get_name(); - - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set", error); - int index_custom = atom->find_custom(argi.get_name(),flag,cols); - if (index_custom < 0) - error->all(FLERR,"Set keyword or custom property {} does not exist",pname); - action->ivalue2 = index_custom; - - switch (argi.get_type()) { - - case ArgInfo::INAME: - if (flag != 0) error->all(FLERR,"Set command custom property {} is not integer",pname); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - - if (argi.get_dim() == 0) { - if (cols > 0) - error->all(FLERR,"Set command custom integer property {} is not a vector",pname); - action->keyword = IVEC; - } else if (argi.get_dim() == 1) { - if (cols == 0) - error->all(FLERR,"Set command custom integer property {} is not an array",pname); - int icol_custom = argi.get_index1(); - if (icol_custom <= 0 || icol_custom > cols) - error->all(FLERR,"Set command per-atom custom integer array {} is accessed " - "out-of-range",pname); - action->ivalue3 = icol_custom; - action->keyword = IARRAY; - } else error->all(FLERR,"Illegal set command"); - break; - - case ArgInfo::DNAME: - if (flag != 1) error->all(FLERR,"Custom property {} is not floating-point",argi.get_name()); - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1); - else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - - if (argi.get_dim() == 0) { - if (cols > 0) - error->all(FLERR,"Set command custom double property {} is not a vector",pname); - action->keyword = DVEC; - } else if (argi.get_dim() == 1) { - if (cols == 0) - error->all(FLERR,"Set command custom double property {} is not an array",pname); - int icol_custom = argi.get_index1(); - if (icol_custom <= 0 || icol_custom > cols) - error->all(FLERR,"Set command per-atom custom double array {} is " - "accessed out-of-range",pname); - action->ivalue3 = icol_custom; - action->keyword = DARRAY; - } else error->all(FLERR,"Illegal set command"); - break; - - default: - error->all(FLERR,"Illegal set command"); - break; - } - - iarg += 2; -} - -void Set2::invoke_custom(Action *action) -{ - int nlocal = atom->nlocal; - int ivalue; - double dvalue; - - int varflag = action->varflag; - int index_custom = action->ivalue2; - - if (action->keyword == IVEC) { - if (!varflag) ivalue = action->ivalue1; - int *ivector = atom->ivector[index_custom]; - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) ivalue = static_cast (vec1[i]); - ivector[i] = ivalue; - } - - } else if (action->keyword == DVEC) { - if (!varflag) dvalue = action->dvalue1; - double *dvector = atom->dvector[index_custom]; - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) dvalue = vec1[i]; - dvector[i] = dvalue; - } - - } else if (action->keyword == IARRAY) { - if (!varflag) ivalue = action->ivalue1; - int **iarray = atom->iarray[index_custom]; - int icol_custom = action->ivalue3 - 1; - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) ivalue = static_cast (vec1[i]); - iarray[i][icol_custom] = ivalue; - } - - } else if (action->keyword == DARRAY) { - if (!varflag) dvalue = action->dvalue1; - double **darray = atom->darray[index_custom]; - int icol_custom = action->ivalue3 - 1; - for (int i = 0; i < nlocal; i++) { - if (!select[i]) continue; - if (varflag) dvalue = vec1[i]; - darray[i][icol_custom] = dvalue; - } - } -} diff --git a/src/set2.h b/src/set2.h deleted file mode 100644 index c1d0c9b1bc..0000000000 --- a/src/set2.h +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - https://www.lammps.org/, Sandia National Laboratories - LAMMPS development team: developers@lammps.org - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifdef COMMAND_CLASS -// clang-format off -CommandStyle(set2,Set2); -// clang-format on -#else - -#ifndef LMP_SET2_H -#define LMP_SET2_H - -#include "command.h" - -namespace LAMMPS_NS { - -class Set2 : public Command { - public: - Set2(class LAMMPS *lmp); - ~Set2(); - - void command(int, char **) override; - - int process_args(int, int, char **); - void selection(int); - void invoke_actions(); - - private: - int caller; // SETCOMMAND or FIXSET - - // params for atom selection - - int style; - char *id; - int nlo,nhi; - bigint nlobig,nhibig; - int groupbit; - class Region *region; - - // one Action = one keyword/value pair - - struct Action { - int keyword; - int argindex; - int count_select,count_action; - int varflag; - int varflag1, varflag2, varflag3, varflag4; - int ivar1, ivar2, ivar3, ivar4; - int ivalue1, ivalue2, ivalue3, ivalue4, ivalue5, ivalue6; - tagint tvalue1; - bigint bvalue1; - double dvalue1,dvalue2,dvalue3,dvalue4; - }; - - int naction,maxaction; - Action *actions; - - typedef void (Set2::*FnPtrPack)(Action *); - FnPtrPack *invoke_choice; // list of ptrs to invoke functions - - double *vec1, *vec2, *vec3, *vec4; // storage for evaluated peratom variables - - int *select; // flag for selected atoms - int count_select; // count of selected atoms on this proc - int count_action; // count of actions on this proc, only if different than selected - - // private functions - - void varparse(const char *, int); - void setrandom(int, Action *); - void topology(int, Action *); - - // customize by adding a process method - - void process_angle(int &, int, char **, Action *); - void process_angmom(int &, int, char **, Action *); - void process_bond(int &, int, char **, Action *); - void process_cc(int &, int, char **, Action *); - void process_charge(int &, int, char **, Action *); - void process_density(int &, int, char **, Action *); - void process_diameter(int &, int, char **, Action *); - void process_dihedral(int &, int, char **, Action *); - void process_dipole(int &, int, char **, Action *); - void process_dipole_random(int &, int, char **, Action *); - void process_dpd_theta(int &, int, char **, Action *); - void process_edpd_cv(int &, int, char **, Action *); - void process_edpd_temp(int &, int, char **, Action *); - void process_epsilon(int &, int, char **, Action *); - void process_image(int &, int, char **, Action *); - void process_improper(int &, int, char **, Action *); - void process_length(int &, int, char **, Action *); - void process_mass(int &, int, char **, Action *); - void process_mol(int &, int, char **, Action *); - void process_omega(int &, int, char **, Action *); - void process_quat(int &, int, char **, Action *); - void process_quat_random(int &, int, char **, Action *); - void process_radius_election(int &, int, char **, Action *); - void process_shape(int &, int, char **, Action *); - void process_smd_contact_radius(int &, int, char **, Action *); - void process_smd_mass_density(int &, int, char **, Action *); - void process_sph_cv(int &, int, char **, Action *); - void process_sph_e(int &, int, char **, Action *); - void process_sph_rho(int &, int, char **, Action *); - void process_spin_atom(int &, int, char **, Action *); - void process_spin_atom_random(int &, int, char **, Action *); - void process_spin_electron(int &, int, char **, Action *); - void process_temperature(int &, int, char **, Action *); - void process_theta(int &, int, char **, Action *); - void process_theta_random(int &, int, char **, Action *); - void process_tri(int &, int, char **, Action *); - void process_type(int &, int, char **, Action *); - void process_type_fraction(int &, int, char **, Action *); - void process_type_ratio(int &, int, char **, Action *); - void process_type_subset(int &, int, char **, Action *); - void process_volume(int &, int, char **, Action *); - void process_vx(int &, int, char **, Action *); - void process_vy(int &, int, char **, Action *); - void process_vz(int &, int, char **, Action *); - void process_x(int &, int, char **, Action *); - void process_y(int &, int, char **, Action *); - void process_z(int &, int, char **, Action *); - - void process_custom(int &, int, char **, Action *); - - // customize by adding an invoke method - - void invoke_angle(Action *); - void invoke_angmom(Action *); - void invoke_bond(Action *); - void invoke_cc(Action *); - void invoke_charge(Action *); - void invoke_density(Action *); - void invoke_diameter(Action *); - void invoke_dihedral(Action *); - void invoke_dipole(Action *); - void invoke_dipole_random(Action *); - void invoke_dpd_theta(Action *); - void invoke_edpd_cv(Action *); - void invoke_edpd_temp(Action *); - void invoke_epsilon(Action *); - void invoke_image(Action *); - void invoke_improper(Action *); - void invoke_length(Action *); - void invoke_mass(Action *); - void invoke_mol(Action *); - void invoke_omega(Action *); - void invoke_quat(Action *); - void invoke_quat_random(Action *); - void invoke_radius_election(Action *); - void invoke_shape(Action *); - void invoke_smd_contact_radius(Action *); - void invoke_smd_mass_density(Action *); - void invoke_sph_cv(Action *); - void invoke_sph_e(Action *); - void invoke_sph_rho(Action *); - void invoke_spin_atom(Action *); - void invoke_spin_atom_random(Action *); - void invoke_spin_electron(Action *); - void invoke_temperature(Action *); - void invoke_theta(Action *); - void invoke_theta_random(Action *); - void invoke_tri(Action *); - void invoke_type(Action *); - void invoke_type_fraction(Action *); - void invoke_type_ratio(Action *); - void invoke_type_subset(Action *); - void invoke_volume(Action *); - void invoke_vx(Action *); - void invoke_vy(Action *); - void invoke_vz(Action *); - void invoke_x(Action *); - void invoke_y(Action *); - void invoke_z(Action *); - - void invoke_custom(Action *); -}; - -} // namespace LAMMPS_NS - -#endif -#endif - From 3b2f794398875213ae8924d9ea788f25200295b7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 01:03:46 -0400 Subject: [PATCH 08/26] fix issue breaking compilation --- src/fix_set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fix_set.cpp b/src/fix_set.cpp index 2e151a2372..ccdd58ed35 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -15,7 +15,7 @@ #include "atom.h" #include "error.h" -#include "set2.h" +#include "set.h" using namespace LAMMPS_NS; using namespace FixConst; From 12c72593f7b7dbf05334146939c31da48c550834 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 01:17:45 -0400 Subject: [PATCH 09/26] more fixes to recover compilation --- src/fix_set.cpp | 2 +- src/fix_set.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fix_set.cpp b/src/fix_set.cpp index ccdd58ed35..f0f9a5cf50 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -33,7 +33,7 @@ FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) // create instance of Set class - set = new Set2(lmp); + set = new Set(lmp); // pass remaining args to Set class // only keywords which use per-atom variables are currently allowed diff --git a/src/fix_set.h b/src/fix_set.h index 9826d764eb..f5d0aeb3f5 100644 --- a/src/fix_set.h +++ b/src/fix_set.h @@ -32,7 +32,7 @@ class FixSet : public Fix { void end_of_step() override; private: - class Set2 *set; + class Set *set; }; } // namespace LAMMPS_NS From 85bac7665aae0613c33fbc43df856da8d0ec6e7e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 01:24:06 -0400 Subject: [PATCH 10/26] add missing override attribute --- src/set.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/set.h b/src/set.h index 67f0b83fd8..da0397ee52 100644 --- a/src/set.h +++ b/src/set.h @@ -27,8 +27,8 @@ namespace LAMMPS_NS { class Set : public Command { public: Set(class LAMMPS *lmp); - ~Set(); - + ~Set() override; + void command(int, char **) override; void process_args(int, int, char **); From 36ad6ebe527b5184084f4cf66842be7f43fac9f4 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 01:24:23 -0400 Subject: [PATCH 11/26] apply clang-format --- src/set.h | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/set.h b/src/set.h index da0397ee52..65489d9932 100644 --- a/src/set.h +++ b/src/set.h @@ -35,56 +35,56 @@ class Set : public Command { void selection(int); void invoke_actions(); - private: - int caller; // SETCOMMAND or FIXSET + private: + int caller; // SETCOMMAND or FIXSET // params for atom selection int style; char *id; - int nlo,nhi; - bigint nlobig,nhibig; + int nlo, nhi; + bigint nlobig, nhibig; int groupbit; class Region *region; // one Action = one keyword/value pair - + struct Action { int keyword; int argindex; - int count_select,count_action; + int count_select, count_action; int varflag; int varflag1, varflag2, varflag3, varflag4; int ivar1, ivar2, ivar3, ivar4; int ivalue1, ivalue2, ivalue3, ivalue4, ivalue5, ivalue6; tagint tvalue1; bigint bvalue1; - double dvalue1,dvalue2,dvalue3,dvalue4; + double dvalue1, dvalue2, dvalue3, dvalue4; }; - - int naction,maxaction; + + int naction, maxaction; Action *actions; typedef void (Set::*FnPtrPack)(Action *); FnPtrPack *invoke_choice; // list of ptrs to invoke functions - double *vec1, *vec2, *vec3, *vec4; // storage for evaluated peratom variables - int varflag; // 1 if any action uses a per-atom variable - int varflag1,varflag2,varflag3,varflag4; // 1 if any action uses this variable - int maxvariable; // size of peratom variable vectors - - int *select; // flag for selected atoms - int maxselect; // size of select vector - - int count_select; // count of selected atoms on this proc - int count_action; // count of actions on this proc, only if different than selected - + double *vec1, *vec2, *vec3, *vec4; // storage for evaluated peratom variables + int varflag; // 1 if any action uses a per-atom variable + int varflag1, varflag2, varflag3, varflag4; // 1 if any action uses this variable + int maxvariable; // size of peratom variable vectors + + int *select; // flag for selected atoms + int maxselect; // size of select vector + + int count_select; // count of selected atoms on this proc + int count_action; // count of actions on this proc, only if different than selected + // private functions - + void varparse(const char *, int, Action *); void setrandom(int, Action *); void topology(int, Action *); - + // customize by adding a process method void process_angle(int &, int, char **, Action *); @@ -194,4 +194,3 @@ class Set : public Command { #endif #endif - From 78c5e9c00b164d0dccfb07916d69bff2f3f0fa78 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 01:33:17 -0400 Subject: [PATCH 12/26] reformat according to revised programming style and partial clang-format --- src/set.cpp | 55 +++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/set.cpp b/src/set.cpp index f3b05a1152..1e83f1c716 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -58,13 +58,10 @@ enum{ANGLE,ANGMOM,BOND,CC,CHARGE,DENSITY,DIAMETER,DIHEDRAL,DIPOLE, /* ---------------------------------------------------------------------- */ -Set::Set(class LAMMPS *lmp) : Command(lmp) +Set::Set(class LAMMPS *lmp) : + Command(lmp), id(nullptr), region(nullptr), actions(nullptr), invoke_choice(nullptr), + vec1(nullptr), vec2(nullptr), vec3(nullptr), vec4(nullptr), select(nullptr) { - actions = nullptr; - invoke_choice = nullptr; - - select = nullptr; - vec1 = vec2 = vec3 = vec4 = nullptr; maxselect = maxvariable = 0; } @@ -83,24 +80,24 @@ Set::~Set() } /* ---------------------------------------------------------------------- */ - +// clang-format on void Set::command(int narg, char **arg) { if (domain->box_exist == 0) - error->all(FLERR, Error::NOLASTLINE, "Set command before simulation box is defined" - + utils::errorurl(0)); + error->all(FLERR, Error::NOLASTLINE, + "Set command before simulation box is defined" + utils::errorurl(0)); if (atom->natoms == 0) error->all(FLERR, Error::NOLASTLINE, "Set command on system without atoms"); if (narg < 4) error->all(FLERR, 1, "Illegal set command: need at least four arguments"); - process_args(SETCOMMAND,narg,arg); - - if (comm->me == 0) utils::logmesg(lmp,"Setting atom values ...\n"); + process_args(SETCOMMAND, narg, arg); + + if (comm->me == 0) utils::logmesg(lmp, "Setting atom values ...\n"); // select which atoms to act on - + selection(atom->nlocal); - + // loop over list of actions to reset atom attributes invoke_actions(); @@ -108,23 +105,26 @@ void Set::command(int narg, char **arg) // print stats for each action // for CC option, include species index - bigint bcount,allcount; + bigint bcount, allcount; for (int i = 0; i < naction; i++) { Action *action = &actions[i]; int iarg = action->argindex; - - if (action->count_action < 0) bcount = action->count_select; - else bcount = action->count_action; - MPI_Allreduce(&bcount,&allcount,1,MPI_LMP_BIGINT,MPI_SUM,world); - + + if (action->count_action < 0) { + bcount = action->count_select; + } else { + bcount = action->count_action; + } + MPI_Allreduce(&bcount, &allcount, 1, MPI_LMP_BIGINT, MPI_SUM, world); + if (comm->me == 0) { - if (strcmp(arg[iarg],"cc") == 0) - utils::logmesg(lmp," {} settings made for {} index {}\n", - allcount,arg[iarg],arg[iarg+1]); - else - utils::logmesg(lmp," {} settings made for {}\n", - allcount,arg[iarg]); + if (strcmp(arg[iarg], "cc") == 0) { + utils::logmesg(lmp, " {} settings made for {} index {}\n", allcount, arg[iarg], + arg[iarg + 1]); + } else { + utils::logmesg(lmp, " {} settings made for {}\n", allcount, arg[iarg]); + } } } } @@ -2224,7 +2224,8 @@ void Set::process_spin_atom(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); + if (action->dvalue1 <= 0.0) + error->all(FLERR,"Invalid spin magnitude {} in set command"); } if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); From 161776b2c7a19ca9e23d4ee8b27bb3af52f2ebcc Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 02:14:10 -0400 Subject: [PATCH 13/26] recover AtomStyle and SetProperty unit tests --- src/set.cpp | 94 ++++++++++++++----------- unittest/commands/test_set_property.cpp | 9 +-- 2 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/set.cpp b/src/set.cpp index 1e83f1c716..6f5022a66b 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -80,7 +80,7 @@ Set::~Set() } /* ---------------------------------------------------------------------- */ -// clang-format on + void Set::command(int narg, char **arg) { if (domain->box_exist == 0) @@ -136,53 +136,53 @@ void Set::command(int narg, char **arg) void Set::process_args(int caller_flag, int narg, char **arg) { caller = caller_flag; - + // style and ID info id = utils::strdup(arg[1]); - if (strcmp(arg[0],"atom") == 0) { + if (strcmp(arg[0], "atom") == 0) { style = ATOM_SELECT; - if (atom->tag_enable == 0) - error->all(FLERR,"Cannot use set atom with no atom IDs defined"); - utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); + if (atom->tag_enable == 0) error->all(FLERR, "Cannot use set atom with no atom IDs defined"); + utils::bounds(FLERR, id, 1, MAXTAGINT, nlobig, nhibig, error); - } else if (strcmp(arg[0],"mol") == 0) { + } else if (strcmp(arg[0], "mol") == 0) { style = MOL_SELECT; if (atom->molecule_flag == 0) - error->all(FLERR,"Cannot use set mol with no molecule IDs defined"); - utils::bounds(FLERR,id,1,MAXTAGINT,nlobig,nhibig,error); - - } else if (strcmp(arg[0],"type") == 0) { + error->all(FLERR, "Cannot use set mol with no molecule IDs defined"); + utils::bounds(FLERR, id, 1, MAXTAGINT, nlobig, nhibig, error); + + } else if (strcmp(arg[0], "type") == 0) { style = TYPE_SELECT; - if (char *typestr = utils::expand_type(FLERR,id,Atom::ATOM,lmp)) { - delete [] id; + 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); - } else if (strcmp(arg[0],"group") == 0) { + } else if (strcmp(arg[0], "group") == 0) { style = GROUP_SELECT; int igroup = group->find(id); - if (igroup == -1) error->all(FLERR,"Could not find set group ID {}", id); + if (igroup == -1) error->all(FLERR, "Could not find set group ID {}", id); groupbit = group->bitmask[igroup]; - } else if (strcmp(arg[0],"region") == 0) { + } else if (strcmp(arg[0], "region") == 0) { style = REGION_SELECT; region = domain->get_region_by_id(id); - if (!region) error->all(FLERR,"Set region {} does not exist", id); + if (!region) error->all(FLERR, "Set region {} does not exist", id); - } else error->all(FLERR,"Unknown set or fix set command style: {}", arg[0]); + } else + error->all(FLERR, "Unknown set or fix set command style: {}", arg[0]); + + delete[] id; - delete [] id; - // loop over remaining keyword/value pairs to create list of actions // one action = keyword/value pair naction = maxaction = 0; actions = nullptr; Action *action; - + int iarg = 2; while (iarg < narg) { @@ -1815,7 +1815,7 @@ void Set::process_omega(int &iarg, int narg, char **arg, Action *action) void Set::invoke_omega(Action *action) { int nlocal = atom->nlocal; - double **omega = atom->angmom; + double **omega = atom->omega; int varflag = action->varflag; double xvalue,yvalue,zvalue; @@ -1948,15 +1948,18 @@ void Set::invoke_quat_random(Action *action) void Set::process_radius_election(int &iarg, int narg, char **arg, Action *action) { if (!atom->eradius_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); - - if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); + error->all(FLERR, "Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "set radius/electron", error); + + if (utils::strmatch(arg[iarg + 1], "^v_")) + varparse(arg[iarg + 1], 1, action); else { - action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid electron radius in set command"); + action->dvalue1 = utils::numeric(FLERR, arg[iarg + 1], false, lmp); + if (action->dvalue1 < 0.0) + error->one(FLERR, iarg + 1, "Invalid electron radius {} in set radius/electron command", + action->dvalue1); } - + iarg += 2; } @@ -2278,24 +2281,28 @@ void Set::invoke_spin_atom(Action *action) void Set::process_spin_atom_random(int &iarg, int narg, char **arg, Action *action) { - if ((strcmp(arg[iarg],"spin/random") == 0) && (comm->me == 0)) - error->warning(FLERR, "Set attribute spin/random is deprecated -- use spin/atom/random instead"); + if ((strcmp(arg[iarg], "spin/random") == 0) && (comm->me == 0)) + error->warning(FLERR, + "Set attribute spin/random is deprecated -- use spin/atom/random instead"); if (!atom->sp_flag) - error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); + error->all(FLERR, "Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); + if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "set spin/atom/random", error); - action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); - - if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude in set command"); - + action->ivalue1 = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); + action->dvalue1 = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + + if (action->ivalue1 <= 0) + error->all(FLERR, iarg + 1, "Invalid random number seed {} in set {} command", action->ivalue1, + arg[iarg]); + if (action->dvalue1 <= 0.0) + error->all(FLERR, iarg + 2, "Invalid spin magnitude {} in set {} command", action->dvalue1, + arg[iarg]); iarg += 3; } void Set::invoke_spin_atom_random(Action *action) { - setrandom(SPIN_ATOM_RANDOM,action); + setrandom(SPIN_ATOM_RANDOM, action); } /* ---------------------------------------------------------------------- */ @@ -2310,7 +2317,7 @@ void Set::process_spin_electron(int &iarg, int narg, char **arg, Action *action) else { action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 < -1 || action->ivalue1 > 3) - error->one(FLERR,"Invalid electron spin in set command"); + error->one(FLERR,"Invalid electron spin {} in set command", action->ivalue1); } iarg += 2; @@ -2458,7 +2465,10 @@ void Set::invoke_tri(Action *action) for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; +#if 0 + // AK: this seems wrong. Isn't the set command supposed *make* this a triangle? if (tri[i] < 0) error->one(FLERR,"Cannot set tri for atom which is not a triangle"); +#endif if (varflag) { trisize = vec1[i]; diff --git a/unittest/commands/test_set_property.cpp b/unittest/commands/test_set_property.cpp index c306ea4739..7944e36222 100644 --- a/unittest/commands/test_set_property.cpp +++ b/unittest/commands/test_set_property.cpp @@ -90,8 +90,9 @@ TEST_F(SetTest, NoBoxNoAtoms) ASSERT_EQ(compute->vector_atom[0], 0); TEST_FAILURE(".*ERROR: Illegal set command: need at least four.*", command("set type 1 x");); - TEST_FAILURE(".*ERROR: Unknown set command style: xxx.*", command("set xxx 1 x 0.0");); - TEST_FAILURE(".*ERROR: Set keyword or custom property yyy does not exist.*", + TEST_FAILURE(".*ERROR: Unknown set or fix set command style: xxx.*", + command("set xxx 1 x 0.0");); + TEST_FAILURE(".*ERROR: Unrecognized set or fix set keyword yyy.*", command("set type 1 yyy 0.0");); TEST_FAILURE(".*ERROR: Cannot set attribute spin/atom for atom style atomic.*", @@ -447,9 +448,9 @@ TEST_F(SetTest, EffPackage) EXPECT_EQ(compute->array_atom[6][1], 0.5); EXPECT_EQ(compute->array_atom[7][1], 1.0); - TEST_FAILURE(".*ERROR on proc 0: Incorrect value for electron spin: 0.5.*", + TEST_FAILURE(".*Expected integer parameter instead of '0.5' in input script.*", command("set atom * spin/electron 0.5");); - TEST_FAILURE(".*ERROR on proc 0: Incorrect value for electron radius: -0.5.*", + TEST_FAILURE(".*ERROR on proc 0: Invalid electron radius -0.5 in set.*", command("set atom * radius/electron -0.5");); } From 3221c53b1401971dc85de0dd4c0e0471f3b1f5a4 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 02:14:42 -0400 Subject: [PATCH 14/26] whitespace --- doc/src/set.rst | 4 +- src/fix_set.cpp | 4 +- src/set.cpp | 314 ++++++++++++++++++++++++------------------------ 3 files changed, 161 insertions(+), 161 deletions(-) diff --git a/doc/src/set.rst b/doc/src/set.rst index dde5ca99fe..9d86f766a4 100644 --- a/doc/src/set.rst +++ b/doc/src/set.rst @@ -22,7 +22,7 @@ Syntax for style = *region*, ID = a region ID * one or more keyword/value pairs may be appended - + * keyword = *angle* or *angmom* or *bond* or *cc* or *charge* or *density* or *density/disc* or *diameter* or *dihedral* or *dipole* or *dipole/random* or *dpd/theta* or *edpd/cv* or *edpd/temp* or @@ -589,7 +589,7 @@ a density, e.g. via the :doc:`read_data ` command. .. versionchanged:: 28Mar2023 Support for type labels was added for setting atom 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, diff --git a/src/fix_set.cpp b/src/fix_set.cpp index f0f9a5cf50..5473cb35f5 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -65,9 +65,9 @@ int FixSet::setmask() void FixSet::end_of_step() { // select which atoms to act on - + set->selection(atom->nlocal); - + // loop over list of actions to reset atom attributes set->invoke_actions(); diff --git a/src/set.cpp b/src/set.cpp index 6f5022a66b..214ce3e405 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -187,7 +187,7 @@ void Set::process_args(int caller_flag, int narg, char **arg) while (iarg < narg) { // grow list of actions if needed - + if (naction == maxaction) { maxaction += DELTA; actions = (Action *) memory->srealloc(actions,maxaction*sizeof(Action),"set:actions"); @@ -199,7 +199,7 @@ void Set::process_args(int caller_flag, int narg, char **arg) action->argindex = iarg; action->varflag = 0; action->varflag1 = action->varflag2 = action->varflag3 = action->varflag4 = 0; - + if (strcmp(arg[iarg],"angle") == 0) { action->keyword = ANGLE; process_angle(iarg,narg,arg,action); @@ -388,13 +388,13 @@ void Set::process_args(int caller_flag, int narg, char **arg) action->keyword = Z; process_z(iarg,narg,arg,action); invoke_choice[naction++] = &Set::invoke_z; - + } else if (utils::strmatch(arg[iarg],"^[id]2?_")) { process_custom(iarg,narg,arg,action); invoke_choice[naction++] = &Set::invoke_custom; // unrecognized keyword - + } else error->all(FLERR,"Unrecognized set or fix set comand keyword {}",arg[iarg]); } @@ -411,10 +411,10 @@ void Set::process_args(int caller_flag, int narg, char **arg) if (action->varflag3) varflag3 = 1; if (action->varflag4) varflag4 = 1; } - + // error if any action of fix set command does not use a per-atom variable // b/c fix set is then effectivly a no-op - + if (caller == FIXSET) { for (int i = 0; i < naction; i++) { action = &actions[i]; @@ -426,7 +426,7 @@ void Set::process_args(int caller_flag, int narg, char **arg) // warn if a keyword sets properties for atoms in rigid bodies // assume no conflict for properties not in this list of cases - + for (int i = 0; i < naction; i++) { switch (actions[i].keyword) { case X: @@ -452,7 +452,7 @@ void Set::process_args(int caller_flag, int narg, char **arg) // in future, could return index to next arg to process // i.e. if fix set command appends its own options - + // return iarg; } @@ -465,7 +465,7 @@ void Set::selection(int n) { // reallocate select vector if needed // this method could be called many times by fix set command - + if (n > maxselect) { memory->destroy(select); memory->create(select,n,"set:select"); @@ -519,7 +519,7 @@ void Set::selection(int n) void Set::invoke_actions() { // reallocate per-atom variable storage if needed - + if (varflag && atom->nlocal > maxvariable) { maxvariable = atom->nlocal; if (varflag1) { @@ -541,7 +541,7 @@ void Set::invoke_actions() } // loop over actions - + for (int i = 0; i < naction; i++) { Action *action = &actions[i]; @@ -550,9 +550,9 @@ void Set::invoke_actions() // if stays -1, count_select is used by caller // if overwritten by an invoke method, count_action is used // only a handful of invoke methods tally their own count - + count_action = -1; - + // evaluate atom-style variable(s) if necessary if (action->varflag) { @@ -571,7 +571,7 @@ void Set::invoke_actions() } // invoke the action to reset per-atom or per-topology values - + (this->*invoke_choice[i])(action); action->count_select = count_select; @@ -620,8 +620,8 @@ void Set::setrandom(int keyword, Action *action) double **x = atom->x; // seed is always set to ivalue1 in process() methods - - int seed = action->ivalue1; + + int seed = action->ivalue1; auto ranpark = new RanPark(lmp,1); auto ranmars = new RanMars(lmp,seed + comm->me); @@ -633,7 +633,7 @@ void Set::setrandom(int keyword, Action *action) double fraction = action->dvalue1; int newtype = action->ivalue2; int count = 0; - + for (i = 0; i < nlocal; i++) if (select[i]) { ranpark->reset(seed,x[i]); @@ -641,7 +641,7 @@ void Set::setrandom(int keyword, Action *action) atom->type[i] = newtype; count++; } - + count_action = count; // set exact count of atom types to newtype @@ -680,7 +680,7 @@ void Set::setrandom(int keyword, Action *action) int count = 0; int eligible = 0; - + for (i = 0; i < nlocal; i++) { if (!select[i]) continue; if (flag[eligible]) { @@ -689,9 +689,9 @@ void Set::setrandom(int keyword, Action *action) } eligible++; } - + count_action = count; - + // clean up memory->destroy(flag); @@ -744,7 +744,7 @@ void Set::setrandom(int keyword, Action *action) int nlocal = atom->nlocal; double dlen = action->dvalue1; double sp_sq,scale; - + if (domain->dimension == 3) { for (i = 0; i < nlocal; i++) if (select[i]) { @@ -785,7 +785,7 @@ void Set::setrandom(int keyword, Action *action) int nlocal = atom->nlocal; int quat_flag = atom->quat_flag; double *quat_one; - + if (domain->dimension == 3) { double s,t1,t2,theta1,theta2; for (i = 0; i < nlocal; i++) @@ -887,7 +887,7 @@ void Set::topology(int keyword, Action *action) selection(atom->nlocal + atom->nghost); int count = 0; - + // for BOND, each of 2 atoms must be in group if (keyword == BOND) { @@ -895,7 +895,7 @@ void Set::topology(int keyword, Action *action) int **bond_type = atom->bond_type; tagint **bond_atom = atom->bond_atom; int nlocal = atom->nlocal; - + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) for (m = 0; m < num_bond[i]; m++) { @@ -910,14 +910,14 @@ void Set::topology(int keyword, Action *action) // for ANGLE, each of 3 atoms must be in group - if (keyword == ANGLE) { + if (keyword == ANGLE) { int *num_angle = atom->num_angle; int **angle_type = atom->angle_type; tagint **angle_atom1 = atom->angle_atom1; tagint **angle_atom2 = atom->angle_atom2; tagint **angle_atom3 = atom->angle_atom3; int nlocal = atom->nlocal; - + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) for (m = 0; m < num_angle[i]; m++) { @@ -943,7 +943,7 @@ void Set::topology(int keyword, Action *action) tagint **dihedral_atom3 = atom->dihedral_atom3; tagint **dihedral_atom4 = atom->dihedral_atom4; int nlocal = atom->nlocal; - + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) for (m = 0; m < num_dihedral[i]; m++) { @@ -970,7 +970,7 @@ void Set::topology(int keyword, Action *action) tagint **improper_atom3 = atom->improper_atom3; tagint **improper_atom4 = atom->improper_atom4; int nlocal = atom->nlocal; - + int itype = action->ivalue1; for (int i = 0; i < nlocal; i++) for (m = 0; m < num_improper[i]; m++) { @@ -1025,14 +1025,14 @@ void Set::process_angmom(int &iarg, int narg, char **arg, Action *action) if (!atom->angmom_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set angmom", error); - + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - + iarg += 4; } @@ -1046,16 +1046,16 @@ void Set::invoke_angmom(Action *action) if (!action->varflag1) xvalue = action->dvalue1; if (!action->varflag2) yvalue = action->dvalue2; if (!action->varflag3) zvalue = action->dvalue3; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - + if (varflag) { if (action->varflag1) xvalue = vec1[i]; if (action->varflag1) yvalue = vec2[i]; if (action->varflag1) zvalue = vec3[i]; } - + angmom[i][0] = xvalue; angmom[i][1] = yvalue; angmom[i][2] = zvalue; @@ -1075,7 +1075,7 @@ void Set::process_bond(int &iarg, int narg, char **arg, Action *action) delete[] typestr; if (action->ivalue1 <= 0 || action->ivalue1 > atom->nbondtypes) error->all(FLERR,"Invalid bond type in set command"); - + iarg += 2; } @@ -1111,7 +1111,7 @@ void Set::invoke_cc(Action *action) int cc_index = action->ivalue1 - 1; // NOTE: need to check if cc_index exceeds cc array allocation - + int varflag = action->varflag; double ccvalue; if (!action->varflag1) ccvalue = action->dvalue1; @@ -1123,7 +1123,7 @@ void Set::invoke_cc(Action *action) ccvalue = vec1[i]; if (ccvalue < 0.0) error->all(FLERR,"Invalid cc value in set command"); } - + cc[i][cc_index] = ccvalue; } } @@ -1148,7 +1148,7 @@ void Set::invoke_charge(Action *action) double *q = atom->q; double *q_scaled = atom->q_scaled; double *epsilon = atom->epsilon; - + int varflag = action->varflag; double qvalue; if (!action->varflag1) qvalue = action->dvalue1; @@ -1178,13 +1178,13 @@ void Set::process_density(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid density in set command"); } - + action->ivalue1 = 0; if (strcmp(arg[iarg],"density/disc") == 0) { action->ivalue1 = 1; if (domain->dimension != 2) error->all(FLERR,"Set density/disc requires 2d simulation"); } - + iarg += 2; } @@ -1210,7 +1210,7 @@ void Set::invoke_density(Action *action) double density; if (!action->varflag1) density = action->dvalue1; int discflag = action->ivalue1; - + // set rmass via density // if radius > 0.0, treat as sphere or disc // if shape > 0.0, treat as ellipsoid (or ellipse, when uncomment below) @@ -1225,11 +1225,11 @@ void Set::invoke_density(Action *action) density = vec1[i]; if (density <= 0.0) error->one(FLERR,"Invalid density in set command"); } - + if (radius_flag && radius[i] > 0.0) if (discflag) rmass[i] = MY_PI*radius[i]*radius[i] * density; else rmass[i] = 4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i] * density; - + else if (ellipsoid_flag && ellipsoid[i] >= 0) { double *shape = avec_ellipsoid->bonus[ellipsoid[i]].shape; // could enable 2d ellipse (versus 3d ellipsoid) when time integration @@ -1238,11 +1238,11 @@ void Set::invoke_density(Action *action) // atom->rmass[i] = MY_PI*shape[0]*shape[1] * dvalue; // else rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * density; - + } else if (line_flag && line[i] >= 0) { double length = avec_line->bonus[line[i]].length; rmass[i] = length * density; - + } else if (tri_flag && tri[i] >= 0) { double *c1 = avec_tri->bonus[tri[i]].c1; double *c2 = avec_tri->bonus[tri[i]].c2; @@ -1254,7 +1254,7 @@ void Set::invoke_density(Action *action) MathExtra::cross3(c2mc1,c3mc1,norm); double area = 0.5 * MathExtra::len3(norm); rmass[i] = area * density; - + } else rmass[i] = density; } } @@ -1272,7 +1272,7 @@ void Set::process_diameter(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid diameter in set command"); } - + iarg += 2; } @@ -1280,7 +1280,7 @@ void Set::invoke_diameter(Action *action) { int nlocal = atom->nlocal; double *radius = atom->radius; - + int varflag = action->varflag; double diam; if (!action->varflag1) diam = action->dvalue1; @@ -1292,7 +1292,7 @@ void Set::invoke_diameter(Action *action) diam = vec1[i]; if (diam < 0.0) error->one(FLERR,"Invalid diameter in set command"); } - + radius[i] = 0.5 * diam; } } @@ -1310,7 +1310,7 @@ void Set::process_dihedral(int &iarg, int narg, char **arg, Action *action) delete[] typestr; if (action->ivalue1 <= 0 || action->ivalue1 > atom->ndihedraltypes) error->all(FLERR,"Invalid dihedral type in set command"); - + iarg += 2; } @@ -1333,7 +1333,7 @@ void Set::process_dipole(int &iarg, int narg, char **arg, Action *action) else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - + iarg += 4; } @@ -1347,7 +1347,7 @@ void Set::invoke_dipole(Action *action) if (!action->varflag1) xvalue = action->dvalue1; if (!action->varflag2) yvalue = action->dvalue2; if (!action->varflag3) zvalue = action->dvalue3; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1356,7 +1356,7 @@ void Set::invoke_dipole(Action *action) if (action->varflag1) yvalue = vec2[i]; if (action->varflag1) zvalue = vec3[i]; } - + mu[i][0] = xvalue; mu[i][1] = yvalue; mu[i][2] = zvalue; @@ -1371,14 +1371,14 @@ void Set::process_dipole_random(int &iarg, int narg, char **arg, Action *action) if (!atom->mu_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "set dipole/random", error); - + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid dipole length in set command"); - + iarg += 3; } @@ -1394,14 +1394,14 @@ void Set::process_dpd_theta(int &iarg, int narg, char **arg, Action *action) if (!atom->dpd_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set dpd/theta", error); - + if (strcmp(arg[iarg+1],"NULL") == 0) action->dvalue1 = -1.0; else if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid dpd/theta value in set command"); } - + iarg += 2; } @@ -1413,7 +1413,7 @@ void Set::invoke_dpd_theta(Action *action) double *mass = atom->mass; double *rmass = atom->rmass; double *dpdTheta = atom->dpdTheta; - + double tfactor = force->mvv2e / (domain->dimension * force->boltz); double onemass; double vx,vy,vz; @@ -1431,7 +1431,7 @@ void Set::invoke_dpd_theta(Action *action) } // if theta is negative, NULL was used, set dpdTheta to KE of particle - + if (theta >= 0.0) dpdTheta[i] = theta; else { if (rmass) onemass = rmass[i]; @@ -1457,7 +1457,7 @@ void Set::process_edpd_cv(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->all(FLERR,"Invalid edpd/cv value in set command"); } - + iarg += 2; } @@ -1465,7 +1465,7 @@ void Set::invoke_edpd_cv(Action *action) { int nlocal = atom->nlocal; double *edpd_cv = atom->edpd_cv; - + int varflag = action->varflag; double cv; if (!action->varflag1) cv = action->dvalue1; @@ -1532,7 +1532,7 @@ void Set::process_epsilon(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid epsilon in set command"); } - + iarg += 2; } @@ -1557,7 +1557,7 @@ void Set::invoke_epsilon(Action *action) eps = vec1[i]; if (eps <= 0.0) error->one(FLERR,"Invalid epsilon in set command"); } - + epsilon[i] = eps; q_scaled[i] = q[i] / eps; } @@ -1568,7 +1568,7 @@ void Set::invoke_epsilon(Action *action) void Set::process_image(int &iarg, int narg, char **arg, Action *action) { if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set image", error); - + if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue4 = 0; else { action->ivalue4 = 1; @@ -1582,7 +1582,7 @@ void Set::process_image(int &iarg, int narg, char **arg, Action *action) error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); } } - + if (strcmp(arg[iarg+2],"NULL") == 0) action->ivalue5 = 0; else { action->ivalue5 = 1; @@ -1596,7 +1596,7 @@ void Set::process_image(int &iarg, int narg, char **arg, Action *action) error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); } } - + if (strcmp(arg[iarg+1],"NULL") == 0) action->ivalue6 = 0; else { action->ivalue6 = 1; @@ -1610,7 +1610,7 @@ void Set::process_image(int &iarg, int narg, char **arg, Action *action) error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension"); } } - + iarg += 4; } @@ -1623,7 +1623,7 @@ void Set::invoke_image(Action *action) int ximageflag = action->ivalue4; int yimageflag = action->ivalue5; int zimageflag = action->ivalue6; - + int varflag = action->varflag; int ximage,yimage,zimage; if (!action->varflag1) ximage = action->ivalue1; @@ -1640,7 +1640,7 @@ void Set::invoke_image(Action *action) if (action->varflag2) yimage = static_cast (vec2[i]); if (action->varflag3) zimage = static_cast (vec3[i]); } - + xbox = (image[i] & IMGMASK) - IMGMAX; ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; zbox = (image[i] >> IMG2BITS) - IMGMAX; @@ -1666,7 +1666,7 @@ void Set::process_improper(int &iarg, int narg, char **arg, Action *action) delete[] typestr; if (action->ivalue1 <= 0 || action->ivalue1 > atom->nimpropertypes) error->all(FLERR,"Invalid value in set command"); - + iarg += 2; } @@ -1688,7 +1688,7 @@ void Set::process_length(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid length in set command"); } - + iarg += 2; } @@ -1731,7 +1731,7 @@ void Set::process_mass(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid mass in set command"); } - + iarg += 2; } @@ -1751,7 +1751,7 @@ void Set::invoke_mass(Action *action) mass_one = vec1[i]; if (mass_one < 0.0) error->one(FLERR,"Invalid mass in set command"); } - + rmass[i] = mass_one; } } @@ -1769,10 +1769,10 @@ void Set::process_mol(int &iarg, int narg, char **arg, Action *action) action->tvalue1 = utils::tnumeric(FLERR,arg[iarg+1],false,lmp); if (action->tvalue1 < 0) error->one(FLERR,"Invalid molecule ID in set command"); } - + iarg += 2; } - + void Set::invoke_mol(Action *action) { int nlocal = atom->nlocal; @@ -1781,7 +1781,7 @@ void Set::invoke_mol(Action *action) int varflag = action->varflag; tagint molID; if (!action->varflag1) molID = action->tvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -1789,7 +1789,7 @@ void Set::invoke_mol(Action *action) molID = vec1[i]; if (molID < 0) error->one(FLERR,"Invalid molecule ID in set command"); } - + molecule[i] = molID; } } @@ -1808,7 +1808,7 @@ void Set::process_omega(int &iarg, int narg, char **arg, Action *action) else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); - + iarg += 4; } @@ -1863,7 +1863,7 @@ void Set::process_quat(int &iarg, int narg, char **arg, Action *action) else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4,action); else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); - + iarg += 5; } @@ -1875,7 +1875,7 @@ void Set::invoke_quat(Action *action) int *body = atom->body; double **quat = atom->quat; int quat_flag = atom->quat_flag; - + auto avec_ellipsoid = dynamic_cast(atom->style_match("ellipsoid")); auto avec_tri = dynamic_cast(atom->style_match("tri")); auto avec_body = dynamic_cast(atom->style_match("body")); @@ -1883,7 +1883,7 @@ void Set::invoke_quat(Action *action) int dimension = domain->dimension; double radians,sintheta; double *quat_one; - + int varflag = action->varflag; double xvalue,yvalue,zvalue,theta; if (!action->varflag1) xvalue = action->dvalue1; @@ -1934,7 +1934,7 @@ void Set::process_quat_random(int &iarg, int narg, char **arg, Action *action) action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - + iarg += 2; } @@ -1967,7 +1967,7 @@ void Set::invoke_radius_election(Action *action) { int nlocal = atom->nlocal; double *eradius = atom->eradius; - + int varflag = action->varflag; double radius; if (!action->varflag1) radius = action->dvalue1; @@ -2036,10 +2036,10 @@ void Set::invoke_shape(Action *action) if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0) error->one(FLERR,"Invalid shape in set command"); - + avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); } - + // update global ellipsoid count bigint nlocal_bonus = avec_ellipsoid->nlocal_bonus; @@ -2072,7 +2072,7 @@ void Set::invoke_smd_contact_radius(Action *action) double radius; if (!action->varflag1) radius = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -2098,7 +2098,7 @@ void Set::process_smd_mass_density(int &iarg, int narg, char **arg, Action *acti action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 <= 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); } - + iarg += 2; } @@ -2107,11 +2107,11 @@ void Set::invoke_smd_mass_density(Action *action) int nlocal = atom->nlocal; double *rmass = atom->rmass; double *vfrac = atom->vfrac; - + int varflag = action->varflag; double density; if (!action->varflag1) density = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -2119,7 +2119,7 @@ void Set::invoke_smd_mass_density(Action *action) density = vec1[i]; if (density < 0.0) error->one(FLERR,"Invalid smd/mass/density in set command"); } - + rmass[i] = vfrac[i] * density; } } @@ -2134,7 +2134,7 @@ void Set::process_sph_cv(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2142,11 +2142,11 @@ void Set::invoke_sph_cv(Action *action) { int nlocal = atom->nlocal; double *cv = atom->cv; - + int varflag = action->varflag; double sph_cv; if (!action->varflag1) sph_cv = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) sph_cv = vec1[i]; @@ -2164,7 +2164,7 @@ void Set::process_sph_e(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2172,11 +2172,11 @@ void Set::invoke_sph_e(Action *action) { int nlocal = atom->nlocal; double *esph = atom->esph; - + int varflag = action->varflag; double sph_e; if (!action->varflag1) sph_e = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) sph_e = vec1[i]; @@ -2206,7 +2206,7 @@ void Set::invoke_sph_rho(Action *action) int varflag = action->varflag; double sph_rho; if (!action->varflag1) sph_rho = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) sph_rho = vec1[i]; @@ -2230,14 +2230,14 @@ void Set::process_spin_atom(int &iarg, int narg, char **arg, Action *action) if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid spin magnitude {} in set command"); } - + if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); else action->dvalue2 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (utils::strmatch(arg[iarg+3],"^v_")) varparse(arg[iarg+3],3,action); else action->dvalue3 = utils::numeric(FLERR,arg[iarg+3],false,lmp); if (utils::strmatch(arg[iarg+4],"^v_")) varparse(arg[iarg+4],4,action); else action->dvalue4 = utils::numeric(FLERR,arg[iarg+4],false,lmp); - + iarg += 5; } @@ -2319,7 +2319,7 @@ void Set::process_spin_electron(int &iarg, int narg, char **arg, Action *action) if (action->ivalue1 < -1 || action->ivalue1 > 3) error->one(FLERR,"Invalid electron spin {} in set command", action->ivalue1); } - + iarg += 2; } @@ -2327,11 +2327,11 @@ void Set::invoke_spin_electron(Action *action) { int nlocal = atom->nlocal; int *spin = atom->spin; - + int varflag = action->varflag; int ispin; if (!action->varflag1) ispin = action->ivalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; @@ -2340,7 +2340,7 @@ void Set::invoke_spin_electron(Action *action) if (ispin < -1 || ispin > 3) error->one(FLERR,"Invalid electron spin in set command"); } - + atom->spin[i] = ispin; } } @@ -2366,7 +2366,7 @@ void Set::invoke_temperature(Action *action) { int nlocal = atom->nlocal; double *temperature = atom->temperature; - + int varflag = action->varflag; double temp; if (!action->varflag1) temp = action->dvalue1; @@ -2378,7 +2378,7 @@ void Set::invoke_temperature(Action *action) temp = vec1[i]; if (temp < 0.0) error->one(FLERR,"Invalid temperature in set command"); } - + temperature[i] = temp; } } @@ -2393,7 +2393,7 @@ void Set::process_theta(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = DEG2RAD * utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2407,7 +2407,7 @@ void Set::invoke_theta(Action *action) int varflag = action->varflag; double theta; if (!action->varflag1) theta = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (line[i] < 0) error->one(FLERR,"Cannot set theta for atom which is not a line"); @@ -2423,10 +2423,10 @@ void Set::process_theta_random(int &iarg, int narg, char **arg, Action *action) if (!atom->line_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set theta/random", error); - + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - + iarg += 2; } @@ -2442,13 +2442,13 @@ void Set::process_tri(int &iarg, int narg, char **arg, Action *action) if (!atom->tri_flag) error->all(FLERR,"Cannot set attribute {} for atom style {}", arg[iarg], atom->get_style()); if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set tri", error); - + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 < 0.0) error->one(FLERR,"Invalid tri size in set command"); } - + iarg += 2; } @@ -2456,13 +2456,13 @@ void Set::invoke_tri(Action *action) { int nlocal = atom->nlocal; int *tri = atom->tri; - + auto avec_tri = dynamic_cast(atom->style_match("tri")); int varflag = action->varflag; double trisize; if (!action->varflag1) trisize = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; #if 0 @@ -2474,7 +2474,7 @@ void Set::invoke_tri(Action *action) trisize = vec1[i]; if (trisize < 0.0) error->one(FLERR,"Invalid tri size in set command"); } - + avec_tri->set_equilateral(i,trisize); } @@ -2489,7 +2489,7 @@ void Set::invoke_tri(Action *action) void Set::process_type(int &iarg, int narg, char **arg, Action *action) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "set type", error); - + if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else { char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); @@ -2498,7 +2498,7 @@ void Set::process_type(int &iarg, int narg, char **arg, Action *action) if (action->ivalue1 <= 0 || action->ivalue1 > atom->ntypes) error->one(FLERR,"Invalid atom type in set command"); } - + iarg += 2; } @@ -2510,16 +2510,16 @@ void Set::invoke_type(Action *action) int varflag = action->varflag; int itype; if (!action->varflag1) itype = action->ivalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - + if (action->varflag) { itype = static_cast (vec1[i]); if (itype <= 0 || itype > atom->ntypes) error->one(FLERR,"Invalid atom type in set command"); } - + type[i] = itype; } } @@ -2531,7 +2531,7 @@ void Set::process_type_fraction(int &iarg, int narg, char **arg, Action *action) if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "set type/fraction", error); // random seed must be ivalue1 for use in setrandom() - + char *typestr = utils::expand_type(FLERR,arg[iarg+1],Atom::ATOM,lmp); action->ivalue2 = utils::inumeric(FLERR,typestr?typestr:arg[iarg+1],false,lmp); delete[] typestr; @@ -2541,11 +2541,11 @@ void Set::process_type_fraction(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) error->all(FLERR,"Invalid fraction in set command"); - + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - + iarg += 4; } @@ -2567,15 +2567,15 @@ void Set::process_type_ratio(int &iarg, int narg, char **arg, Action *action) delete[] typestr; if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) error->all(FLERR,"Invalid atom type in set command"); - + action->dvalue1 = utils::numeric(FLERR,arg[iarg+2],false,lmp); if (action->dvalue1 < 0.0 || action->dvalue1 > 1.0) error->all(FLERR,"Invalid fraction in set command"); - + action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - + iarg += 4; } @@ -2597,7 +2597,7 @@ void Set::process_type_subset(int &iarg, int narg, char **arg, Action *action) delete[] typestr; if (action->ivalue2 <= 0 || action->ivalue2 > atom->ntypes) error->all(FLERR,"Invalid atom type in set command"); - + action->bvalue1 = utils::bnumeric(FLERR,arg[iarg+2],false,lmp); if (action->bvalue1 < 0) error->all(FLERR,"Invalid subset size in set command"); @@ -2605,7 +2605,7 @@ void Set::process_type_subset(int &iarg, int narg, char **arg, Action *action) action->ivalue1 = utils::inumeric(FLERR,arg[iarg+3],false,lmp); if (action->ivalue1 <= 0) error->all(FLERR,"Invalid random number seed in set command"); - + iarg += 4; } @@ -2627,7 +2627,7 @@ void Set::process_volume(int &iarg, int narg, char **arg, Action *action) action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 <= 0.0) error->all(FLERR,"Invalid volume in set command"); } - + iarg += 2; } @@ -2635,19 +2635,19 @@ void Set::invoke_volume(Action *action) { int nlocal = atom->nlocal; double *vfrac = atom->vfrac; - + int varflag = action->varflag; double vol; if (!action->varflag1) vol = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; - + if (varflag) { vol = vec1[i]; if (vol < 0.0) error->one(FLERR,"Invalid volume in set command"); } - + vfrac[i] = vol; } } @@ -2660,7 +2660,7 @@ void Set::process_vx(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2668,7 +2668,7 @@ void Set::invoke_vx(Action *action) { int nlocal = atom->nlocal; double **v = atom->v; - + int varflag = action->varflag; double vx; if (!action->varflag1) vx = action->dvalue1; @@ -2688,7 +2688,7 @@ void Set::process_vy(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2696,11 +2696,11 @@ void Set::invoke_vy(Action *action) { int nlocal = atom->nlocal; double **v = atom->v; - + int varflag = action->varflag; double vy; if (!action->varflag1) vy = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) vy = vec1[i]; @@ -2716,7 +2716,7 @@ void Set::process_vz(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2724,11 +2724,11 @@ void Set::invoke_vz(Action *action) { int nlocal = atom->nlocal; double **v = atom->v; - + int varflag = action->varflag; double vz; if (!action->varflag1) vz = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) vz = vec1[i]; @@ -2744,7 +2744,7 @@ void Set::process_x(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2752,11 +2752,11 @@ void Set::invoke_x(Action *action) { int nlocal = atom->nlocal; double **x = atom->x; - + int varflag = action->varflag; double coord; if (!action->varflag1) coord = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) coord = vec1[i]; @@ -2772,7 +2772,7 @@ void Set::process_y(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2780,11 +2780,11 @@ void Set::invoke_y(Action *action) { int nlocal = atom->nlocal; double **x = atom->x; - + int varflag = action->varflag; double coord; if (!action->varflag1) coord = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) coord = vec1[i]; @@ -2800,7 +2800,7 @@ void Set::process_z(int &iarg, int narg, char **arg, Action *action) if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + iarg += 2; } @@ -2808,11 +2808,11 @@ void Set::invoke_z(Action *action) { int nlocal = atom->nlocal; double **x = atom->x; - + int varflag = action->varflag; double coord; if (!action->varflag1) coord = action->dvalue1; - + for (int i = 0; i < nlocal; i++) { if (!select[i]) continue; if (varflag) coord = vec1[i]; @@ -2840,7 +2840,7 @@ void Set::process_custom(int &iarg, int narg, char **arg, Action *action) if (flag != 0) error->all(FLERR,"Set command custom property {} is not integer",pname); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->ivalue1 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - + if (argi.get_dim() == 0) { if (cols > 0) error->all(FLERR,"Set command custom integer property {} is not a vector",pname); @@ -2861,7 +2861,7 @@ void Set::process_custom(int &iarg, int narg, char **arg, Action *action) if (flag != 1) error->all(FLERR,"Custom property {} is not floating-point",argi.get_name()); if (utils::strmatch(arg[iarg+1],"^v_")) varparse(arg[iarg+1],1,action); else action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); - + if (argi.get_dim() == 0) { if (cols > 0) error->all(FLERR,"Set command custom double property {} is not a vector",pname); @@ -2882,7 +2882,7 @@ void Set::process_custom(int &iarg, int narg, char **arg, Action *action) error->all(FLERR,"Illegal set command"); break; } - + iarg += 2; } @@ -2891,10 +2891,10 @@ void Set::invoke_custom(Action *action) int nlocal = atom->nlocal; int ivalue; double dvalue; - + int varflag = action->varflag; int index_custom = action->ivalue2; - + if (action->keyword == IVEC) { if (!varflag) ivalue = action->ivalue1; int *ivector = atom->ivector[index_custom]; @@ -2903,7 +2903,7 @@ void Set::invoke_custom(Action *action) if (varflag) ivalue = static_cast (vec1[i]); ivector[i] = ivalue; } - + } else if (action->keyword == DVEC) { if (!varflag) dvalue = action->dvalue1; double *dvector = atom->dvector[index_custom]; @@ -2912,7 +2912,7 @@ void Set::invoke_custom(Action *action) if (varflag) dvalue = vec1[i]; dvector[i] = dvalue; } - + } else if (action->keyword == IARRAY) { if (!varflag) ivalue = action->ivalue1; int **iarray = atom->iarray[index_custom]; @@ -2922,7 +2922,7 @@ void Set::invoke_custom(Action *action) if (varflag) ivalue = static_cast (vec1[i]); iarray[i][icol_custom] = ivalue; } - + } else if (action->keyword == DARRAY) { if (!varflag) dvalue = action->dvalue1; double **darray = atom->darray[index_custom]; From 9442218b3664d759ef6bcf8c47ebd55cf61ea2a0 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 02:18:45 -0400 Subject: [PATCH 15/26] spelling --- doc/src/set.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/set.rst b/doc/src/set.rst index 9d86f766a4..aecd2d2cb5 100644 --- a/doc/src/set.rst +++ b/doc/src/set.rst @@ -534,7 +534,7 @@ using SPH in LAMMPS. .. note:: - Noote that the SPH PDF guide file has not been updated for many + Note that the SPH PDF guide file has not been updated for many years and thus does not reflect the current *syntax* of the SPH package commands. For that, please refer to the LAMMPS manual. From 6030c68ba3f737898c026dead0a646eab0ae3630 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 02:17:54 -0400 Subject: [PATCH 16/26] correct reference --- doc/src/pair_lj_pirani.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/pair_lj_pirani.rst b/doc/src/pair_lj_pirani.rst index c7f2703c01..822d277a1b 100644 --- a/doc/src/pair_lj_pirani.rst +++ b/doc/src/pair_lj_pirani.rst @@ -74,7 +74,7 @@ electrostatic interactions. If these are desired, this pair style should be used along with a Coulomb pair style like :doc:`pair styles coul/cut or coul/long ` by using :doc:`pair style hybrid/overlay ` and a suitable -kspace style :doc:``, if needed. +:doc:`kspace style `, if needed. As discussed in :ref:`(Pirani) `, analysis of a variety of systems showed that :math:`\alpha= 4` generally works very well. In From d89ae3d15da61818099cede3228e36f47429e889 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 02:28:43 -0400 Subject: [PATCH 17/26] fix 64-bit integer compilation issue --- src/set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/set.cpp b/src/set.cpp index 214ce3e405..b8cd2a710e 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -1776,7 +1776,7 @@ void Set::process_mol(int &iarg, int narg, char **arg, Action *action) void Set::invoke_mol(Action *action) { int nlocal = atom->nlocal; - int *molecule = atom->molecule; + tagint *molecule = atom->molecule; int varflag = action->varflag; tagint molID; From f8bf6d1ad6de020c30b17a794cfecd702901e10e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 26 Apr 2025 02:42:09 -0400 Subject: [PATCH 18/26] correct a few more issues with unit tests --- src/set.cpp | 4 ++-- unittest/commands/test_set_property.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/set.cpp b/src/set.cpp index b8cd2a710e..951655879a 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -395,7 +395,7 @@ void Set::process_args(int caller_flag, int narg, char **arg) // unrecognized keyword - } else error->all(FLERR,"Unrecognized set or fix set comand keyword {}",arg[iarg]); + } else error->all(FLERR,"Unrecognized set or fix set command keyword {}",arg[iarg]); } // varflag = 1 if any action uses a per-atom variable @@ -2228,7 +2228,7 @@ void Set::process_spin_atom(int &iarg, int narg, char **arg, Action *action) else { action->dvalue1 = utils::numeric(FLERR,arg[iarg+1],false,lmp); if (action->dvalue1 <= 0.0) - error->all(FLERR,"Invalid spin magnitude {} in set command"); + error->all(FLERR,"Invalid spin magnitude {} in set {} command", action->dvalue1, arg[iarg]); } if (utils::strmatch(arg[iarg+2],"^v_")) varparse(arg[iarg+2],2,action); diff --git a/unittest/commands/test_set_property.cpp b/unittest/commands/test_set_property.cpp index 7944e36222..26635d225f 100644 --- a/unittest/commands/test_set_property.cpp +++ b/unittest/commands/test_set_property.cpp @@ -92,7 +92,7 @@ TEST_F(SetTest, NoBoxNoAtoms) TEST_FAILURE(".*ERROR: Illegal set command: need at least four.*", command("set type 1 x");); TEST_FAILURE(".*ERROR: Unknown set or fix set command style: xxx.*", command("set xxx 1 x 0.0");); - TEST_FAILURE(".*ERROR: Unrecognized set or fix set keyword yyy.*", + TEST_FAILURE(".*ERROR: Unrecognized set or fix set command keyword yyy.*", command("set type 1 yyy 0.0");); TEST_FAILURE(".*ERROR: Cannot set attribute spin/atom for atom style atomic.*", From 79f6867d7e77e4c57815615d5150d42aee0056e5 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Fri, 2 May 2025 16:13:01 -0600 Subject: [PATCH 19/26] new doc page for fix set command with example --- doc/src/fix.rst | 1 + doc/src/fix_set.rst | 154 ++++++++++++++++++++++++++++++++++++++++++++ doc/src/set.rst | 6 +- src/fix_set.cpp | 12 +++- src/set.cpp | 2 + 5 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 doc/src/fix_set.rst diff --git a/doc/src/fix.rst b/doc/src/fix.rst index 3b1bc4a75c..22996a327a 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -395,6 +395,7 @@ accelerated styles exist. * :doc:`rigid/small ` - constrain many small clusters of atoms to move as a rigid body with NVE integration * :doc:`rx ` - solve reaction kinetic ODEs for a defined reaction set * :doc:`saed/vtk ` - time-average the intensities from :doc:`compute saed ` +* :doc:`set ` - reset an atom property via an atom-style variable every N steps * :doc:`setforce ` - set the force on each atom * :doc:`setforce/spin ` - set magnetic precession vectors on each atom * :doc:`sgcmc ` - fix for hybrid semi-grand canonical MD/MC simulations diff --git a/doc/src/fix_set.rst b/doc/src/fix_set.rst new file mode 100644 index 0000000000..0f1cf7fcb0 --- /dev/null +++ b/doc/src/fix_set.rst @@ -0,0 +1,154 @@ +.. index:: fix set + +fix set command +=============== + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID set Nfreq set-args + +* ID, group-ID are documented in :doc:`fix ` command +* set = style name of this fix command +* Nfreq = reset per-atom properties every this many timesteps +* set-args = identical to args for the :doc:`set ` command + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 10 all set 1 group all i_dump v_new + fix 10 all set 1 group all i_dump v_turnoff + +Description +""""""""""" + +Reset one or more properties of one or more atoms once every *Nfreq* +stepes during a simulation. + +The args following *Nfreq* are identical to those allowed for the +:doc:`set ` command, as in the examples above and below. + +Note that the group-ID setting for this command is ignored. The +syntax for the :doc:`set ` command allows selection of which +atoms have their properties reset. + +This command can only be used to reset an atom property using a +per-atom variable. This option in allowed by many, but not all, of +the keyword/value pairs supported by the :doc:`set ` command. +The reason for this restriction is that if a per-atom variable is not +used, this command will typically not change atom properties during +the simulation. + +The :doc:`set ` command can be used with similar syntax to this +command to reset atom properties once before or between simulations. + +---------- + +Here is an example of input script commands which will output atoms +into a dump file only when their x-velocity crosses a threshold value +*vthresh* for the first time. Their position and x-velocity will then +be output every step for *twindow* timesteps. + +.. code-block:: LAMMPS + + variable vthresh equal 2 # threshold velocity + variable twindow equal 10 # dump for this many steps + # + # define custom property i_dump to store timestep threshold is crossed + # + fix 2 all property/atom i_dump + set group all i_dump -1 + # + # fix set command checks for threshold crossings every step + # resets i_dump from -1 to current timestep when crossing occurs + # + variable start atom "vx > v_vthresh && i_dump == -1" + variable new atom ternary(v_start,step,i_dump) + fix 3 all set 1 group all i_dump v_new + # + # dump command with thresh which enforces twindow + # + dump 1 all custom 1 tmp.dump id x y vx i_dump + variable dumpflag atom "i_dump >= 0 && (step-i_dump) < v_twindow" + dump_modify 1 thresh v_dumpflag == 1 + # + # run the simulation + # final dump with all atom IDs which crossed threshold on which timestep + # + run 1000 + write_dump all custom tmp.dump.final id i_dump modify thresh i_dump >= 0 + +The tmp.dump.final file lists which atoms crossed the velocity +threshold. This command will print the *twindow* timesteps when a +specific atom ID (104 in this case) was output in the tmp.dump file: + +.. code-block:: LAMMPS + + % grep "^104 " tmp.dump + +If these commands are used instead of the above, then an atom can +cross the velocity threshold multiple times, and will be output for +*twindow* timesteps each time. However the write_dump command is no +longer useful. + +.. code-block:: LAMMPS + + variable vthresh equal 2 # threshold velocity + variable twindow equal 10 # dump for this many steps + # + # define custom property i_dump to store timestep threshold is crossed + # + fix 2 all property/atom i_dump + set group all i_dump -1 + # + # fix set command checks for threshold crossings every step + # resets i_dump from -1 to current timestep when crossing occurs + # + variable start atom "vx > v_vthresh && i_dump == -1" + variable turnon atom ternary(v_start,step,i_dump) + variable stop atom "v_turnon >= 0 && (step-v_turnon) < v_twindow" + variable turnoff atom ternary(v_stop,v_turnon,-1) + fix 3 all set 1 group all i_dump v_turnoff + # + # dump command with thresh which enforces twindow + # + dump 1 all custom 1 tmp.dump id x y vx i_dump + variable dumpflag atom "i_dump >= 0 && (step-i_dump) < v_twindow" + dump_modify 1 thresh v_dumpflag == 1 + # + # run the simulation + # + run 1000 + +---------- + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files +`. None of the :doc:`fix_modify ` options are +relevant to this fix. No global or per-atom quantities are stored by +this fix for access by various :doc:`output commands `. +No parameter of this fix can be used with the *start/stop* keywords of +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. + +Restrictions +"""""""""""" + +As noted above, + + +Related commands +"""""""""""""""" + +:doc:`set ` + +Default +""""""" + +none diff --git a/doc/src/set.rst b/doc/src/set.rst index aecd2d2cb5..d2c865dfbb 100644 --- a/doc/src/set.rst +++ b/doc/src/set.rst @@ -200,6 +200,10 @@ their properties reset. The remaining keywords specify which properties to reset and what the new values are. Some strings like *type* or *mol* can be used as a style and/or a keyword. +The :doc:`fix set ` command can be used with similar syntax +to this command to reset atom properties once every *N* steps during a +simulation using via atom-style variables. + ---------- This section describes how to select which atoms to change @@ -658,7 +662,7 @@ Related commands """""""""""""""" :doc:`create_box `, :doc:`create_atoms `, -:doc:`read_data ` +:doc:`read_data `, :doc:`fix set ` Default """"""" diff --git a/src/fix_set.cpp b/src/fix_set.cpp index 5473cb35f5..a1b8a45655 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -37,8 +37,16 @@ FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) // pass remaining args to Set class // only keywords which use per-atom variables are currently allowed - + // NOTE: could also allow when set style = region, since atoms may move in/out of regions + set->process_args(FIXSET,narg-4,&arg[4]); + + // NOTE: not sure if either of these options for fix set are needed or could be problematic + // could add ghost yes keyword/value to trigger + // ghost comm, e.g. if atom types are reset + // this could require an extract() method in Set to query what value(s) to comm + // could add reneigh yes keyword/value to trigger + // full reneighbor on next step, e.g. if xyz coords are reset } /* ---------------------------------------------------------------------- */ @@ -59,7 +67,7 @@ int FixSet::setmask() /* ---------------------------------------------------------------------- use the Set instance to update per-atom properties - NOTE: could return count of updated atoms from Set and use it as a fix output + NOTE: could return count of updated atoms from Set for use as fix output ---------------------------------------------------------------------- */ void FixSet::end_of_step() diff --git a/src/set.cpp b/src/set.cpp index 951655879a..d07b1e4e2c 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -999,6 +999,8 @@ void Set::topology(int keyword, Action *action) // separate two operations so can be called by either set or fix set command // ---------------------------------------------------------------------- +/* ---------------------------------------------------------------------- */ + void Set::process_angle(int &iarg, int narg, char **arg, Action *action) { if (atom->avec->angles_allow == 0) From af840176e7009142212e6b20c9d5ed93e9f2754e Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Fri, 2 May 2025 16:14:55 -0600 Subject: [PATCH 20/26] doc page tweak --- doc/src/fix_set.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/src/fix_set.rst b/doc/src/fix_set.rst index 0f1cf7fcb0..1411eee4d8 100644 --- a/doc/src/fix_set.rst +++ b/doc/src/fix_set.rst @@ -140,8 +140,7 @@ the :doc:`run ` command. This fix is not invoked during Restrictions """""""""""" -As noted above, - +none Related commands """""""""""""""" From f3adda8d3e1b942b03494cc67530569bf99db86e Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Fri, 2 May 2025 16:21:41 -0600 Subject: [PATCH 21/26] clean-up code and doc page --- doc/src/fix_set.rst | 12 ++++++------ src/fix_set.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/src/fix_set.rst b/doc/src/fix_set.rst index 1411eee4d8..44bc2f21d6 100644 --- a/doc/src/fix_set.rst +++ b/doc/src/fix_set.rst @@ -14,7 +14,7 @@ Syntax * set = style name of this fix command * Nfreq = reset per-atom properties every this many timesteps * set-args = identical to args for the :doc:`set ` command - + Examples """""""" @@ -27,7 +27,7 @@ Description """"""""""" Reset one or more properties of one or more atoms once every *Nfreq* -stepes during a simulation. +steps during a simulation. The args following *Nfreq* are identical to those allowed for the :doc:`set ` command, as in the examples above and below. @@ -72,7 +72,7 @@ be output every step for *twindow* timesteps. # # dump command with thresh which enforces twindow # - dump 1 all custom 1 tmp.dump id x y vx i_dump + dump 1 all custom 1 tmp.dump id x y vx i_dump variable dumpflag atom "i_dump >= 0 && (step-i_dump) < v_twindow" dump_modify 1 thresh v_dumpflag == 1 # @@ -89,7 +89,7 @@ specific atom ID (104 in this case) was output in the tmp.dump file: .. code-block:: LAMMPS % grep "^104 " tmp.dump - + If these commands are used instead of the above, then an atom can cross the velocity threshold multiple times, and will be output for *twindow* timesteps each time. However the write_dump command is no @@ -116,14 +116,14 @@ longer useful. # # dump command with thresh which enforces twindow # - dump 1 all custom 1 tmp.dump id x y vx i_dump + dump 1 all custom 1 tmp.dump id x y vx i_dump variable dumpflag atom "i_dump >= 0 && (step-i_dump) < v_twindow" dump_modify 1 thresh v_dumpflag == 1 # # run the simulation # run 1000 - + ---------- Restart, fix_modify, output, run start/stop, minimize info diff --git a/src/fix_set.cpp b/src/fix_set.cpp index a1b8a45655..7c7245a9eb 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -38,7 +38,7 @@ FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) // pass remaining args to Set class // only keywords which use per-atom variables are currently allowed // NOTE: could also allow when set style = region, since atoms may move in/out of regions - + set->process_args(FIXSET,narg-4,&arg[4]); // NOTE: not sure if either of these options for fix set are needed or could be problematic From 6a5ed2af4ba250140bb2449f11e15872b22fbd6b Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Mon, 26 May 2025 16:22:52 -0600 Subject: [PATCH 22/26] add renieigbor option to fix set --- doc/src/Commands_fix.rst | 1 + doc/src/fix_set.rst | 36 ++++++++++++++++++++++++++++-------- doc/src/run.rst | 18 ++++++++++-------- src/fix_set.cpp | 23 +++++++++++++---------- src/fix_set.h | 2 ++ 5 files changed, 54 insertions(+), 26 deletions(-) diff --git a/doc/src/Commands_fix.rst b/doc/src/Commands_fix.rst index 35c3804969..0638cbe62e 100644 --- a/doc/src/Commands_fix.rst +++ b/doc/src/Commands_fix.rst @@ -216,6 +216,7 @@ OPT. * :doc:`rigid/small (o) ` * :doc:`rx (k) ` * :doc:`saed/vtk ` + * :doc:`set ` * :doc:`setforce (k) ` * :doc:`setforce/spin ` * :doc:`sgcmc ` diff --git a/doc/src/fix_set.rst b/doc/src/fix_set.rst index 44bc2f21d6..07c26b2923 100644 --- a/doc/src/fix_set.rst +++ b/doc/src/fix_set.rst @@ -8,11 +8,12 @@ Syntax .. code-block:: LAMMPS - fix ID group-ID set Nfreq set-args + fix ID group-ID set Nfreq rnflag set-args * ID, group-ID are documented in :doc:`fix ` command * set = style name of this fix command * Nfreq = reset per-atom properties every this many timesteps +* rnflag = 1 to reneighbor on next timestep, 0 to not * set-args = identical to args for the :doc:`set ` command Examples @@ -20,8 +21,8 @@ Examples .. code-block:: LAMMPS - fix 10 all set 1 group all i_dump v_new - fix 10 all set 1 group all i_dump v_turnoff + fix 10 all set 1 0 group all i_dump v_new + fix 10 all set 1 0 group all i_dump v_turnoff Description """"""""""" @@ -29,11 +30,30 @@ Description Reset one or more properties of one or more atoms once every *Nfreq* steps during a simulation. -The args following *Nfreq* are identical to those allowed for the -:doc:`set ` command, as in the examples above and below. +If the *rnflag* for reneighboring is set to 1, then a reneighboring +will be triggered on the next timestep (since the fix set operation +occurs at the end of the current timestep). This is important to do +if this command changes per-atom properties that need to be +communicated to ghost atoms. If this is not the case, an *rnflag* +setting of 0 can be used; reneighboring will only be triggered on +subsequent timesteps by the usual neighbor list criteria; see the +:doc:`neigh_modify ` command. + +Here are two examples where an *rnflag* setting of 1 are needed. If a +custom per-atom property is changed and the :doc:`fix property/atom +` command to create the property used the *ghost +yes* keyword. Or if per-atom charges are changed, all pair styles +which compute Coulombic interactions require charge values for ghost +atoms. In both these examples, the re-neighboring will trigger the +changes in the owned atom properties to be immediately communicated to +ghost atoms. + +The arguments following *Nfreq* and *rnflag* are identical to those +allowed for the :doc:`set ` command, as in the examples above and +below. Note that the group-ID setting for this command is ignored. The -syntax for the :doc:`set ` command allows selection of which +syntax for the :doc:`set ` arguments allows selection of which atoms have their properties reset. This command can only be used to reset an atom property using a @@ -68,7 +88,7 @@ be output every step for *twindow* timesteps. # variable start atom "vx > v_vthresh && i_dump == -1" variable new atom ternary(v_start,step,i_dump) - fix 3 all set 1 group all i_dump v_new + fix 3 all set 1 0 group all i_dump v_new # # dump command with thresh which enforces twindow # @@ -112,7 +132,7 @@ longer useful. variable turnon atom ternary(v_start,step,i_dump) variable stop atom "v_turnon >= 0 && (step-v_turnon) < v_twindow" variable turnoff atom ternary(v_stop,v_turnon,-1) - fix 3 all set 1 group all i_dump v_turnoff + fix 3 all set 1 0 group all i_dump v_turnoff # # dump command with thresh which enforces twindow # diff --git a/doc/src/run.rst b/doc/src/run.rst index c3dd171f6b..95e2f037db 100644 --- a/doc/src/run.rst +++ b/doc/src/run.rst @@ -103,14 +103,16 @@ must be done. .. note:: - If your input script changes the system between 2 runs, then the - initial setup must be performed to ensure the change is recognized by - all parts of the code that are affected. Examples are adding a - :doc:`fix ` or :doc:`dump ` or :doc:`compute `, changing - a :doc:`neighbor ` list parameter, or writing restart file - which can migrate atoms between processors. LAMMPS has no easy way to - check if this has happened, but it is an error to use the *pre no* - option in this case. + If your input script "changes" the system between 2 runs, then the + initial setup typically needs to be performed to ensure the change + is recognized by all parts of the code that are affected. Examples + are adding a :doc:`fix ` or :doc:`dump ` or + :doc:`compute `, changing a :doc:`neighbor ` + list parameter, using the :doc:`set ` command, or writing a + restart file via the :doc:`write_restart ` command, + which can migrate atoms between processors. LAMMPS has no easy way + to check if this has happened, but it is an error to use the *pre + no* option in these cases. If *post* is specified as "no", the full timing summary is skipped; only a one-line summary timing is printed. diff --git a/src/fix_set.cpp b/src/fix_set.cpp index 7c7245a9eb..cab303660b 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -16,6 +16,7 @@ #include "atom.h" #include "error.h" #include "set.h" +#include "update.h" using namespace LAMMPS_NS; using namespace FixConst; @@ -26,27 +27,25 @@ enum{SETCOMMAND,FIXSET}; // also used in Set class FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { - if (narg < 7) error->all(FLERR, 1, "Illegal fix set command: need at least four arguments"); + if (narg < 8) error->all(FLERR, 1, "Illegal fix set command: need at least eight arguments"); nevery = utils::inumeric(FLERR, arg[3], false, lmp); if (nevery <= 0) error->all(FLERR, "Fix {} Nevery must be > 0", style); + reneighbor = utils::inumeric(FLERR, arg[4], false, lmp); + if (reneighbor = 0 || reneighbor > 1) + error->all(FLERR, "Fix {} rnflag must be 0/1", style); + // create instance of Set class set = new Set(lmp); // pass remaining args to Set class // only keywords which use per-atom variables are currently allowed - // NOTE: could also allow when set style = region, since atoms may move in/out of regions + // NOTE: could also allow when set style = region, + // since atoms may move in/out of regions - set->process_args(FIXSET,narg-4,&arg[4]); - - // NOTE: not sure if either of these options for fix set are needed or could be problematic - // could add ghost yes keyword/value to trigger - // ghost comm, e.g. if atom types are reset - // this could require an extract() method in Set to query what value(s) to comm - // could add reneigh yes keyword/value to trigger - // full reneighbor on next step, e.g. if xyz coords are reset + set->process_args(FIXSET,narg-5,&arg[5]); } /* ---------------------------------------------------------------------- */ @@ -79,5 +78,9 @@ void FixSet::end_of_step() // loop over list of actions to reset atom attributes set->invoke_actions(); + + // trigger reneighboring on next timestep if requested + + if (reneighbor) next_reneighbor = update->ntimestep + 1; } diff --git a/src/fix_set.h b/src/fix_set.h index f5d0aeb3f5..7328ebd144 100644 --- a/src/fix_set.h +++ b/src/fix_set.h @@ -32,6 +32,8 @@ class FixSet : public Fix { void end_of_step() override; private: + int reneighbor; + class Set *set; }; From 1668bcffcf1e4e473d2c9a58ee076a5477474527 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 28 May 2025 08:53:55 -0600 Subject: [PATCH 23/26] fix 2 bugs caught in review --- src/fix_set.cpp | 3 +-- src/set.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/fix_set.cpp b/src/fix_set.cpp index cab303660b..ac4400c1a9 100644 --- a/src/fix_set.cpp +++ b/src/fix_set.cpp @@ -33,7 +33,7 @@ FixSet::FixSet(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) if (nevery <= 0) error->all(FLERR, "Fix {} Nevery must be > 0", style); reneighbor = utils::inumeric(FLERR, arg[4], false, lmp); - if (reneighbor = 0 || reneighbor > 1) + if (reneighbor < 0 || reneighbor > 1) error->all(FLERR, "Fix {} rnflag must be 0/1", style); // create instance of Set class @@ -83,4 +83,3 @@ void FixSet::end_of_step() if (reneighbor) next_reneighbor = update->ntimestep + 1; } - diff --git a/src/set.cpp b/src/set.cpp index d07b1e4e2c..f42dd175ab 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -303,7 +303,7 @@ void Set::process_args(int caller_flag, int narg, char **arg) } else if (strcmp(arg[iarg],"smd/mass/density") == 0) { action->keyword = SMD_MASS_DENSITY; process_smd_mass_density(iarg,narg,arg,action); - invoke_choice[naction++] = &Set::invoke_density; + invoke_choice[naction++] = &Set::invoke_smd_mass_density; } else if (strcmp(arg[iarg],"sph/cv") == 0) { action->keyword = SPH_CV; process_sph_cv(iarg,narg,arg,action); From f584d7219a85bf538c42d53e50bf4e43a04d598c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 29 May 2025 05:24:00 -0400 Subject: [PATCH 24/26] correct incorrect reference to command --- doc/src/fix_set.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/fix_set.rst b/doc/src/fix_set.rst index 07c26b2923..cfa8231ccd 100644 --- a/doc/src/fix_set.rst +++ b/doc/src/fix_set.rst @@ -37,7 +37,7 @@ if this command changes per-atom properties that need to be communicated to ghost atoms. If this is not the case, an *rnflag* setting of 0 can be used; reneighboring will only be triggered on subsequent timesteps by the usual neighbor list criteria; see the -:doc:`neigh_modify ` command. +:doc:`neigh_modify command `. Here are two examples where an *rnflag* setting of 1 are needed. If a custom per-atom property is changed and the :doc:`fix property/atom From 26def4a3cf041106f99d9405b50c3eb02b7d0acf Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 26 May 2025 17:56:26 -0400 Subject: [PATCH 25/26] we only need the MPI C library support for loading liblammps.so dynamically --- examples/COUPLE/plugin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/COUPLE/plugin/CMakeLists.txt b/examples/COUPLE/plugin/CMakeLists.txt index 00f86058fb..c8deb5c7c6 100644 --- a/examples/COUPLE/plugin/CMakeLists.txt +++ b/examples/COUPLE/plugin/CMakeLists.txt @@ -27,7 +27,7 @@ if(MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() -find_package(MPI REQUIRED) +find_package(MPI REQUIRED COMPONENTS C) # do not include the (obsolete) MPI C++ bindings which makes # for leaner object files and avoids namespace conflicts set(MPI_CXX_SKIP_MPICXX TRUE) From 0af41a211d308da5ee552151e7bd39f1ac9d8e4b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 29 May 2025 05:27:41 -0400 Subject: [PATCH 26/26] add false positive --- doc/utils/sphinx-config/false_positives.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index af91745034..e6ecd4e136 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -3360,6 +3360,7 @@ Rmin RMS rmsd rnage +rnflag rng rNEMD ro