From 36afc91dfa27c6e5b8ebbd64976a58c80cba2a6a Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Sat, 25 Nov 2023 15:20:28 -0700 Subject: [PATCH 001/396] 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 002/396] 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 003/396] 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 004/396] 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 005/396] 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 006/396] 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 57ce8ee6ab64220e27eee02be4aad7f46e018ad3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:50:00 +0000 Subject: [PATCH 007/396] Bump actions/setup-python from 4 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/compile-msvc.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 58b001be24..00c0e8642d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -30,7 +30,7 @@ jobs: fetch-depth: 2 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/compile-msvc.yml b/.github/workflows/compile-msvc.yml index 5c6ceeefb4..1a0f1ea62f 100644 --- a/.github/workflows/compile-msvc.yml +++ b/.github/workflows/compile-msvc.yml @@ -24,7 +24,7 @@ jobs: fetch-depth: 2 - name: Select Python version - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' From c234d6e997091f7d7c95bca20e45dda3a31c1177 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 17:51:12 +0000 Subject: [PATCH 008/396] Bump github/codeql-action from 2 to 3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 58b001be24..cfa59e6db3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,7 +35,7 @@ jobs: python-version: '3.x' - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/${{ matrix.language }}.yml @@ -55,4 +55,4 @@ jobs: cmake --build . --parallel 2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 From b23f70daf7ba16fddd9a1fdb96a7db90c86552af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:37:35 +0000 Subject: [PATCH 009/396] Bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/coverity.yml | 2 +- .github/workflows/unittest-macos.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 00a4596cc8..c0c3e3f89a 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -25,7 +25,7 @@ jobs: - name: Cache Coverity id: cache-coverity - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./download/ key: ${{ runner.os }}-download-${{ hashFiles('**/coverity_tool.*') }} diff --git a/.github/workflows/unittest-macos.yml b/.github/workflows/unittest-macos.yml index 6970faceaa..f9c2a838d6 100644 --- a/.github/workflows/unittest-macos.yml +++ b/.github/workflows/unittest-macos.yml @@ -32,7 +32,7 @@ jobs: run: mkdir build - name: Set up ccache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.CCACHE_DIR }} key: macos-ccache-${{ github.sha }} From f980e8babf44f3a6fef948c4e03922a41a3e4dcb Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Thu, 19 Dec 2024 09:52:05 -0700 Subject: [PATCH 010/396] Integrated MD-KMC code to current development branch --- src/Depend.sh | 1 + src/MC/Install.sh | 2 + src/MC/fix_neighbor_swap.cpp | 1012 ++++++++++++++++++++++++++++++++++ src/MC/fix_neighbor_swap.h | 146 +++++ 4 files changed, 1161 insertions(+) create mode 100755 src/MC/fix_neighbor_swap.cpp create mode 100755 src/MC/fix_neighbor_swap.h diff --git a/src/Depend.sh b/src/Depend.sh index 9ddb29450d..ba55deb62c 100755 --- a/src/Depend.sh +++ b/src/Depend.sh @@ -146,6 +146,7 @@ fi if (test $1 = "MC") then depend MISC + depend VORONOI fi if (test $1 = "MEAM") then diff --git a/src/MC/Install.sh b/src/MC/Install.sh index ccf6767c4d..9a0095fd34 100755 --- a/src/MC/Install.sh +++ b/src/MC/Install.sh @@ -51,6 +51,8 @@ action fix_charge_regulation.cpp action fix_charge_regulation.h action fix_gcmc.cpp action fix_gcmc.h +action fix_neighbor_swap.cpp +action fix_neighbor_swap.h action fix_mol_swap.cpp action fix_mol_swap.h action fix_sgcmc.cpp pair_eam.cpp diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp new file mode 100755 index 0000000000..52730ee6f5 --- /dev/null +++ b/src/MC/fix_neighbor_swap.cpp @@ -0,0 +1,1012 @@ +// 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Jacob Tavenner +------------------------------------------------------------------------- */ + +#include "fix_neighbor_swap.h" + +#include "angle.h" +#include "atom.h" +#include "bond.h" +#include "comm.h" +#include "compute.h" +#include "dihedral.h" +#include "domain.h" +#include "error.h" +#include "fix.h" +#include "force.h" +#include "group.h" +#include "improper.h" +#include "kspace.h" +#include "memory.h" +#include "modify.h" +#include "neighbor.h" +#include "pair.h" +#include "random_park.h" +#include "region.h" +#include "update.h" +#include "compute_voronoi_atom.h" + +#include +#include +#include +#include + +using namespace LAMMPS_NS; +using namespace FixConst; + +static const char cite_fix_neighbor_swap_c[] = + "fix neighbor/swap command: doi:10.1016/j.commatsci.2022.111929\n\n" + "@Article{Tavenner2023111929,\n" + " author = {Jacob P. Tavenner and Mikhail I. Mendelev and John W. Lawson},\n" + " title = {Molecular dynamics based kinetic Monte Carlo simulation for accelerated diffusion},\n" + " journal = {Computational Materials Science},\n" + " year = {2023},\n" + " volume = {218},\n" + " pages = {111929}\n" + " url = {https://www.sciencedirect.com/science/article/pii/S0927025622006401}\n" + "}\n\n"; + +/* ---------------------------------------------------------------------- */ + +FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), region(nullptr), idregion(nullptr), type_list(nullptr), + qtype(nullptr), c_voro(nullptr), voro_neighbor_list(nullptr), + sqrt_mass_ratio(nullptr), local_swap_iatom_list(nullptr), + random_equal(nullptr), random_unequal(nullptr), c_pe(nullptr) +{ + if (narg < 10) error->all(FLERR,"Illegal fix neighbor/swap command"); + + // utils::logmesg(lmp,"Starting neighbor/swap\n"); + + dynamic_group_allow = 1; + + vector_flag = 1; + size_vector = 2; + global_freq = 1; + extvector = 0; + restart_global = 1; + time_depend = 1; + + // required args + + nevery = utils::inumeric(FLERR,arg[3],false,lmp); + ncycles = utils::inumeric(FLERR,arg[4],false,lmp); + seed = utils::inumeric(FLERR,arg[5],false,lmp); + double temperature = utils::numeric(FLERR,arg[6],false,lmp); + + if (nevery <= 0) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (ncycles < 0) error->all(FLERR,"Illegal fix neighbor/swap command"); + // if (nevery < ncycles) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (seed <= 0) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (temperature <= 0.0) error->all(FLERR,"Illegal fix neighbor/swap command"); + + beta = 1.0 / (force->boltz * temperature); + + memory->create(type_list,atom->ntypes,"neighbor/swap:type_list"); + memory->create(rate_list,atom->ntypes,"neighbor/swap:rate_list"); + + // read options from end of input line + + options(narg-7,&arg[7]); + + if (voro_flag != 1) error->all(FLERR,"Voro Compute Required for fix neighbor/swap command"); + + // random number generator, same for all procs + + random_equal = new RanPark(lmp,seed); + + // random number generator, not the same for all procs + + random_unequal = new RanPark(lmp,seed); + + // set up reneighboring + + force_reneighbor = 1; + next_reneighbor = update->ntimestep + 1; + + // zero out counters + + nswap_attempts = 0.0; + nswap_successes = 0.0; + + atom_swap_nmax = 0; + voro_neighbor_list = nullptr; + local_swap_iatom_list = nullptr; + local_swap_neighbor_list = nullptr; + local_swap_probability = nullptr; + local_swap_type_list = nullptr; + + // set comm size needed by this Fix + + if (atom->q_flag) comm_forward = 2; + else comm_forward = 1; + +} + +/* ---------------------------------------------------------------------- */ + +FixNeighborSwap::~FixNeighborSwap() +{ + memory->destroy(type_list); + memory->destroy(rate_list); + memory->destroy(qtype); + memory->destroy(sqrt_mass_ratio); + memory->destroy(local_swap_iatom_list); + memory->destroy(local_swap_neighbor_list); + memory->destroy(local_swap_probability); + memory->destroy(local_swap_type_list); + delete[] idregion; + delete random_equal; + delete random_unequal; +} + +/* ---------------------------------------------------------------------- + parse optional parameters at end of input line +------------------------------------------------------------------------- */ + +void FixNeighborSwap::options(int narg, char **arg) +{ + if (narg < 0) error->all(FLERR,"Illegal fix neighbor/swap command\n"); + + ke_flag = 1; + diff_flag = 0; + rates_flag = 0; + voro_flag = 0; + nswaptypes = 0; + + int iarg = 0; + while (iarg < narg) { + // utils::logmesg(lmp,"Parsing Argument {}\n", arg[iarg]); + if (strcmp(arg[iarg],"region") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + region = domain->get_region_by_id(arg[iarg+1]); + if (!region) error->all(FLERR,"Region ID for fix neighbor/swap does not exist"); + idregion = utils::strdup(arg[iarg + 1]); + iarg += 2; + } else if (strcmp(arg[iarg],"ke") == 0) { + if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + ke_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); + iarg += 2; + } else if (strcmp(arg[iarg],"types") == 0) { + if (iarg + 3 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (diff_flag != 0) error->all(FLERR,"Illegal fix neighbor/swap command"); + iarg++; + nswaptypes = 0; + while (iarg < narg) { + if (isalpha(arg[iarg][0])) break; + if (nswaptypes >= atom->ntypes) error->all(FLERR,"Illegal fix neighbor/swap command"); + type_list[nswaptypes] = utils::numeric(FLERR,arg[iarg],false,lmp); + nswaptypes++; + iarg++; + } + } else if (strcmp(arg[iarg],"voro") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + + int icompute = modify->find_compute(utils::strdup(arg[iarg+1])); + + if (icompute < 0) error->all(FLERR,"Could not find neighbor compute ID"); + c_voro = modify->compute[icompute]; + if (c_voro->local_flag == 0) + error->all(FLERR,"Neighbor compute does not compute local info"); + if (c_voro->size_local_cols != 3) + error->all(FLERR,"Neighbor compute does not give i, j, size as expected"); + + voro_flag = 1; + iarg += 2; + } else if (strcmp(arg[iarg],"diff") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (nswaptypes != 0) error->all(FLERR,"Illegal fix neighbor/swap command"); + type_list[nswaptypes] = utils::numeric(FLERR,arg[iarg+1],false,lmp); + diff_flag = 1; + nswaptypes++; + iarg += 2; + } else if (strcmp(arg[iarg],"rates") == 0) { + if (iarg+atom->ntypes >= narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + // utils::logmesg(lmp,"Reading rates\n"); + iarg++; + int i = 0; + while (iarg < narg) { + if (isalpha(arg[iarg][0])) break; + if (i >= atom->ntypes) error->all(FLERR,"Illegal fix neighbor/swap command"); + rate_list[i] = utils::numeric(FLERR,arg[iarg],false,lmp); + i++; + iarg++; + } + rates_flag = 1; + if (i != atom->ntypes) error->all(FLERR,"Illegal fix neighbor/swap command"); + } + else error->all(FLERR,"Illegal fix neighbor/swap command"); + } +} + +/* ---------------------------------------------------------------------- */ + +int FixNeighborSwap::setmask() +{ + int mask = 0; + mask |= PRE_EXCHANGE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixNeighborSwap::init() +{ + // utils::logmesg(lmp,"Initializing neighbor/swap\n"); + c_pe = modify->get_compute_by_id("thermo_pe"); + + int *type = atom->type; + + if (nswaptypes < 2 && !diff_flag) error->all(FLERR,"Must specify at least 2 types in fix neighbor/swap command"); + + // set index and check validity of region + + if (idregion) { + region = domain->get_region_by_id(idregion); + if (!region) error->all(FLERR, "Region {} for fix setforce does not exist", idregion); + } + + for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) + if (type_list[iswaptype] <= 0 || type_list[iswaptype] > atom->ntypes) + error->all(FLERR,"Invalid atom type in fix neighbor/swap command"); + + if (atom->q_flag) { + double qmax,qmin; + int firstall,first; + memory->create(qtype,nswaptypes,"neighbor/swap:qtype"); + for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) { + first = 1; + for (int i = 0; i < atom->nlocal; i++) { + if (atom->mask[i] & groupbit) { + if (type[i] == type_list[iswaptype]) { + if (first) { + qtype[iswaptype] = atom->q[i]; + first = 0; + } else if (qtype[iswaptype] != atom->q[i]) + error->one(FLERR,"All atoms of a swapped type must have the same charge."); + } + } + } + MPI_Allreduce(&first,&firstall,1,MPI_INT,MPI_MIN,world); + if (firstall) error->all(FLERR,"At least one atom of each swapped type must be present to define charges."); + if (first) qtype[iswaptype] = -DBL_MAX; + MPI_Allreduce(&qtype[iswaptype],&qmax,1,MPI_DOUBLE,MPI_MAX,world); + if (first) qtype[iswaptype] = DBL_MAX; + MPI_Allreduce(&qtype[iswaptype],&qmin,1,MPI_DOUBLE,MPI_MIN,world); + if (qmax != qmin) error->all(FLERR,"All atoms of a swapped type must have same charge."); + } + } + + memory->create(sqrt_mass_ratio,atom->ntypes+1,atom->ntypes+1,"neighbor/swap:sqrt_mass_ratio"); + for (int itype = 1; itype <= atom->ntypes; itype++) + for (int jtype = 1; jtype <= atom->ntypes; jtype++) + sqrt_mass_ratio[itype][jtype] = sqrt(atom->mass[itype]/atom->mass[jtype]); + + // check to see if itype and jtype cutoffs are the same + // if not, reneighboring will be needed between swaps + + double **cutsq = force->pair->cutsq; + unequal_cutoffs = false; + for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) + for (int jswaptype = 0; jswaptype < nswaptypes; jswaptype++) + for (int ktype = 1; ktype <= atom->ntypes; ktype++) + if (cutsq[type_list[iswaptype]][ktype] != cutsq[type_list[jswaptype]][ktype]) + unequal_cutoffs = true; + + // check that no swappable atoms are in atom->firstgroup + // swapping such an atom might not leave firstgroup atoms first + + if (atom->firstgroup >= 0) { + int *mask = atom->mask; + int firstgroupbit = group->bitmask[atom->firstgroup]; + + int flag = 0; + for (int i = 0; i < atom->nlocal; i++) + if ((mask[i] == groupbit) && (mask[i] && firstgroupbit)) flag = 1; + + int flagall; + MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); + + if (flagall) + error->all(FLERR,"Cannot do neighbor/swap on atoms in atom_modify first group"); + + // utils::logmesg(lmp,"Done Init\n"); + } +} + +/* ---------------------------------------------------------------------- + attempt Monte Carlo swaps +------------------------------------------------------------------------- */ + +void FixNeighborSwap::pre_exchange() +{ + // just return if should not be called on this timestep + + if (next_reneighbor != update->ntimestep) return; + + // ensure current system is ready to compute energy + + if (domain->triclinic) domain->x2lamda(atom->nlocal); + domain->pbc(); + comm->exchange(); + comm->borders(); + if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); + if (modify->n_pre_neighbor) modify->pre_neighbor(); + neighbor->build(1); + + // energy_stored = energy of current state + // will be updated after accepted swaps + + energy_stored = energy_full(); + + // attempt Ncycle atom swaps + + // utils::logmesg(lmp,"Attempting Swap\n"); + + int nsuccess = 0; + update_iswap_atoms_list(); + // utils::logmesg(lmp,"Updated Atom i List\n"); + for (int i = 0; i < ncycles; i++) nsuccess += attempt_swap(); + + // utils::logmesg(lmp,"\n"); + + // udpate MC stats + + nswap_attempts += ncycles; + nswap_successes += nsuccess; + + next_reneighbor = update->ntimestep + nevery; +} + +/* ---------------------------------------------------------------------- + attempt a swap of a pair of atoms + compare before/after energy and accept/reject the swap +------------------------------------------------------------------------- */ + +int FixNeighborSwap::attempt_swap() +{ + // int nlocal = atom->nlocal; + tagint *id = atom->tag; + + if ( niswap == 0 ) return 0; + + // pre-swap energy + + double energy_before = energy_stored; + + // pick a random atom i + + int i = pick_i_swap_atom(); + + // get global id and position of atom i + // get_global_i(i); + + // build nearest-neighbor list based on atom i + + build_i_neighbor_list(i); + // utils::logmesg(lmp,"Built neighbor list with {} atoms\n",njswap); + if ( njswap <= 0 ) { + // utils::logmesg(lmp,"No valid neighbors found\n"); + return 0; + } + + // pick a neighbor atom j based on i neighbor list + jtype_selected = -1; + int j = pick_j_swap_neighbor(i); + // utils::logmesg(lmp,"Selected swap neighbor j\n"); + + int itype = type_list[0]; + int jtype = jtype_selected; + // utils::logmesg(lmp,"Selected atom j type {}\n",jtype); + + // utils::logmesg(lmp,"Swapping local atoms {} and ",i); + // utils::logmesg(lmp,"{}\n",j); + + // if ( i >= 0 || j >= 0) { + // utils::logmesg(lmp,"Selected atom j type {}\n",jtype); + // utils::logmesg(lmp,"Swapping atoms {} and ",id[i]); + // utils::logmesg(lmp,"{}\n",id[j]); + // } + + // utils::logmesg(lmp,"Atom type {} and ",itype); + // utils::logmesg(lmp,"{}\n",jtype); + + // Accept swap if types are equal, no change to system + if ( itype == jtype ){ + // utils::logmesg(lmp,"Atoms have same type, no processing needed\n"); + return 1; + } + + // swap their properties + if ( i >= 0 ) { + atom->type[i] = jtype; + if (atom->q_flag) atom->q[i] = qtype[jtype_selected]; + } + if ( j >= 0 ) { + atom->type[j] = itype; + if (atom->q_flag) atom->q[j] = qtype[0]; + } + + // if unequal_cutoffs, call comm->borders() and rebuild neighbor list + // else communicate ghost atoms + // call to comm->exchange() is a no-op but clears ghost atoms + + if (unequal_cutoffs) { + if (domain->triclinic) domain->x2lamda(atom->nlocal); + domain->pbc(); + comm->exchange(); + comm->borders(); + if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); + if (modify->n_pre_neighbor) modify->pre_neighbor(); + neighbor->build(1); + } else { + comm->forward_comm(this); + } + + // post-swap energy + + double energy_after = energy_full(); + + // if swap accepted, return 1 + // if ke_flag, rescale atom velocities + + if (random_equal->uniform() < + exp(beta*(energy_before - energy_after))) { + update_iswap_atoms_list(); + if (ke_flag) { + if ( i >= 0 ) { + atom->v[i][0] *= sqrt_mass_ratio[itype][jtype]; + atom->v[i][1] *= sqrt_mass_ratio[itype][jtype]; + atom->v[i][2] *= sqrt_mass_ratio[itype][jtype]; + } + if ( j >= 0 ) { + atom->v[j][0] *= sqrt_mass_ratio[jtype][itype]; + atom->v[j][1] *= sqrt_mass_ratio[jtype][itype]; + atom->v[j][2] *= sqrt_mass_ratio[jtype][itype]; + } + } + energy_stored = energy_after; + + // utils::logmesg(lmp,"Swap accepted\n"); + // Swap atom groups if successful swap + + // int groupi = atom->mask[i]; + // int groupj = atom->mask[j]; + + // atom->mask[i] = group->bitmask[groupj]; + // atom->mask[j] = group->bitmask[groupi]; + + return 1; + } + + // swap not accepted, return 0 + // restore the swapped itype & jtype atoms + // do not need to re-call comm->borders() and rebuild neighbor list + // since will be done on next cycle or in Verlet when this fix finishes + + // utils::logmesg(lmp,"Swap not accepted\n"); + + if ( i >= 0 ) { + atom->type[i] = itype; + if (atom->q_flag) atom->q[i] = qtype[0]; + } + if ( j >= 0 ) { + atom->type[j] = jtype; + if (atom->q_flag) atom->q[j] = qtype[jtype_selected]; + } + + return 0; +} + +/* ---------------------------------------------------------------------- + compute system potential energy +------------------------------------------------------------------------- */ + +double FixNeighborSwap::energy_full() +{ + int eflag = 1; + int vflag = 0; + + if (modify->n_pre_force) modify->pre_force(vflag); + + if (force->pair) force->pair->compute(eflag,vflag); + + if (atom->molecular != Atom::ATOMIC) { + if (force->bond) force->bond->compute(eflag,vflag); + if (force->angle) force->angle->compute(eflag,vflag); + if (force->dihedral) force->dihedral->compute(eflag,vflag); + if (force->improper) force->improper->compute(eflag,vflag); + } + + if (force->kspace) force->kspace->compute(eflag,vflag); + + if (modify->n_post_force_any) modify->post_force(vflag); + + update->eflag_global = update->ntimestep; + double total_energy = c_pe->compute_scalar(); + + return total_energy; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +int FixNeighborSwap::pick_i_swap_atom() +{ + tagint *id = atom->tag; + int id_center_local = -1; + int i = -1; + + int iwhichglobal = static_cast (niswap*random_equal->uniform()); + if ((iwhichglobal >= niswap_before) && + (iwhichglobal < niswap_before + niswap_local)) { + int iwhichlocal = iwhichglobal - niswap_before; + i = local_swap_iatom_list[iwhichlocal]; + id_center_local = id[i]; + MPI_Allreduce(&id[i],&id_center,1,MPI_INT,MPI_MAX,world); + } else { + MPI_Allreduce(&id[i],&id_center,1,MPI_INT,MPI_MAX,world); + } + + return i; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +int FixNeighborSwap::pick_j_swap_neighbor(int i) +{ + int j = -1; + int jtype_selected_local = -1; + + // Generate random double from 0 to maximum global probability + double selected_prob = static_cast (global_probability*random_equal->uniform()); + + // utils::logmesg(lmp,"Local Probability {}\n",local_probability); + + // Find which local swap atom corresponds to probability + if ((selected_prob >= prev_probability) && + (selected_prob < prev_probability + local_probability)){ + // utils::logmesg(lmp,"Selected Probability {}\n",selected_prob); + double search_prob = selected_prob - prev_probability; + for (int n = 0; n < njswap_local; n++){ + if (search_prob > local_swap_probability[n]){ + search_prob -= local_swap_probability[n]; + } + else{ + j = local_swap_neighbor_list[n]; + jtype_selected_local = local_swap_type_list[n]; + // utils::logmesg(lmp,"Selecting Atom j type {}\n",jtype_selected_local); + MPI_Allreduce(&jtype_selected_local,&jtype_selected,1,MPI_INT,MPI_MAX,world); + return j; + } + } + error->all(FLERR,"Did not select local neighbor swap atom"); + } + + // utils::logmesg(lmp,"Swap atom not found on processor\n"); + MPI_Allreduce(&jtype_selected_local,&jtype_selected,1,MPI_INT,MPI_MAX,world); + return j; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +double FixNeighborSwap::get_distance(double* i, double* j) +{ + // double r_x, r_y, r_z; + + // r_x = i[0] - j[0]; + // r_y = i[1] - j[1]; + // r_z = i[2] - j[2]; + + // // Domain::minimum_image(r_x, r_y, r_z); + // double r = sqrt(pow(r_x, 2.) + + // pow(r_y, 2.) + + // pow(r_z, 2.)); + + double r = sqrt(pow((i[0] - j[0]), 2.) + + pow((i[1] - j[1]), 2.) + + pow((i[2] - j[2]), 2.)); + + + return r; +} + +/* ---------------------------------------------------------------------- +------------------------------------------------------------------------- */ + +void FixNeighborSwap::build_i_neighbor_list(int i_center) +{ + int nghost = atom->nghost; + int nlocal = atom->nlocal; + int *type = atom->type; + double **x = atom->x; + tagint *id = atom->tag; + + // Allocate local_swap_neighbor_list size + + memory->sfree(local_swap_neighbor_list); + atom_swap_nmax = atom->nmax; + local_swap_neighbor_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), + "MCSWAP:local_swap_neighbor_list"); + + memory->sfree(local_swap_probability); + local_swap_probability = (double *) memory->smalloc(atom_swap_nmax*sizeof(double), + "MCSWAP:local_swap_probability_list"); + + memory->sfree(local_swap_type_list); + local_swap_type_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), + "MCSWAP:local_swap_type_list"); + + // Compute voronoi and access neighbor list + + c_voro->compute_local(); + + voro_neighbor_list = c_voro->array_local; + njswap_local = 0; + local_probability = 0.0; + + // utils::logmesg(lmp,"Searching for atom {}\n",id_center); + + for (int n = 0; n < c_voro->size_local_rows; n++){ + + int temp_j_id = -1; + int temp_j = -1; + + // Find local voronoi entry with selected central atom + if ( (int)voro_neighbor_list[n][0] == id_center ){ + temp_j_id = voro_neighbor_list[n][1]; + temp_j = -1; + } else if ( ((int)voro_neighbor_list[n][1] == id_center) && + ( i_center < 0 ) ){ + temp_j_id = voro_neighbor_list[n][0]; + temp_j = -1; + } else { + continue; + } + + // Find which local atom corresponds to neighbor + for (int j = 0; j < nlocal; j++){ + if ( temp_j_id == id[j] ){ + temp_j = j; + // utils::logmesg(lmp,"Found neighbor {}\n",id[j]); + break; + } + } + + // If temp_j not on this processor, skip + if ( temp_j < 0 ) continue; + + // // If atom is already in local list, skip + // bool inlist = false; + // for ( int j = 0; j < njswap_local; j++ ){ + // if ( temp_j == local_swap_neighbor_list[j] ){ + // utils::logmesg(lmp,"Skipping atom {}, pair already counted\n",id[temp_j]); + // inlist = true; + // break; + // } + // } + // if (inlist) continue; + + if (region) { + if (region->match(x[temp_j][0],x[temp_j][1],x[temp_j][2]) == 1) { + if (atom->mask[temp_j] & groupbit) { + if (diff_flag) { + // Calculate distance from i to each j, adjust probability of selection + + // Get distance if own centr atom + double r = INFINITY; + if ( i_center >= 0 ){ + double r = get_distance(x[temp_j], x[i_center]); + } + + // Get local id of ghost center atom when ghost + for (int i=nlocal; i < nlocal+nghost; i++){ + if ( (id[i] == id_center) && + (get_distance(x[temp_j], x[i]) < r) ){ + r = get_distance(x[temp_j], x[i]); + } + } + + if (rates_flag) { + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + } else { + local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + } + local_probability += local_swap_probability[njswap_local]; + + // utils::logmesg(lmp,"Adding Atom j type {}\n",type[temp_j]); + local_swap_type_list[njswap_local] = type[temp_j]; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } else { + for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++){ + if (type[temp_j] == type_list[jswaptype]) { + // Calculate distance from i to each j, adjust probability of selection + // Get distance if own center atom + double r = INFINITY; + if ( i_center >= 0 ){ + double r = get_distance(x[temp_j], x[i_center]); + } + + // Get local id of ghost center atom when ghost + for (int i=nlocal; i < nlocal+nghost; i++){ + if ( (id[i] == id_center) && + (get_distance(x[temp_j], x[i]) < r) ){ + r = get_distance(x[temp_j], x[i]); + } + } + + if (rates_flag) { + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + } else { + local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + } + local_probability += local_swap_probability[njswap_local]; + + local_swap_type_list[njswap_local] = jswaptype; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } + } + } + } + } + } else { + if (atom->mask[temp_j] & groupbit) { + if (diff_flag) { + // Calculate distance from i to each j, adjust probability of selection + // Get distance if own center atom + double r = INFINITY; + if ( i_center >= 0 ){ + r = get_distance(x[temp_j], x[i_center]); + } + + // Get local id of ghost center atoms + // if ( i_center < 0 ){ + // utils::logmesg(lmp,"Initial distance {}\n", r); + for (int i=nlocal; i < nlocal+nghost; i++){ + if ( (id[i] == id_center) && + (get_distance(x[temp_j], x[i]) < r) ){ + r = get_distance(x[temp_j], x[i]); + // utils::logmesg(lmp,"Updated distance {}\n", r); + } + } + // } + + // utils::logmesg(lmp,"Final distance {}\n", r); + + if (rates_flag) { + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + } else{ + local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + } + local_probability += local_swap_probability[njswap_local]; + + local_swap_type_list[njswap_local] = type[temp_j]; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } else { + for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++){ + if (type[temp_j] == type_list[jswaptype]) { + // Calculate distance from i to each j, adjust probability of selection + // Get distance if own center atom + double r = INFINITY; + if ( i_center >= 0 ){ + double r = get_distance(x[temp_j], x[i_center]); + } + + // Get local id of ghost center atom when ghost + for (int i=nlocal; i < nlocal+nghost; i++){ + if ( (id[i] == id_center) && + (get_distance(x[temp_j], x[i]) < r) ){ + r = get_distance(x[temp_j], x[i]); + } + } + + if (rates_flag) { + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + } else { + local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + } + local_probability += local_swap_probability[njswap_local]; + + local_swap_type_list[njswap_local] = jswaptype; + local_swap_neighbor_list[njswap_local] = temp_j; + njswap_local++; + } + } + } + } + } + } + + MPI_Allreduce(&njswap_local,&njswap,1,MPI_INT,MPI_SUM,world); + MPI_Scan(&njswap_local,&njswap_before,1,MPI_INT,MPI_SUM,world); + njswap_before -= njswap_local; + + MPI_Allreduce(&local_probability,&global_probability,1,MPI_DOUBLE,MPI_SUM,world); + MPI_Scan(&local_probability,&prev_probability,1,MPI_DOUBLE,MPI_SUM,world); + prev_probability -= local_probability; +} + +/* ---------------------------------------------------------------------- + update the list of swap atoms +------------------------------------------------------------------------- */ + +void FixNeighborSwap::update_iswap_atoms_list() +{ + int nlocal = atom->nlocal; + int *type = atom->type; + double **x = atom->x; + + if (atom->nmax > atom_swap_nmax) { + memory->sfree(local_swap_iatom_list); + atom_swap_nmax = atom->nmax; + local_swap_iatom_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), + "MCSWAP:local_swap_iatom_list"); + } + + niswap_local = 0; + + if (region) { + + for (int i = 0; i < nlocal; i++) { + if (region->match(x[i][0],x[i][1],x[i][2]) == 1) { + if (atom->mask[i] & groupbit) { + if (type[i] == type_list[0]) { + local_swap_iatom_list[niswap_local] = i; + niswap_local++; + } + } + } + } + + } else { + for (int i = 0; i < nlocal; i++) { + if (atom->mask[i] & groupbit) { + if (type[i] == type_list[0]) { + local_swap_iatom_list[niswap_local] = i; + niswap_local++; + } + } + } + } + + MPI_Allreduce(&niswap_local,&niswap,1,MPI_INT,MPI_SUM,world); + MPI_Scan(&niswap_local,&niswap_before,1,MPI_INT,MPI_SUM,world); + niswap_before -= niswap_local; +} + +/* ---------------------------------------------------------------------- */ + +int FixNeighborSwap::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/) +{ + int i,j,m; + + int *type = atom->type; + double *q = atom->q; + + m = 0; + + if (atom->q_flag) { + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = type[j]; + buf[m++] = q[j]; + } + } else { + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = type[j]; + } + } + + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixNeighborSwap::unpack_forward_comm(int n, int first, double *buf) +{ + int i,m,last; + + int *type = atom->type; + double *q = atom->q; + + m = 0; + last = first + n; + + if (atom->q_flag) { + for (i = first; i < last; i++) { + type[i] = static_cast (buf[m++]); + q[i] = buf[m++]; + } + } else { + for (i = first; i < last; i++) + type[i] = static_cast (buf[m++]); + } +} + +/* ---------------------------------------------------------------------- + return acceptance ratio +------------------------------------------------------------------------- */ + +double FixNeighborSwap::compute_vector(int n) +{ + if (n == 0) return nswap_attempts; + if (n == 1) return nswap_successes; + return 0.0; +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based arrays +------------------------------------------------------------------------- */ + +double FixNeighborSwap::memory_usage() +{ + double bytes = (double)atom_swap_nmax * sizeof(int); + return bytes; +} + +/* ---------------------------------------------------------------------- + pack entire state of Fix into one write +------------------------------------------------------------------------- */ + +void FixNeighborSwap::write_restart(FILE *fp) +{ + int n = 0; + double list[6]; + list[n++] = random_equal->state(); + list[n++] = random_unequal->state(); + list[n++] = ubuf(next_reneighbor).d; + list[n++] = nswap_attempts; + list[n++] = nswap_successes; + list[n++] = ubuf(update->ntimestep).d; + + if (comm->me == 0) { + int size = n * sizeof(double); + fwrite(&size,sizeof(int),1,fp); + fwrite(list,sizeof(double),n,fp); + } +} + +/* ---------------------------------------------------------------------- + use state info from restart file to restart the Fix +------------------------------------------------------------------------- */ + +void FixNeighborSwap::restart(char *buf) +{ + int n = 0; + double *list = (double *) buf; + + seed = static_cast (list[n++]); + random_equal->reset(seed); + + seed = static_cast (list[n++]); + random_unequal->reset(seed); + + next_reneighbor = (bigint) ubuf(list[n++]).i; + + nswap_attempts = static_cast(list[n++]); + nswap_successes = static_cast(list[n++]); + + bigint ntimestep_restart = (bigint) ubuf(list[n++]).i; + if (ntimestep_restart != update->ntimestep) + error->all(FLERR,"Must not reset timestep when restarting fix neighbor/swap"); +} diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h new file mode 100755 index 0000000000..1413de2ef8 --- /dev/null +++ b/src/MC/fix_neighbor_swap.h @@ -0,0 +1,146 @@ +/* -*- 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(neighbor/swap,FixNeighborSwap); +// clang-format on +#else + +#ifndef LMP_FIX_NEIGH_SWAP_H +#define LMP_FIX_NEIGH_SWAP_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixNeighborSwap : public Fix { + public: + FixNeighborSwap(class LAMMPS *, int, char **); + ~FixNeighborSwap(); + int setmask(); + void init(); + void pre_exchange(); + int pack_forward_comm(int, int *, double *, int, int *); + void unpack_forward_comm(int, int, double *); + double compute_vector(int); + double memory_usage(); + void write_restart(FILE *); + void restart(char *); + + private: + int nevery, seed; + int ke_flag; // yes = conserve ke, no = do not conserve ke + int diff_flag; // yes = simulate diffusion of central atom, no = swap only to certain types + int rates_flag; // yes = use modified type rates, no = swap rates are equivilent across types + int voro_flag; // yes = use given voronoi calculation, no = use internal voronoi calculation + int ncycles; + int niswap, njswap; // # of i,j swap atoms on all procs + int niswap_local, njswap_local; // # of swap atoms on this proc + int niswap_before, njswap_before; // # of swap atoms on procs < this proc + // int global_i_ID; // global id of selected i atom + class Region *region; // swap region + char *idregion; // swap region id + + int nswaptypes; + int jtype_selected; + int id_center; + double x_center; + double y_center; + double z_center; + int *type_list; + double *rate_list; + + double nswap_attempts; + double nswap_successes; + + bool unequal_cutoffs; + + int atom_swap_nmax; + double beta; + double local_probability; // Total swap probability stored on this proc + double global_probability; // Total swap probability across all proc + double prev_probability; // Swap probability on proc < this proc + double *qtype; + double energy_stored; + double **sqrt_mass_ratio; + double **voro_neighbor_list; + int *local_swap_iatom_list; + int *local_swap_neighbor_list; + int *local_swap_type_list; // Type list index of atoms stored on this proc + double *local_swap_probability; + + + class RanPark *random_equal; + class RanPark *random_unequal; + + class Compute *c_voro; + class Compute *c_pe; + + void options(int, char **); + int attempt_swap(); + double energy_full(); + int pick_i_swap_atom(); + int pick_j_swap_neighbor(int); + double get_distance(double[3], double[3]); + void build_i_neighbor_list(int); + void update_iswap_atoms_list(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Region ID for fix neighbor/swap does not exist + +Self-explanatory. + +E: Must specify at least 2 types in fix neighbor/swap command + +Self-explanatory. + +E: Need nswaptypes mu values in fix neighbor/swap command + +Self-explanatory. + +E: Invalid atom type in fix neighbor/swap command + +The atom type specified in the neighbor/swap command does not exist. + +E: All atoms of a swapped type must have the same charge. + +Self-explanatory. + +E: At least one atom of each swapped type must be present to define charges. + +Self-explanatory. + +E: All atoms of a swapped type must have same charge. + +Self-explanatory. + +E: Cannot do neighbor/swap on atoms in atom_modify first group + +This is a restriction due to the way atoms are organized in a list to +enable the atom_modify first command. + +*/ From 82569f444826aaad99ff7bd4cdd8d66d1a389f32 Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Thu, 19 Dec 2024 11:29:19 -0700 Subject: [PATCH 011/396] Added documentation files --- doc/src/Commands_fix.rst | 1 + doc/src/fix.rst | 1 + doc/src/fix_neighbor_swap.rst | 169 ++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 doc/src/fix_neighbor_swap.rst diff --git a/doc/src/Commands_fix.rst b/doc/src/Commands_fix.rst index 04d1a9969a..cbadc09880 100644 --- a/doc/src/Commands_fix.rst +++ b/doc/src/Commands_fix.rst @@ -110,6 +110,7 @@ OPT. * :doc:`mvv/tdpd ` * :doc:`neb ` * :doc:`neb/spin ` + * :doc:`neighbor/swap ` * :doc:`nonaffine/displacement ` * :doc:`nph (ko) ` * :doc:`nph/asphere (o) ` diff --git a/doc/src/fix.rst b/doc/src/fix.rst index 9af607601b..a4a9ac4a86 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -289,6 +289,7 @@ accelerated styles exist. * :doc:`mvv/tdpd ` - constant temperature DPD using the modified velocity-Verlet algorithm * :doc:`neb ` - nudged elastic band (NEB) spring forces * :doc:`neb/spin ` - nudged elastic band (NEB) spring forces for spins +* :doc:`neighbor/swap ` - kinetic Monte Calo atom swapping * :doc:`nonaffine/displacement ` - calculate nonaffine displacement of atoms * :doc:`nph ` - constant NPH time integration via Nose/Hoover * :doc:`nph/asphere ` - NPH for aspherical particles diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst new file mode 100644 index 0000000000..a3eb1c6d82 --- /dev/null +++ b/doc/src/fix_neighbor_swap.rst @@ -0,0 +1,169 @@ +.. index:: fix neighbor/swap + +fix neighbor/swap command +===================== + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID neighbor/swap N X seed T R keyword values ... + +* ID, group-ID are documented in :doc:`fix ` command +* neighbor/swap = style name of this fix command +* N = invoke this fix every N steps +* X = number of swaps to attempt every N steps +* seed = random # seed (positive integer) +* T = scaling temperature of the MC swaps (temperature units) +* R = scaling swap probability of the MC swaps (distance units) +* one or more keyword/value pairs may be appended to args +* keyword = *types* or *mu* or *ke* or *semi-grand* or *region* + + .. parsed-literal:: + + *types* values = two or more atom types (1-Ntypes or type label) + *ke* value = *no* or *yes* + *no* = no conservation of kinetic energy after atom swaps + *yes* = kinetic energy is conserved after atom swaps + *region* value = region-ID + region-ID = ID of region to use as an exchange/move volume + *diff* values = one atom type + *voro* values = valid voronoi compute id (compute voronoi/atom) + *rates* values = Ntype values to conduct variable diffusion for different atom types (unitless) + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix mc all neighbor/swap 10 160 15238 1000.0 diff 2 voro voroN + fix myFix all neighbor/swap 100 1 12345 298.0 region my_swap_region types 5 6 voro voroN + fix kmc all neighbor/swap 1 100 345 1.0 diff 3 rates 3 1 6 voro voroN + +Description +""""""""""" + +Computes MC evaluations to enable kinetic Monte Carlo (kMC) behavior +during MD simulation through only allowing neighboring atom swaps. +Neighboring atoms are selected using a Voronoi tesselation approach. This +implementation is as described in :ref:`(Tavenner) `. + +The fix is called every *N* timesteps and attempts *X* swaps. The system +is initialized with a random seed, using a temperature *T* for evaluating +the MC energy swaps. The distance-based probability is weighted according +to *R* which sets the radius :math:`r_0` for the weighting + +.. math:: + + p_{ij} = e^{(\frac{r_{ij}}{r_0})^2} + +where :math:`p_{ij}` is the probability of selecting atoms :math:`i` and :math:`j` for an +evaluated swap. + +The keyword *types* is submitted with two or more atom types as the value. +Atoms of the first atom type are swapped with valid neighbors of all the remaining +atom types. + +The keyword *diff* is used for implementation of simulated diffusion of a given atom type +as given by *diff type*. This command selects all atom types as acceptable swap types to a +centrally selected atom of type *type*. This includes the atom type specified by the diff +keyword to account for self-diffusion hops of an atom type with itself. + +Keyword *voro* is currently required, and is implemented as + +.. code-block:: LAMMPS + voro compute-ID + +where *compute-ID* is the ID of a corresponding Voronoi computation with neighbor list, i.e. + +.. code-block:: LAMMPS + + compute compute-ID group-ID voronoi/atom neighbors yes + +The group selected for computing *voro* should correspond to all the potential atoms to +be swapped at the initial step, i.e. + +.. code-block:: LAMMPS + group group-ID type 2 + +for using *fix neighbor/swap* with *diff 2*. + +The keyword *rates* can modify the swap rate for each swapped type by values +where the adjusted rates values are given in order of increasing atom type. +The number of rates provided must equal the number of atom types in the simulaton. +In the third provided example above, a simulation is conducted with three atom types +where the third atom type is the one sampled for attempted swaps. All three atom +types are considered valid swaps, but atoms of type 1 will be selected three times +as often as atoms of type 2. Conversely, atoms of type 3 are six times more likely to +be selected than atoms of type two and twice as likely as atoms of type 1. + +Finally, the *region* keyword is implemented as in other atomic fixes, where +the *region region-ID* command indicates that atom swaps only be considered in the area +given by *region-ID*. If only atoms of certain groups are expected to be in this region, +the corresponding compute voronoi command can be adjusted accordingly. + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +This fix writes the state of the fix to :doc:`binary restart files +`. This includes information about the random number generator +seed, the next timestep for MC exchanges, the number of exchange +attempts and successes, etc. See the :doc:`read_restart ` +command for info on how to re-specify a fix in an input script that +reads a restart file, so that the operation of the fix continues in an +uninterrupted fashion. + +None of the :doc:`fix_modify ` options are relevant to this +fix. + +This fix computes a global vector of length 2, which can be accessed +by various :doc:`output commands `. The vector values are +the following global cumulative quantities: + + #. swap attempts + #. swap accepts + +The vector values calculated by this fix are "intensive". + +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 +"""""""""""" + +This fix is part of the MC package. It is only enabled if LAMMPS was +built with that package. See the :doc:`Build package ` +doc page for more info. + +Voronoi compute must be enabled on build. See :doc:`compute voronoi/atom `. +A vaild voronoi command which returns neighboring atoms must be used +and referenced with the *voro* keyword. + +When this fix is used with a :doc:`hybrid pair style ` +system, only swaps between atom types of the same sub-style (or +combination of sub-styles) are permitted. + +If this fix is used with systems that do not have per-type masses +(e.g. atom style sphere), the ke flag must be set to off since the implemented +algorithm will not be able to re-scale velocity properly. + +Related commands +"""""""""""""""" + +:doc:`fix nvt `, :doc:`compute voronoi/atom ` +:doc:`delete_atoms `, :doc:`fix gcmc `, +:doc:`fix atom/swap `, :doc:`fix mol/swap `, :doc:`fix sgcmc ` + +Default +""""""" + +The option defaults are *ke* = yes, *diff* = no, *rates* = 1 for +all atom types. + +---------- + +.. Tavenner: + +**(Tavenner)** J Tavenner, M Mendelev, J Lawson, Computational Materials Science, 218, 111929 (2023). From 4004d263048f914dc93f3332cdbd2106ecbe9163 Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Thu, 19 Dec 2024 12:57:17 -0700 Subject: [PATCH 012/396] Spelling check fix --- src/MC/fix_neighbor_swap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp index 52730ee6f5..9bbb777d92 100755 --- a/src/MC/fix_neighbor_swap.cpp +++ b/src/MC/fix_neighbor_swap.cpp @@ -103,7 +103,7 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : options(narg-7,&arg[7]); - if (voro_flag != 1) error->all(FLERR,"Voro Compute Required for fix neighbor/swap command"); + if (voro_flag != 1) error->all(FLERR,"Voronoi compute required for fix neighbor/swap command"); // random number generator, same for all procs @@ -194,7 +194,7 @@ void FixNeighborSwap::options(int narg, char **arg) iarg++; } } else if (strcmp(arg[iarg],"voro") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); int icompute = modify->find_compute(utils::strdup(arg[iarg+1])); @@ -208,7 +208,7 @@ void FixNeighborSwap::options(int narg, char **arg) voro_flag = 1; iarg += 2; } else if (strcmp(arg[iarg],"diff") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); if (nswaptypes != 0) error->all(FLERR,"Illegal fix neighbor/swap command"); type_list[nswaptypes] = utils::numeric(FLERR,arg[iarg+1],false,lmp); diff_flag = 1; From c847ac1fd45259e4bec3618d2ee2153a213a77fe Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Thu, 19 Dec 2024 13:37:30 -0700 Subject: [PATCH 013/396] Removed trailing whitespace --- doc/src/fix_neighbor_swap.rst | 12 ++++++------ src/MC/fix_neighbor_swap.cpp | 30 +++++++++++++++--------------- src/MC/fix_neighbor_swap.h | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index a3eb1c6d82..e97b8bcbf2 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -70,11 +70,11 @@ as given by *diff type*. This command selects all atom types as acceptable swap centrally selected atom of type *type*. This includes the atom type specified by the diff keyword to account for self-diffusion hops of an atom type with itself. -Keyword *voro* is currently required, and is implemented as +Keyword *voro* is currently required, and is implemented as .. code-block:: LAMMPS voro compute-ID - + where *compute-ID* is the ID of a corresponding Voronoi computation with neighbor list, i.e. .. code-block:: LAMMPS @@ -89,17 +89,17 @@ be swapped at the initial step, i.e. for using *fix neighbor/swap* with *diff 2*. -The keyword *rates* can modify the swap rate for each swapped type by values -where the adjusted rates values are given in order of increasing atom type. +The keyword *rates* can modify the swap rate for each swapped type by values +where the adjusted rates values are given in order of increasing atom type. The number of rates provided must equal the number of atom types in the simulaton. In the third provided example above, a simulation is conducted with three atom types where the third atom type is the one sampled for attempted swaps. All three atom types are considered valid swaps, but atoms of type 1 will be selected three times as often as atoms of type 2. Conversely, atoms of type 3 are six times more likely to -be selected than atoms of type two and twice as likely as atoms of type 1. +be selected than atoms of type two and twice as likely as atoms of type 1. Finally, the *region* keyword is implemented as in other atomic fixes, where -the *region region-ID* command indicates that atom swaps only be considered in the area +the *region region-ID* command indicates that atom swaps only be considered in the area given by *region-ID*. If only atoms of certain groups are expected to be in this region, the corresponding compute voronoi command can be adjusted accordingly. diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp index 9bbb777d92..1bd9cbbc02 100755 --- a/src/MC/fix_neighbor_swap.cpp +++ b/src/MC/fix_neighbor_swap.cpp @@ -195,7 +195,7 @@ void FixNeighborSwap::options(int narg, char **arg) } } else if (strcmp(arg[iarg],"voro") == 0) { if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); - + int icompute = modify->find_compute(utils::strdup(arg[iarg+1])); if (icompute < 0) error->all(FLERR,"Could not find neighbor compute ID"); @@ -481,7 +481,7 @@ int FixNeighborSwap::attempt_swap() } energy_stored = energy_after; - // utils::logmesg(lmp,"Swap accepted\n"); + // utils::logmesg(lmp,"Swap accepted\n"); // Swap atom groups if successful swap // int groupi = atom->mask[i]; @@ -498,7 +498,7 @@ int FixNeighborSwap::attempt_swap() // do not need to re-call comm->borders() and rebuild neighbor list // since will be done on next cycle or in Verlet when this fix finishes - // utils::logmesg(lmp,"Swap not accepted\n"); + // utils::logmesg(lmp,"Swap not accepted\n"); if ( i >= 0 ) { atom->type[i] = itype; @@ -613,7 +613,7 @@ double FixNeighborSwap::get_distance(double* i, double* j) // r_x = i[0] - j[0]; // r_y = i[1] - j[1]; // r_z = i[2] - j[2]; - + // // Domain::minimum_image(r_x, r_y, r_z); // double r = sqrt(pow(r_x, 2.) + // pow(r_y, 2.) + @@ -648,7 +648,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) memory->sfree(local_swap_probability); local_swap_probability = (double *) memory->smalloc(atom_swap_nmax*sizeof(double), "MCSWAP:local_swap_probability_list"); - + memory->sfree(local_swap_type_list); local_swap_type_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), "MCSWAP:local_swap_type_list"); @@ -656,7 +656,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Compute voronoi and access neighbor list c_voro->compute_local(); - + voro_neighbor_list = c_voro->array_local; njswap_local = 0; local_probability = 0.0; @@ -664,7 +664,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // utils::logmesg(lmp,"Searching for atom {}\n",id_center); for (int n = 0; n < c_voro->size_local_rows; n++){ - + int temp_j_id = -1; int temp_j = -1; @@ -708,13 +708,13 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if (atom->mask[temp_j] & groupbit) { if (diff_flag) { // Calculate distance from i to each j, adjust probability of selection - + // Get distance if own centr atom double r = INFINITY; if ( i_center >= 0 ){ double r = get_distance(x[temp_j], x[i_center]); } - + // Get local id of ghost center atom when ghost for (int i=nlocal; i < nlocal+nghost; i++){ if ( (id[i] == id_center) && @@ -743,7 +743,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if ( i_center >= 0 ){ double r = get_distance(x[temp_j], x[i_center]); } - + // Get local id of ghost center atom when ghost for (int i=nlocal; i < nlocal+nghost; i++){ if ( (id[i] == id_center) && @@ -776,7 +776,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if ( i_center >= 0 ){ r = get_distance(x[temp_j], x[i_center]); } - + // Get local id of ghost center atoms // if ( i_center < 0 ){ // utils::logmesg(lmp,"Initial distance {}\n", r); @@ -788,7 +788,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) } } // } - + // utils::logmesg(lmp,"Final distance {}\n", r); if (rates_flag) { @@ -797,7 +797,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); } local_probability += local_swap_probability[njswap_local]; - + local_swap_type_list[njswap_local] = type[temp_j]; local_swap_neighbor_list[njswap_local] = temp_j; njswap_local++; @@ -810,7 +810,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if ( i_center >= 0 ){ double r = get_distance(x[temp_j], x[i_center]); } - + // Get local id of ghost center atom when ghost for (int i=nlocal; i < nlocal+nghost; i++){ if ( (id[i] == id_center) && @@ -823,7 +823,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); } else { local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); - } + } local_probability += local_swap_probability[njswap_local]; local_swap_type_list[njswap_local] = jswaptype; diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h index 1413de2ef8..e53eb9c1c3 100755 --- a/src/MC/fix_neighbor_swap.h +++ b/src/MC/fix_neighbor_swap.h @@ -63,7 +63,7 @@ class FixNeighborSwap : public Fix { double nswap_attempts; double nswap_successes; - + bool unequal_cutoffs; int atom_swap_nmax; @@ -79,7 +79,7 @@ class FixNeighborSwap : public Fix { int *local_swap_neighbor_list; int *local_swap_type_list; // Type list index of atoms stored on this proc double *local_swap_probability; - + class RanPark *random_equal; class RanPark *random_unequal; From 49b2b978e67cd8df42dfddfa7ad5faaa57443fdc Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:20:51 -0500 Subject: [PATCH 014/396] build system updates to skip fix neighbor/swap if VORONOI package is not installed --- cmake/Modules/Packages/MC.cmake | 10 ++++++++++ src/.gitignore | 2 ++ src/MC/Install.sh | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/Packages/MC.cmake b/cmake/Modules/Packages/MC.cmake index f162254558..2a72a895cf 100644 --- a/cmake/Modules/Packages/MC.cmake +++ b/cmake/Modules/Packages/MC.cmake @@ -7,3 +7,13 @@ if(NOT PKG_MANYBODY) list(REMOVE_ITEM LAMMPS_SOURCES ${LAMMPS_SOURCE_DIR}/MC/fix_sgcmc.cpp) set_property(TARGET lammps PROPERTY SOURCES "${LAMMPS_SOURCES}") endif() + +# fix neighbor/swap may only be installed if also the VORONOI package is installed +if(NOT PKG_VORONOI) + get_property(LAMMPS_FIX_HEADERS GLOBAL PROPERTY FIX) + list(REMOVE_ITEM LAMMPS_FIX_HEADERS ${LAMMPS_SOURCE_DIR}/MC/fix_neighbor_swap.h) + set_property(GLOBAL PROPERTY FIX "${LAMMPS_FIX_HEADERS}") + get_target_property(LAMMPS_SOURCES lammps SOURCES) + list(REMOVE_ITEM LAMMPS_SOURCES ${LAMMPS_SOURCE_DIR}/MC/fix_neighbor_swap.cpp) + set_property(TARGET lammps PROPERTY SOURCES "${LAMMPS_SOURCES}") +endif() diff --git a/src/.gitignore b/src/.gitignore index f0554e3bfe..0f0e3759c9 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -912,6 +912,8 @@ /fix_msst.h /fix_neb.cpp /fix_neb.h +/fix_neighbor_swap.cpp +/fix_neighbor_swap.h /fix_nh_asphere.cpp /fix_nh_asphere.h /fix_nph_asphere.cpp diff --git a/src/MC/Install.sh b/src/MC/Install.sh index 9a0095fd34..efe6b7c07b 100755 --- a/src/MC/Install.sh +++ b/src/MC/Install.sh @@ -51,8 +51,8 @@ action fix_charge_regulation.cpp action fix_charge_regulation.h action fix_gcmc.cpp action fix_gcmc.h -action fix_neighbor_swap.cpp -action fix_neighbor_swap.h +action fix_neighbor_swap.cpp compute_voronoi_atom.cpp +action fix_neighbor_swap.h compute_voronoi_atom.h action fix_mol_swap.cpp action fix_mol_swap.h action fix_sgcmc.cpp pair_eam.cpp From b05172fe9687ba25b65efbb6cd6c47c980d360b1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:21:35 -0500 Subject: [PATCH 015/396] spelling fixes and documentation formatting corrections --- doc/src/fix.rst | 2 +- doc/src/fix_neighbor_swap.rst | 90 ++++++++++++--------- doc/utils/sphinx-config/false_positives.txt | 1 + 3 files changed, 52 insertions(+), 41 deletions(-) diff --git a/doc/src/fix.rst b/doc/src/fix.rst index a4a9ac4a86..ae02118bec 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -289,7 +289,7 @@ accelerated styles exist. * :doc:`mvv/tdpd ` - constant temperature DPD using the modified velocity-Verlet algorithm * :doc:`neb ` - nudged elastic band (NEB) spring forces * :doc:`neb/spin ` - nudged elastic band (NEB) spring forces for spins -* :doc:`neighbor/swap ` - kinetic Monte Calo atom swapping +* :doc:`neighbor/swap ` - kinetic Monte Carlo (kMC) atom swapping * :doc:`nonaffine/displacement ` - calculate nonaffine displacement of atoms * :doc:`nph ` - constant NPH time integration via Nose/Hoover * :doc:`nph/asphere ` - NPH for aspherical particles diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index e97b8bcbf2..898957c56c 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -1,7 +1,7 @@ .. index:: fix neighbor/swap fix neighbor/swap command -===================== +========================= Syntax """""" @@ -50,61 +50,69 @@ Neighboring atoms are selected using a Voronoi tesselation approach. This implementation is as described in :ref:`(Tavenner) `. The fix is called every *N* timesteps and attempts *X* swaps. The system -is initialized with a random seed, using a temperature *T* for evaluating -the MC energy swaps. The distance-based probability is weighted according -to *R* which sets the radius :math:`r_0` for the weighting +is initialized with a random seed, using a temperature *T* for +evaluating the MC energy swaps. The distance-based probability is +weighted according to *R* which sets the radius :math:`r_0` for the +weighting .. math:: p_{ij} = e^{(\frac{r_{ij}}{r_0})^2} -where :math:`p_{ij}` is the probability of selecting atoms :math:`i` and :math:`j` for an -evaluated swap. +where :math:`p_{ij}` is the probability of selecting atoms :math:`i` and +:math:`j` for an evaluated swap. -The keyword *types* is submitted with two or more atom types as the value. -Atoms of the first atom type are swapped with valid neighbors of all the remaining -atom types. +The keyword *types* is submitted with two or more atom types as the +value. Atoms of the first atom type are swapped with valid neighbors of +all the remaining atom types. -The keyword *diff* is used for implementation of simulated diffusion of a given atom type -as given by *diff type*. This command selects all atom types as acceptable swap types to a -centrally selected atom of type *type*. This includes the atom type specified by the diff -keyword to account for self-diffusion hops of an atom type with itself. +The keyword *diff* is used for implementation of simulated diffusion of +a given atom type as given by *diff type*. This command selects all atom +types as acceptable swap types to a centrally selected atom of type +*type*. This includes the atom type specified by the diff keyword to +account for self-diffusion hops of an atom type with itself. Keyword *voro* is currently required, and is implemented as .. code-block:: LAMMPS - voro compute-ID -where *compute-ID* is the ID of a corresponding Voronoi computation with neighbor list, i.e. + voro compute-ID + +where *compute-ID* is the ID of a corresponding Voronoi computation with +neighbor list, i.e. .. code-block:: LAMMPS compute compute-ID group-ID voronoi/atom neighbors yes -The group selected for computing *voro* should correspond to all the potential atoms to -be swapped at the initial step, i.e. +The group selected for computing *voro* should correspond to all the +potential atoms to be swapped at the initial step, i.e. .. code-block:: LAMMPS - group group-ID type 2 + + group group-ID type 2 for using *fix neighbor/swap* with *diff 2*. -The keyword *rates* can modify the swap rate for each swapped type by values -where the adjusted rates values are given in order of increasing atom type. -The number of rates provided must equal the number of atom types in the simulaton. -In the third provided example above, a simulation is conducted with three atom types -where the third atom type is the one sampled for attempted swaps. All three atom -types are considered valid swaps, but atoms of type 1 will be selected three times -as often as atoms of type 2. Conversely, atoms of type 3 are six times more likely to -be selected than atoms of type two and twice as likely as atoms of type 1. +The keyword *rates* can modify the swap rate for each swapped type by +values where the adjusted rates values are given in order of increasing +atom type. The number of rates provided must equal the number of atom +types in the simulation. In the third provided example above, a +simulation is conducted with three atom types where the third atom type +is the one sampled for attempted swaps. All three atom types are +considered valid swaps, but atoms of type 1 will be selected three times +as often as atoms of type 2. Conversely, atoms of type 3 are six times +more likely to be selected than atoms of type two and twice as likely as +atoms of type 1. -Finally, the *region* keyword is implemented as in other atomic fixes, where -the *region region-ID* command indicates that atom swaps only be considered in the area -given by *region-ID*. If only atoms of certain groups are expected to be in this region, -the corresponding compute voronoi command can be adjusted accordingly. +Finally, the *region* keyword is implemented as in other atomic fixes, +where the *region region-ID* command indicates that atom swaps only be +considered in the area given by *region-ID*. If only atoms of certain +groups are expected to be in this region, the corresponding compute +voronoi command can be adjusted accordingly. Restart, fix_modify, output, run start/stop, minimize info -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" This fix writes the state of the fix to :doc:`binary restart files `. This includes information about the random number generator @@ -135,10 +143,11 @@ Restrictions This fix is part of the MC package. It is only enabled if LAMMPS was built with that package. See the :doc:`Build package ` -doc page for more info. +doc page for more info. Also this fix requires that the +:ref:`VORONOI package ` is installed, otherwise the fix +will not be compiled. -Voronoi compute must be enabled on build. See :doc:`compute voronoi/atom `. -A vaild voronoi command which returns neighboring atoms must be used +A valid voronoi command which returns neighboring atoms must be used and referenced with the *voro* keyword. When this fix is used with a :doc:`hybrid pair style ` @@ -146,24 +155,25 @@ system, only swaps between atom types of the same sub-style (or combination of sub-styles) are permitted. If this fix is used with systems that do not have per-type masses -(e.g. atom style sphere), the ke flag must be set to off since the implemented -algorithm will not be able to re-scale velocity properly. +(e.g. atom style sphere), the ke flag must be set to off since the +implemented algorithm will not be able to re-scale velocity properly. Related commands """""""""""""""" :doc:`fix nvt `, :doc:`compute voronoi/atom ` :doc:`delete_atoms `, :doc:`fix gcmc `, -:doc:`fix atom/swap `, :doc:`fix mol/swap `, :doc:`fix sgcmc ` +:doc:`fix atom/swap `, :doc:`fix mol/swap `, +:doc:`fix sgcmc ` Default """"""" -The option defaults are *ke* = yes, *diff* = no, *rates* = 1 for -all atom types. +The option defaults are *ke* = yes, *diff* = no, *rates* = 1 for all +atom types. ---------- -.. Tavenner: +.. _Tavenner: **(Tavenner)** J Tavenner, M Mendelev, J Lawson, Computational Materials Science, 218, 111929 (2023). diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 67db18a17d..4d2b6f5d68 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -1812,6 +1812,7 @@ Kloss Kloza kmax Kmax +kMC KMP kmu Knizhnik From 8a89d2fcf6f19b932abc20c440ea2016ac43fe79 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:22:02 -0500 Subject: [PATCH 016/396] no more error lists in headers --- src/MC/fix_neighbor_swap.h | 43 -------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h index e53eb9c1c3..df75505a6d 100755 --- a/src/MC/fix_neighbor_swap.h +++ b/src/MC/fix_neighbor_swap.h @@ -101,46 +101,3 @@ class FixNeighborSwap : public Fix { #endif #endif - -/* ERROR/WARNING messages: - -E: Illegal ... command - -Self-explanatory. Check the input script syntax and compare to the -documentation for the command. You can use -echo screen as a -command-line option when running LAMMPS to see the offending line. - -E: Region ID for fix neighbor/swap does not exist - -Self-explanatory. - -E: Must specify at least 2 types in fix neighbor/swap command - -Self-explanatory. - -E: Need nswaptypes mu values in fix neighbor/swap command - -Self-explanatory. - -E: Invalid atom type in fix neighbor/swap command - -The atom type specified in the neighbor/swap command does not exist. - -E: All atoms of a swapped type must have the same charge. - -Self-explanatory. - -E: At least one atom of each swapped type must be present to define charges. - -Self-explanatory. - -E: All atoms of a swapped type must have same charge. - -Self-explanatory. - -E: Cannot do neighbor/swap on atoms in atom_modify first group - -This is a restriction due to the way atoms are organized in a list to -enable the atom_modify first command. - -*/ From 3c0d4c8e145140fac912619da6e15bebadcddaff Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:36:36 -0500 Subject: [PATCH 017/396] add versionadded tag --- doc/src/fix_neighbor_swap.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index 898957c56c..3c97400d3f 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -44,6 +44,8 @@ Examples Description """"""""""" +.. versionadded:: TBD + Computes MC evaluations to enable kinetic Monte Carlo (kMC) behavior during MD simulation through only allowing neighboring atom swaps. Neighboring atoms are selected using a Voronoi tesselation approach. This From 42b6308e2669ec7d8bcfdbc6c56ccf4505abf334 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:37:22 -0500 Subject: [PATCH 018/396] remove commented out debug code, replace pow(x,2.0) with MathSpecial::square() --- src/MC/fix_neighbor_swap.cpp | 174 +++++++++-------------------------- 1 file changed, 44 insertions(+), 130 deletions(-) diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp index 1bd9cbbc02..703207783a 100755 --- a/src/MC/fix_neighbor_swap.cpp +++ b/src/MC/fix_neighbor_swap.cpp @@ -31,6 +31,7 @@ #include "group.h" #include "improper.h" #include "kspace.h" +#include "math_special.h" #include "memory.h" #include "modify.h" #include "neighbor.h" @@ -68,9 +69,7 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : sqrt_mass_ratio(nullptr), local_swap_iatom_list(nullptr), random_equal(nullptr), random_unequal(nullptr), c_pe(nullptr) { - if (narg < 10) error->all(FLERR,"Illegal fix neighbor/swap command"); - - // utils::logmesg(lmp,"Starting neighbor/swap\n"); + if (narg < 10) utils::missing_cmd_args(FLERR,"fix neighbor/swap", error); dynamic_group_allow = 1; @@ -88,11 +87,10 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : seed = utils::inumeric(FLERR,arg[5],false,lmp); double temperature = utils::numeric(FLERR,arg[6],false,lmp); - if (nevery <= 0) error->all(FLERR,"Illegal fix neighbor/swap command"); - if (ncycles < 0) error->all(FLERR,"Illegal fix neighbor/swap command"); - // if (nevery < ncycles) error->all(FLERR,"Illegal fix neighbor/swap command"); - if (seed <= 0) error->all(FLERR,"Illegal fix neighbor/swap command"); - if (temperature <= 0.0) error->all(FLERR,"Illegal fix neighbor/swap command"); + if (nevery <= 0) error->all(FLERR,"Illegal fix neighbor/swap command nevery value"); + if (ncycles < 0) error->all(FLERR,"Illegal fix neighbor/swap command ncycles value"); + if (seed <= 0) error->all(FLERR,"Illegal fix neighbor/swap command seed value"); + if (temperature <= 0.0) error->all(FLERR,"Illegal fix neighbor/swap command temperature value"); beta = 1.0 / (force->boltz * temperature); @@ -170,7 +168,6 @@ void FixNeighborSwap::options(int narg, char **arg) int iarg = 0; while (iarg < narg) { - // utils::logmesg(lmp,"Parsing Argument {}\n", arg[iarg]); if (strcmp(arg[iarg],"region") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); region = domain->get_region_by_id(arg[iarg+1]); @@ -216,7 +213,6 @@ void FixNeighborSwap::options(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"rates") == 0) { if (iarg+atom->ntypes >= narg) error->all(FLERR,"Illegal fix neighbor/swap command"); - // utils::logmesg(lmp,"Reading rates\n"); iarg++; int i = 0; while (iarg < narg) { @@ -246,7 +242,6 @@ int FixNeighborSwap::setmask() void FixNeighborSwap::init() { - // utils::logmesg(lmp,"Initializing neighbor/swap\n"); c_pe = modify->get_compute_by_id("thermo_pe"); int *type = atom->type; @@ -321,10 +316,7 @@ void FixNeighborSwap::init() int flagall; MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); - if (flagall) - error->all(FLERR,"Cannot do neighbor/swap on atoms in atom_modify first group"); - - // utils::logmesg(lmp,"Done Init\n"); + if (flagall) error->all(FLERR,"Cannot do neighbor/swap on atoms in atom_modify first group"); } } @@ -355,15 +347,10 @@ void FixNeighborSwap::pre_exchange() // attempt Ncycle atom swaps - // utils::logmesg(lmp,"Attempting Swap\n"); - int nsuccess = 0; update_iswap_atoms_list(); - // utils::logmesg(lmp,"Updated Atom i List\n"); for (int i = 0; i < ncycles; i++) nsuccess += attempt_swap(); - // utils::logmesg(lmp,"\n"); - // udpate MC stats nswap_attempts += ncycles; @@ -398,36 +385,17 @@ int FixNeighborSwap::attempt_swap() // build nearest-neighbor list based on atom i build_i_neighbor_list(i); - // utils::logmesg(lmp,"Built neighbor list with {} atoms\n",njswap); - if ( njswap <= 0 ) { - // utils::logmesg(lmp,"No valid neighbors found\n"); - return 0; - } + if ( njswap <= 0 ) return 0; // pick a neighbor atom j based on i neighbor list jtype_selected = -1; int j = pick_j_swap_neighbor(i); - // utils::logmesg(lmp,"Selected swap neighbor j\n"); int itype = type_list[0]; int jtype = jtype_selected; - // utils::logmesg(lmp,"Selected atom j type {}\n",jtype); - - // utils::logmesg(lmp,"Swapping local atoms {} and ",i); - // utils::logmesg(lmp,"{}\n",j); - - // if ( i >= 0 || j >= 0) { - // utils::logmesg(lmp,"Selected atom j type {}\n",jtype); - // utils::logmesg(lmp,"Swapping atoms {} and ",id[i]); - // utils::logmesg(lmp,"{}\n",id[j]); - // } - - // utils::logmesg(lmp,"Atom type {} and ",itype); - // utils::logmesg(lmp,"{}\n",jtype); // Accept swap if types are equal, no change to system - if ( itype == jtype ){ - // utils::logmesg(lmp,"Atoms have same type, no processing needed\n"); + if ( itype == jtype ) { return 1; } @@ -480,16 +448,6 @@ int FixNeighborSwap::attempt_swap() } } energy_stored = energy_after; - - // utils::logmesg(lmp,"Swap accepted\n"); - // Swap atom groups if successful swap - - // int groupi = atom->mask[i]; - // int groupj = atom->mask[j]; - - // atom->mask[i] = group->bitmask[groupj]; - // atom->mask[j] = group->bitmask[groupi]; - return 1; } @@ -498,8 +456,6 @@ int FixNeighborSwap::attempt_swap() // do not need to re-call comm->borders() and rebuild neighbor list // since will be done on next cycle or in Verlet when this fix finishes - // utils::logmesg(lmp,"Swap not accepted\n"); - if ( i >= 0 ) { atom->type[i] = itype; if (atom->q_flag) atom->q[i] = qtype[0]; @@ -529,7 +485,7 @@ double FixNeighborSwap::energy_full() if (force->bond) force->bond->compute(eflag,vflag); if (force->angle) force->angle->compute(eflag,vflag); if (force->dihedral) force->dihedral->compute(eflag,vflag); - if (force->improper) force->improper->compute(eflag,vflag); + if (force->improper) force->improper->compute(eflag,vflag); } if (force->kspace) force->kspace->compute(eflag,vflag); @@ -576,21 +532,17 @@ int FixNeighborSwap::pick_j_swap_neighbor(int i) // Generate random double from 0 to maximum global probability double selected_prob = static_cast (global_probability*random_equal->uniform()); - // utils::logmesg(lmp,"Local Probability {}\n",local_probability); - // Find which local swap atom corresponds to probability if ((selected_prob >= prev_probability) && - (selected_prob < prev_probability + local_probability)){ - // utils::logmesg(lmp,"Selected Probability {}\n",selected_prob); + (selected_prob < prev_probability + local_probability)) { double search_prob = selected_prob - prev_probability; - for (int n = 0; n < njswap_local; n++){ - if (search_prob > local_swap_probability[n]){ + for (int n = 0; n < njswap_local; n++) { + if (search_prob > local_swap_probability[n]) { search_prob -= local_swap_probability[n]; } else{ j = local_swap_neighbor_list[n]; jtype_selected_local = local_swap_type_list[n]; - // utils::logmesg(lmp,"Selecting Atom j type {}\n",jtype_selected_local); MPI_Allreduce(&jtype_selected_local,&jtype_selected,1,MPI_INT,MPI_MAX,world); return j; } @@ -598,7 +550,6 @@ int FixNeighborSwap::pick_j_swap_neighbor(int i) error->all(FLERR,"Did not select local neighbor swap atom"); } - // utils::logmesg(lmp,"Swap atom not found on processor\n"); MPI_Allreduce(&jtype_selected_local,&jtype_selected,1,MPI_INT,MPI_MAX,world); return j; } @@ -608,22 +559,9 @@ int FixNeighborSwap::pick_j_swap_neighbor(int i) double FixNeighborSwap::get_distance(double* i, double* j) { - // double r_x, r_y, r_z; - - // r_x = i[0] - j[0]; - // r_y = i[1] - j[1]; - // r_z = i[2] - j[2]; - - // // Domain::minimum_image(r_x, r_y, r_z); - // double r = sqrt(pow(r_x, 2.) + - // pow(r_y, 2.) + - // pow(r_z, 2.)); - - double r = sqrt(pow((i[0] - j[0]), 2.) + - pow((i[1] - j[1]), 2.) + - pow((i[2] - j[2]), 2.)); - - + double r = sqrt(MathSpecial::square((i[0] - j[0])) + + MathSpecial::square((i[1] - j[1])) + + MathSpecial::square((i[2] - j[2]))); return r; } @@ -661,19 +599,17 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) njswap_local = 0; local_probability = 0.0; - // utils::logmesg(lmp,"Searching for atom {}\n",id_center); - - for (int n = 0; n < c_voro->size_local_rows; n++){ + for (int n = 0; n < c_voro->size_local_rows; n++) { int temp_j_id = -1; int temp_j = -1; // Find local voronoi entry with selected central atom - if ( (int)voro_neighbor_list[n][0] == id_center ){ + if ( (int)voro_neighbor_list[n][0] == id_center ) { temp_j_id = voro_neighbor_list[n][1]; temp_j = -1; } else if ( ((int)voro_neighbor_list[n][1] == id_center) && - ( i_center < 0 ) ){ + ( i_center < 0 ) ) { temp_j_id = voro_neighbor_list[n][0]; temp_j = -1; } else { @@ -681,10 +617,9 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) } // Find which local atom corresponds to neighbor - for (int j = 0; j < nlocal; j++){ - if ( temp_j_id == id[j] ){ + for (int j = 0; j < nlocal; j++) { + if ( temp_j_id == id[j] ) { temp_j = j; - // utils::logmesg(lmp,"Found neighbor {}\n",id[j]); break; } } @@ -692,17 +627,6 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // If temp_j not on this processor, skip if ( temp_j < 0 ) continue; - // // If atom is already in local list, skip - // bool inlist = false; - // for ( int j = 0; j < njswap_local; j++ ){ - // if ( temp_j == local_swap_neighbor_list[j] ){ - // utils::logmesg(lmp,"Skipping atom {}, pair already counted\n",id[temp_j]); - // inlist = true; - // break; - // } - // } - // if (inlist) continue; - if (region) { if (region->match(x[temp_j][0],x[temp_j][1],x[temp_j][2]) == 1) { if (atom->mask[temp_j] & groupbit) { @@ -711,51 +635,49 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Get distance if own centr atom double r = INFINITY; - if ( i_center >= 0 ){ + if ( i_center >= 0 ) { double r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atom when ghost - for (int i=nlocal; i < nlocal+nghost; i++){ + for (int i=nlocal; i < nlocal+nghost; i++) { if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r) ){ + (get_distance(x[temp_j], x[i]) < r) ) { r = get_distance(x[temp_j], x[i]); } } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); } else { - local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); } local_probability += local_swap_probability[njswap_local]; - - // utils::logmesg(lmp,"Adding Atom j type {}\n",type[temp_j]); local_swap_type_list[njswap_local] = type[temp_j]; local_swap_neighbor_list[njswap_local] = temp_j; njswap_local++; } else { - for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++){ + for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++) { if (type[temp_j] == type_list[jswaptype]) { // Calculate distance from i to each j, adjust probability of selection // Get distance if own center atom double r = INFINITY; - if ( i_center >= 0 ){ + if ( i_center >= 0 ) { double r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atom when ghost - for (int i=nlocal; i < nlocal+nghost; i++){ + for (int i=nlocal; i < nlocal+nghost; i++) { if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r) ){ + (get_distance(x[temp_j], x[i]) < r) ) { r = get_distance(x[temp_j], x[i]); } } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); } else { - local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); } local_probability += local_swap_probability[njswap_local]; @@ -773,28 +695,20 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Calculate distance from i to each j, adjust probability of selection // Get distance if own center atom double r = INFINITY; - if ( i_center >= 0 ){ + if ( i_center >= 0 ) { r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atoms - // if ( i_center < 0 ){ - // utils::logmesg(lmp,"Initial distance {}\n", r); - for (int i=nlocal; i < nlocal+nghost; i++){ - if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r) ){ - r = get_distance(x[temp_j], x[i]); - // utils::logmesg(lmp,"Updated distance {}\n", r); - } + for (int i=nlocal; i < nlocal+nghost; i++) { + if ( (id[i] == id_center) && (get_distance(x[temp_j], x[i]) < r) ) + r = get_distance(x[temp_j], x[i]); } - // } - - // utils::logmesg(lmp,"Final distance {}\n", r); if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); } else{ - local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); } local_probability += local_swap_probability[njswap_local]; @@ -802,27 +716,27 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) local_swap_neighbor_list[njswap_local] = temp_j; njswap_local++; } else { - for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++){ + for (int jswaptype = 1; jswaptype < nswaptypes; jswaptype++) { if (type[temp_j] == type_list[jswaptype]) { // Calculate distance from i to each j, adjust probability of selection // Get distance if own center atom double r = INFINITY; - if ( i_center >= 0 ){ + if ( i_center >= 0 ) { double r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atom when ghost - for (int i=nlocal; i < nlocal+nghost; i++){ + for (int i=nlocal; i < nlocal+nghost; i++) { if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r) ){ + (get_distance(x[temp_j], x[i]) < r)) { r = get_distance(x[temp_j], x[i]); } } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); } else { - local_swap_probability[njswap_local] = exp(-pow((r/3.), 2.)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); } local_probability += local_swap_probability[njswap_local]; From 60b0ef68a60e1dccb5a7341f7c748985bd27f104 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:39:19 -0500 Subject: [PATCH 019/396] enable and apply clang-format --- src/MC/fix_neighbor_swap.cpp | 360 +++++++++++++++++------------------ src/MC/fix_neighbor_swap.h | 21 +- 2 files changed, 185 insertions(+), 196 deletions(-) diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp index 703207783a..95e74bee22 100755 --- a/src/MC/fix_neighbor_swap.cpp +++ b/src/MC/fix_neighbor_swap.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -23,6 +22,7 @@ #include "bond.h" #include "comm.h" #include "compute.h" +#include "compute_voronoi_atom.h" #include "dihedral.h" #include "domain.h" #include "error.h" @@ -39,37 +39,36 @@ #include "random_park.h" #include "region.h" #include "update.h" -#include "compute_voronoi_atom.h" -#include #include #include +#include #include using namespace LAMMPS_NS; using namespace FixConst; static const char cite_fix_neighbor_swap_c[] = - "fix neighbor/swap command: doi:10.1016/j.commatsci.2022.111929\n\n" - "@Article{Tavenner2023111929,\n" - " author = {Jacob P. Tavenner and Mikhail I. Mendelev and John W. Lawson},\n" - " title = {Molecular dynamics based kinetic Monte Carlo simulation for accelerated diffusion},\n" - " journal = {Computational Materials Science},\n" - " year = {2023},\n" - " volume = {218},\n" - " pages = {111929}\n" - " url = {https://www.sciencedirect.com/science/article/pii/S0927025622006401}\n" - "}\n\n"; + "fix neighbor/swap command: doi:10.1016/j.commatsci.2022.111929\n\n" + "@Article{Tavenner2023111929,\n" + " author = {Jacob P. Tavenner and Mikhail I. Mendelev and John W. Lawson},\n" + " title = {Molecular dynamics based kinetic Monte Carlo simulation for accelerated " + "diffusion},\n" + " journal = {Computational Materials Science},\n" + " year = {2023},\n" + " volume = {218},\n" + " pages = {111929}\n" + " url = {https://www.sciencedirect.com/science/article/pii/S0927025622006401}\n" + "}\n\n"; /* ---------------------------------------------------------------------- */ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg), region(nullptr), idregion(nullptr), type_list(nullptr), - qtype(nullptr), c_voro(nullptr), voro_neighbor_list(nullptr), - sqrt_mass_ratio(nullptr), local_swap_iatom_list(nullptr), - random_equal(nullptr), random_unequal(nullptr), c_pe(nullptr) + Fix(lmp, narg, arg), region(nullptr), idregion(nullptr), type_list(nullptr), qtype(nullptr), + c_voro(nullptr), voro_neighbor_list(nullptr), sqrt_mass_ratio(nullptr), + local_swap_iatom_list(nullptr), random_equal(nullptr), random_unequal(nullptr), c_pe(nullptr) { - if (narg < 10) utils::missing_cmd_args(FLERR,"fix neighbor/swap", error); + if (narg < 10) utils::missing_cmd_args(FLERR, "fix neighbor/swap", error); dynamic_group_allow = 1; @@ -82,34 +81,34 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : // required args - nevery = utils::inumeric(FLERR,arg[3],false,lmp); - ncycles = utils::inumeric(FLERR,arg[4],false,lmp); - seed = utils::inumeric(FLERR,arg[5],false,lmp); - double temperature = utils::numeric(FLERR,arg[6],false,lmp); + nevery = utils::inumeric(FLERR, arg[3], false, lmp); + ncycles = utils::inumeric(FLERR, arg[4], false, lmp); + seed = utils::inumeric(FLERR, arg[5], false, lmp); + double temperature = utils::numeric(FLERR, arg[6], false, lmp); - if (nevery <= 0) error->all(FLERR,"Illegal fix neighbor/swap command nevery value"); - if (ncycles < 0) error->all(FLERR,"Illegal fix neighbor/swap command ncycles value"); - if (seed <= 0) error->all(FLERR,"Illegal fix neighbor/swap command seed value"); - if (temperature <= 0.0) error->all(FLERR,"Illegal fix neighbor/swap command temperature value"); + if (nevery <= 0) error->all(FLERR, "Illegal fix neighbor/swap command nevery value"); + if (ncycles < 0) error->all(FLERR, "Illegal fix neighbor/swap command ncycles value"); + if (seed <= 0) error->all(FLERR, "Illegal fix neighbor/swap command seed value"); + if (temperature <= 0.0) error->all(FLERR, "Illegal fix neighbor/swap command temperature value"); beta = 1.0 / (force->boltz * temperature); - memory->create(type_list,atom->ntypes,"neighbor/swap:type_list"); - memory->create(rate_list,atom->ntypes,"neighbor/swap:rate_list"); + memory->create(type_list, atom->ntypes, "neighbor/swap:type_list"); + memory->create(rate_list, atom->ntypes, "neighbor/swap:rate_list"); // read options from end of input line - options(narg-7,&arg[7]); + options(narg - 7, &arg[7]); - if (voro_flag != 1) error->all(FLERR,"Voronoi compute required for fix neighbor/swap command"); + if (voro_flag != 1) error->all(FLERR, "Voronoi compute required for fix neighbor/swap command"); // random number generator, same for all procs - random_equal = new RanPark(lmp,seed); + random_equal = new RanPark(lmp, seed); // random number generator, not the same for all procs - random_unequal = new RanPark(lmp,seed); + random_unequal = new RanPark(lmp, seed); // set up reneighboring @@ -130,9 +129,10 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : // set comm size needed by this Fix - if (atom->q_flag) comm_forward = 2; - else comm_forward = 1; - + if (atom->q_flag) + comm_forward = 2; + else + comm_forward = 1; } /* ---------------------------------------------------------------------- */ @@ -158,7 +158,7 @@ FixNeighborSwap::~FixNeighborSwap() void FixNeighborSwap::options(int narg, char **arg) { - if (narg < 0) error->all(FLERR,"Illegal fix neighbor/swap command\n"); + if (narg < 0) error->all(FLERR, "Illegal fix neighbor/swap command\n"); ke_flag = 1; diff_flag = 0; @@ -168,64 +168,64 @@ void FixNeighborSwap::options(int narg, char **arg) int iarg = 0; while (iarg < narg) { - if (strcmp(arg[iarg],"region") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); - region = domain->get_region_by_id(arg[iarg+1]); - if (!region) error->all(FLERR,"Region ID for fix neighbor/swap does not exist"); + if (strcmp(arg[iarg], "region") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); + region = domain->get_region_by_id(arg[iarg + 1]); + if (!region) error->all(FLERR, "Region ID for fix neighbor/swap does not exist"); idregion = utils::strdup(arg[iarg + 1]); iarg += 2; - } else if (strcmp(arg[iarg],"ke") == 0) { - if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); - ke_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); + } else if (strcmp(arg[iarg], "ke") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); + ke_flag = utils::logical(FLERR, arg[iarg + 1], false, lmp); iarg += 2; - } else if (strcmp(arg[iarg],"types") == 0) { - if (iarg + 3 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); - if (diff_flag != 0) error->all(FLERR,"Illegal fix neighbor/swap command"); + } else if (strcmp(arg[iarg], "types") == 0) { + if (iarg + 3 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); + if (diff_flag != 0) error->all(FLERR, "Illegal fix neighbor/swap command"); iarg++; nswaptypes = 0; while (iarg < narg) { if (isalpha(arg[iarg][0])) break; - if (nswaptypes >= atom->ntypes) error->all(FLERR,"Illegal fix neighbor/swap command"); - type_list[nswaptypes] = utils::numeric(FLERR,arg[iarg],false,lmp); + if (nswaptypes >= atom->ntypes) error->all(FLERR, "Illegal fix neighbor/swap command"); + type_list[nswaptypes] = utils::numeric(FLERR, arg[iarg], false, lmp); nswaptypes++; iarg++; } - } else if (strcmp(arg[iarg],"voro") == 0) { - if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + } else if (strcmp(arg[iarg], "voro") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); - int icompute = modify->find_compute(utils::strdup(arg[iarg+1])); + int icompute = modify->find_compute(utils::strdup(arg[iarg + 1])); - if (icompute < 0) error->all(FLERR,"Could not find neighbor compute ID"); + if (icompute < 0) error->all(FLERR, "Could not find neighbor compute ID"); c_voro = modify->compute[icompute]; if (c_voro->local_flag == 0) - error->all(FLERR,"Neighbor compute does not compute local info"); + error->all(FLERR, "Neighbor compute does not compute local info"); if (c_voro->size_local_cols != 3) - error->all(FLERR,"Neighbor compute does not give i, j, size as expected"); + error->all(FLERR, "Neighbor compute does not give i, j, size as expected"); voro_flag = 1; iarg += 2; - } else if (strcmp(arg[iarg],"diff") == 0) { - if (iarg + 2 > narg) error->all(FLERR,"Illegal fix neighbor/swap command"); - if (nswaptypes != 0) error->all(FLERR,"Illegal fix neighbor/swap command"); - type_list[nswaptypes] = utils::numeric(FLERR,arg[iarg+1],false,lmp); + } else if (strcmp(arg[iarg], "diff") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); + if (nswaptypes != 0) error->all(FLERR, "Illegal fix neighbor/swap command"); + type_list[nswaptypes] = utils::numeric(FLERR, arg[iarg + 1], false, lmp); diff_flag = 1; nswaptypes++; iarg += 2; - } else if (strcmp(arg[iarg],"rates") == 0) { - if (iarg+atom->ntypes >= narg) error->all(FLERR,"Illegal fix neighbor/swap command"); + } else if (strcmp(arg[iarg], "rates") == 0) { + if (iarg + atom->ntypes >= narg) error->all(FLERR, "Illegal fix neighbor/swap command"); iarg++; int i = 0; while (iarg < narg) { if (isalpha(arg[iarg][0])) break; - if (i >= atom->ntypes) error->all(FLERR,"Illegal fix neighbor/swap command"); - rate_list[i] = utils::numeric(FLERR,arg[iarg],false,lmp); + if (i >= atom->ntypes) error->all(FLERR, "Illegal fix neighbor/swap command"); + rate_list[i] = utils::numeric(FLERR, arg[iarg], false, lmp); i++; iarg++; } rates_flag = 1; - if (i != atom->ntypes) error->all(FLERR,"Illegal fix neighbor/swap command"); - } - else error->all(FLERR,"Illegal fix neighbor/swap command"); + if (i != atom->ntypes) error->all(FLERR, "Illegal fix neighbor/swap command"); + } else + error->all(FLERR, "Illegal fix neighbor/swap command"); } } @@ -246,7 +246,8 @@ void FixNeighborSwap::init() int *type = atom->type; - if (nswaptypes < 2 && !diff_flag) error->all(FLERR,"Must specify at least 2 types in fix neighbor/swap command"); + if (nswaptypes < 2 && !diff_flag) + error->all(FLERR, "Must specify at least 2 types in fix neighbor/swap command"); // set index and check validity of region @@ -257,12 +258,12 @@ void FixNeighborSwap::init() for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) if (type_list[iswaptype] <= 0 || type_list[iswaptype] > atom->ntypes) - error->all(FLERR,"Invalid atom type in fix neighbor/swap command"); + error->all(FLERR, "Invalid atom type in fix neighbor/swap command"); if (atom->q_flag) { - double qmax,qmin; - int firstall,first; - memory->create(qtype,nswaptypes,"neighbor/swap:qtype"); + double qmax, qmin; + int firstall, first; + memory->create(qtype, nswaptypes, "neighbor/swap:qtype"); for (int iswaptype = 0; iswaptype < nswaptypes; iswaptype++) { first = 1; for (int i = 0; i < atom->nlocal; i++) { @@ -272,24 +273,27 @@ void FixNeighborSwap::init() qtype[iswaptype] = atom->q[i]; first = 0; } else if (qtype[iswaptype] != atom->q[i]) - error->one(FLERR,"All atoms of a swapped type must have the same charge."); + error->one(FLERR, "All atoms of a swapped type must have the same charge."); } } } - MPI_Allreduce(&first,&firstall,1,MPI_INT,MPI_MIN,world); - if (firstall) error->all(FLERR,"At least one atom of each swapped type must be present to define charges."); + MPI_Allreduce(&first, &firstall, 1, MPI_INT, MPI_MIN, world); + if (firstall) + error->all(FLERR, + "At least one atom of each swapped type must be present to define charges."); if (first) qtype[iswaptype] = -DBL_MAX; - MPI_Allreduce(&qtype[iswaptype],&qmax,1,MPI_DOUBLE,MPI_MAX,world); + MPI_Allreduce(&qtype[iswaptype], &qmax, 1, MPI_DOUBLE, MPI_MAX, world); if (first) qtype[iswaptype] = DBL_MAX; - MPI_Allreduce(&qtype[iswaptype],&qmin,1,MPI_DOUBLE,MPI_MIN,world); - if (qmax != qmin) error->all(FLERR,"All atoms of a swapped type must have same charge."); + MPI_Allreduce(&qtype[iswaptype], &qmin, 1, MPI_DOUBLE, MPI_MIN, world); + if (qmax != qmin) error->all(FLERR, "All atoms of a swapped type must have same charge."); } } - memory->create(sqrt_mass_ratio,atom->ntypes+1,atom->ntypes+1,"neighbor/swap:sqrt_mass_ratio"); + memory->create(sqrt_mass_ratio, atom->ntypes + 1, atom->ntypes + 1, + "neighbor/swap:sqrt_mass_ratio"); for (int itype = 1; itype <= atom->ntypes; itype++) for (int jtype = 1; jtype <= atom->ntypes; jtype++) - sqrt_mass_ratio[itype][jtype] = sqrt(atom->mass[itype]/atom->mass[jtype]); + sqrt_mass_ratio[itype][jtype] = sqrt(atom->mass[itype] / atom->mass[jtype]); // check to see if itype and jtype cutoffs are the same // if not, reneighboring will be needed between swaps @@ -314,9 +318,9 @@ void FixNeighborSwap::init() if ((mask[i] == groupbit) && (mask[i] && firstgroupbit)) flag = 1; int flagall; - MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); + MPI_Allreduce(&flag, &flagall, 1, MPI_INT, MPI_SUM, world); - if (flagall) error->all(FLERR,"Cannot do neighbor/swap on atoms in atom_modify first group"); + if (flagall) error->all(FLERR, "Cannot do neighbor/swap on atoms in atom_modify first group"); } } @@ -336,7 +340,7 @@ void FixNeighborSwap::pre_exchange() domain->pbc(); comm->exchange(); comm->borders(); - if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); + if (domain->triclinic) domain->lamda2x(atom->nlocal + atom->nghost); if (modify->n_pre_neighbor) modify->pre_neighbor(); neighbor->build(1); @@ -369,7 +373,7 @@ int FixNeighborSwap::attempt_swap() // int nlocal = atom->nlocal; tagint *id = atom->tag; - if ( niswap == 0 ) return 0; + if (niswap == 0) return 0; // pre-swap energy @@ -385,7 +389,7 @@ int FixNeighborSwap::attempt_swap() // build nearest-neighbor list based on atom i build_i_neighbor_list(i); - if ( njswap <= 0 ) return 0; + if (njswap <= 0) return 0; // pick a neighbor atom j based on i neighbor list jtype_selected = -1; @@ -395,16 +399,14 @@ int FixNeighborSwap::attempt_swap() int jtype = jtype_selected; // Accept swap if types are equal, no change to system - if ( itype == jtype ) { - return 1; - } + if (itype == jtype) { return 1; } // swap their properties - if ( i >= 0 ) { + if (i >= 0) { atom->type[i] = jtype; if (atom->q_flag) atom->q[i] = qtype[jtype_selected]; } - if ( j >= 0 ) { + if (j >= 0) { atom->type[j] = itype; if (atom->q_flag) atom->q[j] = qtype[0]; } @@ -418,7 +420,7 @@ int FixNeighborSwap::attempt_swap() domain->pbc(); comm->exchange(); comm->borders(); - if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost); + if (domain->triclinic) domain->lamda2x(atom->nlocal + atom->nghost); if (modify->n_pre_neighbor) modify->pre_neighbor(); neighbor->build(1); } else { @@ -432,16 +434,15 @@ int FixNeighborSwap::attempt_swap() // if swap accepted, return 1 // if ke_flag, rescale atom velocities - if (random_equal->uniform() < - exp(beta*(energy_before - energy_after))) { + if (random_equal->uniform() < exp(beta * (energy_before - energy_after))) { update_iswap_atoms_list(); if (ke_flag) { - if ( i >= 0 ) { + if (i >= 0) { atom->v[i][0] *= sqrt_mass_ratio[itype][jtype]; atom->v[i][1] *= sqrt_mass_ratio[itype][jtype]; atom->v[i][2] *= sqrt_mass_ratio[itype][jtype]; } - if ( j >= 0 ) { + if (j >= 0) { atom->v[j][0] *= sqrt_mass_ratio[jtype][itype]; atom->v[j][1] *= sqrt_mass_ratio[jtype][itype]; atom->v[j][2] *= sqrt_mass_ratio[jtype][itype]; @@ -456,11 +457,11 @@ int FixNeighborSwap::attempt_swap() // do not need to re-call comm->borders() and rebuild neighbor list // since will be done on next cycle or in Verlet when this fix finishes - if ( i >= 0 ) { + if (i >= 0) { atom->type[i] = itype; if (atom->q_flag) atom->q[i] = qtype[0]; } - if ( j >= 0 ) { + if (j >= 0) { atom->type[j] = jtype; if (atom->q_flag) atom->q[j] = qtype[jtype_selected]; } @@ -479,16 +480,16 @@ double FixNeighborSwap::energy_full() if (modify->n_pre_force) modify->pre_force(vflag); - if (force->pair) force->pair->compute(eflag,vflag); + if (force->pair) force->pair->compute(eflag, vflag); if (atom->molecular != Atom::ATOMIC) { - if (force->bond) force->bond->compute(eflag,vflag); - if (force->angle) force->angle->compute(eflag,vflag); - if (force->dihedral) force->dihedral->compute(eflag,vflag); - if (force->improper) force->improper->compute(eflag,vflag); + if (force->bond) force->bond->compute(eflag, vflag); + if (force->angle) force->angle->compute(eflag, vflag); + if (force->dihedral) force->dihedral->compute(eflag, vflag); + if (force->improper) force->improper->compute(eflag, vflag); } - if (force->kspace) force->kspace->compute(eflag,vflag); + if (force->kspace) force->kspace->compute(eflag, vflag); if (modify->n_post_force_any) modify->post_force(vflag); @@ -507,15 +508,14 @@ int FixNeighborSwap::pick_i_swap_atom() int id_center_local = -1; int i = -1; - int iwhichglobal = static_cast (niswap*random_equal->uniform()); - if ((iwhichglobal >= niswap_before) && - (iwhichglobal < niswap_before + niswap_local)) { + int iwhichglobal = static_cast(niswap * random_equal->uniform()); + if ((iwhichglobal >= niswap_before) && (iwhichglobal < niswap_before + niswap_local)) { int iwhichlocal = iwhichglobal - niswap_before; i = local_swap_iatom_list[iwhichlocal]; id_center_local = id[i]; - MPI_Allreduce(&id[i],&id_center,1,MPI_INT,MPI_MAX,world); + MPI_Allreduce(&id[i], &id_center, 1, MPI_INT, MPI_MAX, world); } else { - MPI_Allreduce(&id[i],&id_center,1,MPI_INT,MPI_MAX,world); + MPI_Allreduce(&id[i], &id_center, 1, MPI_INT, MPI_MAX, world); } return i; @@ -530,7 +530,7 @@ int FixNeighborSwap::pick_j_swap_neighbor(int i) int jtype_selected_local = -1; // Generate random double from 0 to maximum global probability - double selected_prob = static_cast (global_probability*random_equal->uniform()); + double selected_prob = static_cast(global_probability * random_equal->uniform()); // Find which local swap atom corresponds to probability if ((selected_prob >= prev_probability) && @@ -539,28 +539,26 @@ int FixNeighborSwap::pick_j_swap_neighbor(int i) for (int n = 0; n < njswap_local; n++) { if (search_prob > local_swap_probability[n]) { search_prob -= local_swap_probability[n]; - } - else{ + } else { j = local_swap_neighbor_list[n]; jtype_selected_local = local_swap_type_list[n]; - MPI_Allreduce(&jtype_selected_local,&jtype_selected,1,MPI_INT,MPI_MAX,world); + MPI_Allreduce(&jtype_selected_local, &jtype_selected, 1, MPI_INT, MPI_MAX, world); return j; } } - error->all(FLERR,"Did not select local neighbor swap atom"); + error->all(FLERR, "Did not select local neighbor swap atom"); } - MPI_Allreduce(&jtype_selected_local,&jtype_selected,1,MPI_INT,MPI_MAX,world); + MPI_Allreduce(&jtype_selected_local, &jtype_selected, 1, MPI_INT, MPI_MAX, world); return j; } /* ---------------------------------------------------------------------- ------------------------------------------------------------------------- */ -double FixNeighborSwap::get_distance(double* i, double* j) +double FixNeighborSwap::get_distance(double *i, double *j) { - double r = sqrt(MathSpecial::square((i[0] - j[0])) + - MathSpecial::square((i[1] - j[1])) + + double r = sqrt(MathSpecial::square((i[0] - j[0])) + MathSpecial::square((i[1] - j[1])) + MathSpecial::square((i[2] - j[2]))); return r; } @@ -580,16 +578,16 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) memory->sfree(local_swap_neighbor_list); atom_swap_nmax = atom->nmax; - local_swap_neighbor_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), - "MCSWAP:local_swap_neighbor_list"); + local_swap_neighbor_list = + (int *) memory->smalloc(atom_swap_nmax * sizeof(int), "MCSWAP:local_swap_neighbor_list"); memory->sfree(local_swap_probability); - local_swap_probability = (double *) memory->smalloc(atom_swap_nmax*sizeof(double), - "MCSWAP:local_swap_probability_list"); + local_swap_probability = (double *) memory->smalloc(atom_swap_nmax * sizeof(double), + "MCSWAP:local_swap_probability_list"); memory->sfree(local_swap_type_list); - local_swap_type_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), - "MCSWAP:local_swap_type_list"); + local_swap_type_list = + (int *) memory->smalloc(atom_swap_nmax * sizeof(int), "MCSWAP:local_swap_type_list"); // Compute voronoi and access neighbor list @@ -605,11 +603,10 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) int temp_j = -1; // Find local voronoi entry with selected central atom - if ( (int)voro_neighbor_list[n][0] == id_center ) { + if ((int) voro_neighbor_list[n][0] == id_center) { temp_j_id = voro_neighbor_list[n][1]; temp_j = -1; - } else if ( ((int)voro_neighbor_list[n][1] == id_center) && - ( i_center < 0 ) ) { + } else if (((int) voro_neighbor_list[n][1] == id_center) && (i_center < 0)) { temp_j_id = voro_neighbor_list[n][0]; temp_j = -1; } else { @@ -618,39 +615,37 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Find which local atom corresponds to neighbor for (int j = 0; j < nlocal; j++) { - if ( temp_j_id == id[j] ) { + if (temp_j_id == id[j]) { temp_j = j; break; } } // If temp_j not on this processor, skip - if ( temp_j < 0 ) continue; + if (temp_j < 0) continue; if (region) { - if (region->match(x[temp_j][0],x[temp_j][1],x[temp_j][2]) == 1) { + if (region->match(x[temp_j][0], x[temp_j][1], x[temp_j][2]) == 1) { if (atom->mask[temp_j] & groupbit) { if (diff_flag) { // Calculate distance from i to each j, adjust probability of selection // Get distance if own centr atom double r = INFINITY; - if ( i_center >= 0 ) { - double r = get_distance(x[temp_j], x[i_center]); - } + if (i_center >= 0) { double r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atom when ghost - for (int i=nlocal; i < nlocal+nghost; i++) { - if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r) ) { - r = get_distance(x[temp_j], x[i]); + for (int i = nlocal; i < nlocal + nghost; i++) { + if ((id[i] == id_center) && (get_distance(x[temp_j], x[i]) < r)) { + r = get_distance(x[temp_j], x[i]); } } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); } local_probability += local_swap_probability[njswap_local]; local_swap_type_list[njswap_local] = type[temp_j]; @@ -662,22 +657,20 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Calculate distance from i to each j, adjust probability of selection // Get distance if own center atom double r = INFINITY; - if ( i_center >= 0 ) { - double r = get_distance(x[temp_j], x[i_center]); - } + if (i_center >= 0) { double r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atom when ghost - for (int i=nlocal; i < nlocal+nghost; i++) { - if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r) ) { - r = get_distance(x[temp_j], x[i]); + for (int i = nlocal; i < nlocal + nghost; i++) { + if ((id[i] == id_center) && (get_distance(x[temp_j], x[i]) < r)) { + r = get_distance(x[temp_j], x[i]); } } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); } local_probability += local_swap_probability[njswap_local]; @@ -695,20 +688,19 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Calculate distance from i to each j, adjust probability of selection // Get distance if own center atom double r = INFINITY; - if ( i_center >= 0 ) { - r = get_distance(x[temp_j], x[i_center]); - } + if (i_center >= 0) { r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atoms - for (int i=nlocal; i < nlocal+nghost; i++) { - if ( (id[i] == id_center) && (get_distance(x[temp_j], x[i]) < r) ) + for (int i = nlocal; i < nlocal + nghost; i++) { + if ((id[i] == id_center) && (get_distance(x[temp_j], x[i]) < r)) r = get_distance(x[temp_j], x[i]); } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); - } else{ - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); + } else { + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); } local_probability += local_swap_probability[njswap_local]; @@ -721,22 +713,20 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) // Calculate distance from i to each j, adjust probability of selection // Get distance if own center atom double r = INFINITY; - if ( i_center >= 0 ) { - double r = get_distance(x[temp_j], x[i_center]); - } + if (i_center >= 0) { double r = get_distance(x[temp_j], x[i_center]); } // Get local id of ghost center atom when ghost - for (int i=nlocal; i < nlocal+nghost; i++) { - if ( (id[i] == id_center) && - (get_distance(x[temp_j], x[i]) < r)) { - r = get_distance(x[temp_j], x[i]); + for (int i = nlocal; i < nlocal + nghost; i++) { + if ((id[i] == id_center) && (get_distance(x[temp_j], x[i]) < r)) { + r = get_distance(x[temp_j], x[i]); } } if (rates_flag) { - local_swap_probability[njswap_local] = rate_list[type[temp_j] - 1]*exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r/3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); } local_probability += local_swap_probability[njswap_local]; @@ -750,12 +740,12 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) } } - MPI_Allreduce(&njswap_local,&njswap,1,MPI_INT,MPI_SUM,world); - MPI_Scan(&njswap_local,&njswap_before,1,MPI_INT,MPI_SUM,world); + MPI_Allreduce(&njswap_local, &njswap, 1, MPI_INT, MPI_SUM, world); + MPI_Scan(&njswap_local, &njswap_before, 1, MPI_INT, MPI_SUM, world); njswap_before -= njswap_local; - MPI_Allreduce(&local_probability,&global_probability,1,MPI_DOUBLE,MPI_SUM,world); - MPI_Scan(&local_probability,&prev_probability,1,MPI_DOUBLE,MPI_SUM,world); + MPI_Allreduce(&local_probability, &global_probability, 1, MPI_DOUBLE, MPI_SUM, world); + MPI_Scan(&local_probability, &prev_probability, 1, MPI_DOUBLE, MPI_SUM, world); prev_probability -= local_probability; } @@ -772,8 +762,8 @@ void FixNeighborSwap::update_iswap_atoms_list() if (atom->nmax > atom_swap_nmax) { memory->sfree(local_swap_iatom_list); atom_swap_nmax = atom->nmax; - local_swap_iatom_list = (int *) memory->smalloc(atom_swap_nmax*sizeof(int), - "MCSWAP:local_swap_iatom_list"); + local_swap_iatom_list = + (int *) memory->smalloc(atom_swap_nmax * sizeof(int), "MCSWAP:local_swap_iatom_list"); } niswap_local = 0; @@ -781,9 +771,9 @@ void FixNeighborSwap::update_iswap_atoms_list() if (region) { for (int i = 0; i < nlocal; i++) { - if (region->match(x[i][0],x[i][1],x[i][2]) == 1) { + if (region->match(x[i][0], x[i][1], x[i][2]) == 1) { if (atom->mask[i] & groupbit) { - if (type[i] == type_list[0]) { + if (type[i] == type_list[0]) { local_swap_iatom_list[niswap_local] = i; niswap_local++; } @@ -794,7 +784,7 @@ void FixNeighborSwap::update_iswap_atoms_list() } else { for (int i = 0; i < nlocal; i++) { if (atom->mask[i] & groupbit) { - if (type[i] == type_list[0]) { + if (type[i] == type_list[0]) { local_swap_iatom_list[niswap_local] = i; niswap_local++; } @@ -802,16 +792,17 @@ void FixNeighborSwap::update_iswap_atoms_list() } } - MPI_Allreduce(&niswap_local,&niswap,1,MPI_INT,MPI_SUM,world); - MPI_Scan(&niswap_local,&niswap_before,1,MPI_INT,MPI_SUM,world); + MPI_Allreduce(&niswap_local, &niswap, 1, MPI_INT, MPI_SUM, world); + MPI_Scan(&niswap_local, &niswap_before, 1, MPI_INT, MPI_SUM, world); niswap_before -= niswap_local; } /* ---------------------------------------------------------------------- */ -int FixNeighborSwap::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/) +int FixNeighborSwap::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, + int * /*pbc*/) { - int i,j,m; + int i, j, m; int *type = atom->type; double *q = atom->q; @@ -838,7 +829,7 @@ int FixNeighborSwap::pack_forward_comm(int n, int *list, double *buf, int /*pbc_ void FixNeighborSwap::unpack_forward_comm(int n, int first, double *buf) { - int i,m,last; + int i, m, last; int *type = atom->type; double *q = atom->q; @@ -848,12 +839,11 @@ void FixNeighborSwap::unpack_forward_comm(int n, int first, double *buf) if (atom->q_flag) { for (i = first; i < last; i++) { - type[i] = static_cast (buf[m++]); + type[i] = static_cast(buf[m++]); q[i] = buf[m++]; } } else { - for (i = first; i < last; i++) - type[i] = static_cast (buf[m++]); + for (i = first; i < last; i++) type[i] = static_cast(buf[m++]); } } @@ -874,7 +864,7 @@ double FixNeighborSwap::compute_vector(int n) double FixNeighborSwap::memory_usage() { - double bytes = (double)atom_swap_nmax * sizeof(int); + double bytes = (double) atom_swap_nmax * sizeof(int); return bytes; } @@ -895,8 +885,8 @@ void FixNeighborSwap::write_restart(FILE *fp) if (comm->me == 0) { int size = n * sizeof(double); - fwrite(&size,sizeof(int),1,fp); - fwrite(list,sizeof(double),n,fp); + fwrite(&size, sizeof(int), 1, fp); + fwrite(list, sizeof(double), n, fp); } } @@ -909,10 +899,10 @@ void FixNeighborSwap::restart(char *buf) int n = 0; double *list = (double *) buf; - seed = static_cast (list[n++]); + seed = static_cast(list[n++]); random_equal->reset(seed); - seed = static_cast (list[n++]); + seed = static_cast(list[n++]); random_unequal->reset(seed); next_reneighbor = (bigint) ubuf(list[n++]).i; @@ -922,5 +912,5 @@ void FixNeighborSwap::restart(char *buf) bigint ntimestep_restart = (bigint) ubuf(list[n++]).i; if (ntimestep_restart != update->ntimestep) - error->all(FLERR,"Must not reset timestep when restarting fix neighbor/swap"); + error->all(FLERR, "Must not reset timestep when restarting fix neighbor/swap"); } diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h index df75505a6d..826ab96a65 100755 --- a/src/MC/fix_neighbor_swap.h +++ b/src/MC/fix_neighbor_swap.h @@ -40,17 +40,17 @@ class FixNeighborSwap : public Fix { private: int nevery, seed; - int ke_flag; // yes = conserve ke, no = do not conserve ke - int diff_flag; // yes = simulate diffusion of central atom, no = swap only to certain types - int rates_flag; // yes = use modified type rates, no = swap rates are equivilent across types - int voro_flag; // yes = use given voronoi calculation, no = use internal voronoi calculation + int ke_flag; // yes = conserve ke, no = do not conserve ke + int diff_flag; // yes = simulate diffusion of central atom, no = swap only to certain types + int rates_flag; // yes = use modified type rates, no = swap rates are equivilent across types + int voro_flag; // yes = use given voronoi calculation, no = use internal voronoi calculation int ncycles; int niswap, njswap; // # of i,j swap atoms on all procs int niswap_local, njswap_local; // # of swap atoms on this proc int niswap_before, njswap_before; // # of swap atoms on procs < this proc // int global_i_ID; // global id of selected i atom - class Region *region; // swap region - char *idregion; // swap region id + class Region *region; // swap region + char *idregion; // swap region id int nswaptypes; int jtype_selected; @@ -68,19 +68,18 @@ class FixNeighborSwap : public Fix { int atom_swap_nmax; double beta; - double local_probability; // Total swap probability stored on this proc - double global_probability; // Total swap probability across all proc - double prev_probability; // Swap probability on proc < this proc + double local_probability; // Total swap probability stored on this proc + double global_probability; // Total swap probability across all proc + double prev_probability; // Swap probability on proc < this proc double *qtype; double energy_stored; double **sqrt_mass_ratio; double **voro_neighbor_list; int *local_swap_iatom_list; int *local_swap_neighbor_list; - int *local_swap_type_list; // Type list index of atoms stored on this proc + int *local_swap_type_list; // Type list index of atoms stored on this proc double *local_swap_probability; - class RanPark *random_equal; class RanPark *random_unequal; From dbc930c756696a87463f976d46f34fe19c7a1df6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 20 Dec 2024 19:44:28 -0500 Subject: [PATCH 020/396] correct permissions --- src/MC/fix_neighbor_swap.cpp | 0 src/MC/fix_neighbor_swap.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/MC/fix_neighbor_swap.cpp mode change 100755 => 100644 src/MC/fix_neighbor_swap.h diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp old mode 100755 new mode 100644 diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h old mode 100755 new mode 100644 From e6986cbc06208ae22457ad70178da60373c7942a Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Tue, 28 Jan 2025 18:51:07 -0700 Subject: [PATCH 021/396] Removed unused local RNG and restructured reading of command options --- src/MC/fix_neighbor_swap.cpp | 59 ++++++++++++++---------------------- src/MC/fix_neighbor_swap.h | 4 +-- 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/src/MC/fix_neighbor_swap.cpp b/src/MC/fix_neighbor_swap.cpp index 95e74bee22..d44181a981 100644 --- a/src/MC/fix_neighbor_swap.cpp +++ b/src/MC/fix_neighbor_swap.cpp @@ -66,7 +66,7 @@ static const char cite_fix_neighbor_swap_c[] = FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), region(nullptr), idregion(nullptr), type_list(nullptr), qtype(nullptr), c_voro(nullptr), voro_neighbor_list(nullptr), sqrt_mass_ratio(nullptr), - local_swap_iatom_list(nullptr), random_equal(nullptr), random_unequal(nullptr), c_pe(nullptr) + local_swap_iatom_list(nullptr), random_equal(nullptr), c_pe(nullptr) { if (narg < 10) utils::missing_cmd_args(FLERR, "fix neighbor/swap", error); @@ -85,6 +85,17 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : ncycles = utils::inumeric(FLERR, arg[4], false, lmp); seed = utils::inumeric(FLERR, arg[5], false, lmp); double temperature = utils::numeric(FLERR, arg[6], false, lmp); + r_0 = utils::inumeric(FLERR, arg[7], false, lmp); + + // Voro compute check + + int icompute = modify->find_compute(utils::strdup(arg[8])); + if (icompute < 0) error->all(FLERR, "Could not find neighbor compute ID"); + c_voro = modify->compute[icompute]; + if (c_voro->local_flag == 0) + error->all(FLERR, "Neighbor compute does not compute local info"); + if (c_voro->size_local_cols != 3) + error->all(FLERR, "Neighbor compute does not give i, j, size as expected"); if (nevery <= 0) error->all(FLERR, "Illegal fix neighbor/swap command nevery value"); if (ncycles < 0) error->all(FLERR, "Illegal fix neighbor/swap command ncycles value"); @@ -98,18 +109,12 @@ FixNeighborSwap::FixNeighborSwap(LAMMPS *lmp, int narg, char **arg) : // read options from end of input line - options(narg - 7, &arg[7]); - - if (voro_flag != 1) error->all(FLERR, "Voronoi compute required for fix neighbor/swap command"); + options(narg - 8, &arg[8]); // random number generator, same for all procs random_equal = new RanPark(lmp, seed); - // random number generator, not the same for all procs - - random_unequal = new RanPark(lmp, seed); - // set up reneighboring force_reneighbor = 1; @@ -149,7 +154,6 @@ FixNeighborSwap::~FixNeighborSwap() memory->destroy(local_swap_type_list); delete[] idregion; delete random_equal; - delete random_unequal; } /* ---------------------------------------------------------------------- @@ -163,7 +167,6 @@ void FixNeighborSwap::options(int narg, char **arg) ke_flag = 1; diff_flag = 0; rates_flag = 0; - voro_flag = 0; nswaptypes = 0; int iarg = 0; @@ -190,20 +193,6 @@ void FixNeighborSwap::options(int narg, char **arg) nswaptypes++; iarg++; } - } else if (strcmp(arg[iarg], "voro") == 0) { - if (iarg + 2 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); - - int icompute = modify->find_compute(utils::strdup(arg[iarg + 1])); - - if (icompute < 0) error->all(FLERR, "Could not find neighbor compute ID"); - c_voro = modify->compute[icompute]; - if (c_voro->local_flag == 0) - error->all(FLERR, "Neighbor compute does not compute local info"); - if (c_voro->size_local_cols != 3) - error->all(FLERR, "Neighbor compute does not give i, j, size as expected"); - - voro_flag = 1; - iarg += 2; } else if (strcmp(arg[iarg], "diff") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix neighbor/swap command"); if (nswaptypes != 0) error->all(FLERR, "Illegal fix neighbor/swap command"); @@ -630,7 +619,7 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if (diff_flag) { // Calculate distance from i to each j, adjust probability of selection - // Get distance if own centr atom + // Get distance if own center atom double r = INFINITY; if (i_center >= 0) { double r = get_distance(x[temp_j], x[i_center]); } @@ -643,9 +632,9 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if (rates_flag) { local_swap_probability[njswap_local] = - rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / r_0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / r_0)); } local_probability += local_swap_probability[njswap_local]; local_swap_type_list[njswap_local] = type[temp_j]; @@ -668,9 +657,9 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if (rates_flag) { local_swap_probability[njswap_local] = - rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / r_0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / r_0)); } local_probability += local_swap_probability[njswap_local]; @@ -698,9 +687,9 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if (rates_flag) { local_swap_probability[njswap_local] = - rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / r_0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / r_0)); } local_probability += local_swap_probability[njswap_local]; @@ -724,9 +713,9 @@ void FixNeighborSwap::build_i_neighbor_list(int i_center) if (rates_flag) { local_swap_probability[njswap_local] = - rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / 3.0)); + rate_list[type[temp_j] - 1] * exp(-MathSpecial::square(r / r_0)); } else { - local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / 3.0)); + local_swap_probability[njswap_local] = exp(-MathSpecial::square(r / r_0)); } local_probability += local_swap_probability[njswap_local]; @@ -877,7 +866,6 @@ void FixNeighborSwap::write_restart(FILE *fp) int n = 0; double list[6]; list[n++] = random_equal->state(); - list[n++] = random_unequal->state(); list[n++] = ubuf(next_reneighbor).d; list[n++] = nswap_attempts; list[n++] = nswap_successes; @@ -902,9 +890,6 @@ void FixNeighborSwap::restart(char *buf) seed = static_cast(list[n++]); random_equal->reset(seed); - seed = static_cast(list[n++]); - random_unequal->reset(seed); - next_reneighbor = (bigint) ubuf(list[n++]).i; nswap_attempts = static_cast(list[n++]); diff --git a/src/MC/fix_neighbor_swap.h b/src/MC/fix_neighbor_swap.h index 826ab96a65..821eda1bdc 100644 --- a/src/MC/fix_neighbor_swap.h +++ b/src/MC/fix_neighbor_swap.h @@ -43,7 +43,6 @@ class FixNeighborSwap : public Fix { int ke_flag; // yes = conserve ke, no = do not conserve ke int diff_flag; // yes = simulate diffusion of central atom, no = swap only to certain types int rates_flag; // yes = use modified type rates, no = swap rates are equivilent across types - int voro_flag; // yes = use given voronoi calculation, no = use internal voronoi calculation int ncycles; int niswap, njswap; // # of i,j swap atoms on all procs int niswap_local, njswap_local; // # of swap atoms on this proc @@ -67,7 +66,7 @@ class FixNeighborSwap : public Fix { bool unequal_cutoffs; int atom_swap_nmax; - double beta; + double beta, r_0; double local_probability; // Total swap probability stored on this proc double global_probability; // Total swap probability across all proc double prev_probability; // Swap probability on proc < this proc @@ -81,7 +80,6 @@ class FixNeighborSwap : public Fix { double *local_swap_probability; class RanPark *random_equal; - class RanPark *random_unequal; class Compute *c_voro; class Compute *c_pe; From a678a3b4742a5fe132babb2ddeea6a14ceabe03e Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Tue, 28 Jan 2025 18:51:52 -0700 Subject: [PATCH 022/396] Initial update of doc file --- doc/src/fix_neighbor_swap.rst | 63 +++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index 3c97400d3f..913f479ebe 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -8,7 +8,7 @@ Syntax .. code-block:: LAMMPS - fix ID group-ID neighbor/swap N X seed T R keyword values ... + fix ID group-ID neighbor/swap N X seed T R0 voro keyword values ... * ID, group-ID are documented in :doc:`fix ` command * neighbor/swap = style name of this fix command @@ -16,9 +16,11 @@ Syntax * X = number of swaps to attempt every N steps * seed = random # seed (positive integer) * T = scaling temperature of the MC swaps (temperature units) -* R = scaling swap probability of the MC swaps (distance units) +* R0 = scaling swap probability of the MC swaps (distance units) +* voro = valid voronoi compute id (compute voronoi/atom) * one or more keyword/value pairs may be appended to args -* keyword = *types* or *mu* or *ke* or *semi-grand* or *region* +* keywords *types* and *diff* are mutually exclusive, but one must be specified +* keyword = *types* or *ke* or *region* or *diff* or *rates* .. parsed-literal:: @@ -29,32 +31,35 @@ Syntax *region* value = region-ID region-ID = ID of region to use as an exchange/move volume *diff* values = one atom type - *voro* values = valid voronoi compute id (compute voronoi/atom) - *rates* values = Ntype values to conduct variable diffusion for different atom types (unitless) + *rates* values = V1 V2 . . . Vntypes values to conduct variable diffusion for different atom types (unitless) Examples """""""" .. code-block:: LAMMPS - fix mc all neighbor/swap 10 160 15238 1000.0 diff 2 voro voroN - fix myFix all neighbor/swap 100 1 12345 298.0 region my_swap_region types 5 6 voro voroN - fix kmc all neighbor/swap 1 100 345 1.0 diff 3 rates 3 1 6 voro voroN + fix mc all neighbor/swap 10 160 15238 1000.0 3.0 diff 2 voro voroN + fix myFix all neighbor/swap 100 1 12345 298.0 3.0 region my_swap_region types 5 6 voro voroN + fix kmc all neighbor/swap 1 100 345 1.0 3.0 diff 3 rates 3 1 6 voro voroN Description """"""""""" .. versionadded:: TBD -Computes MC evaluations to enable kinetic Monte Carlo (kMC) behavior -during MD simulation through only allowing neighboring atom swaps. +Computes MC evaluations to enable kinetic Monte Carlo (kMC)-type behavior +during MD simulation through only allowing neighboring atom swaps. This +creates a hybrid type simulation of MDkMC simulation where atoms are only +swapped with their neighbors, but the swapping acceptance is perfomed by +evaluating the change in system energy using the Metropolis Criterion. Neighboring atoms are selected using a Voronoi tesselation approach. This -implementation is as described in :ref:`(Tavenner) `. +implementation is as described in :ref:`(Tavenner 2023) <_TavennerMDkMC>` +as originally intended for simulating accelerated diffusion in an MD context. The fix is called every *N* timesteps and attempts *X* swaps. The system is initialized with a random seed, using a temperature *T* for evaluating the MC energy swaps. The distance-based probability is -weighted according to *R* which sets the radius :math:`r_0` for the +weighted according to *R0* which sets the radius :math:`r_0` for the weighting .. math:: @@ -64,6 +69,10 @@ weighting where :math:`p_{ij}` is the probability of selecting atoms :math:`i` and :math:`j` for an evaluated swap. +Typically, a value around the average nearest-neighbor spacing is appropriate +for *R0*. Since this is simply a proability weighting, behavior is not +particularly sensitive to the exact value of *R0*. + The keyword *types* is submitted with two or more atom types as the value. Atoms of the first atom type are swapped with valid neighbors of all the remaining atom types. @@ -96,6 +105,9 @@ potential atoms to be swapped at the initial step, i.e. for using *fix neighbor/swap* with *diff 2*. +If atoms in the specified group are not in the voro calculated group +they will not be considered for swapping. + The keyword *rates* can modify the swap rate for each swapped type by values where the adjusted rates values are given in order of increasing atom type. The number of rates provided must equal the number of atom @@ -113,6 +125,24 @@ considered in the area given by *region-ID*. If only atoms of certain groups are expected to be in this region, the corresponding compute voronoi command can be adjusted accordingly. +Either the *types* or *diff* keyword must be specified to select atom +types for swapping + +Keywords +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +---------------------------------------------------------- + +types = Select random atom matching first type as type I, remaining +atom types are valid for selecting atom J. +diff = Select random atom of this type as atom I, all atoms are valid +for type J. +ke = re-scale velocities when atoms are swapped based on difference in +mass +region = select only atoms I and J from region +rates = pre-factor modification to the J atom selection probability +based on atom type. + + Restart, fix_modify, output, run start/stop, minimize info """""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -149,8 +179,7 @@ doc page for more info. Also this fix requires that the :ref:`VORONOI package ` is installed, otherwise the fix will not be compiled. -A valid voronoi command which returns neighboring atoms must be used -and referenced with the *voro* keyword. +The voronoi command specified by *voro* must return neighboring atoms. When this fix is used with a :doc:`hybrid pair style ` system, only swaps between atom types of the same sub-style (or @@ -171,11 +200,11 @@ Related commands Default """"""" -The option defaults are *ke* = yes, *diff* = no, *rates* = 1 for all +The option defaults are *ke* = yes, *rates* = 1 for all atom types. ---------- -.. _Tavenner: +.. _TavennerMDkMC: -**(Tavenner)** J Tavenner, M Mendelev, J Lawson, Computational Materials Science, 218, 111929 (2023). +**(Tavenner 2023)** J Tavenner, M Mendelev, J Lawson, Computational Materials Science, 218, 111929 (2023). From 94885186b8838d7c0fc091474f7198ac17482f26 Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Thu, 27 Feb 2025 16:12:06 -0700 Subject: [PATCH 023/396] Updated doc with description of kMC algorithm --- doc/src/fix_neighbor_swap.rst | 62 ++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index 913f479ebe..9c87547321 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -20,7 +20,7 @@ Syntax * voro = valid voronoi compute id (compute voronoi/atom) * one or more keyword/value pairs may be appended to args * keywords *types* and *diff* are mutually exclusive, but one must be specified -* keyword = *types* or *ke* or *region* or *diff* or *rates* +* keyword = *types* or *diff* or *rates* or *ke* or *region* .. parsed-literal:: @@ -47,14 +47,55 @@ Description .. versionadded:: TBD -Computes MC evaluations to enable kinetic Monte Carlo (kMC)-type behavior -during MD simulation through only allowing neighboring atom swaps. This -creates a hybrid type simulation of MDkMC simulation where atoms are only -swapped with their neighbors, but the swapping acceptance is perfomed by -evaluating the change in system energy using the Metropolis Criterion. -Neighboring atoms are selected using a Voronoi tesselation approach. This -implementation is as described in :ref:`(Tavenner 2023) <_TavennerMDkMC>` -as originally intended for simulating accelerated diffusion in an MD context. +This fix computes Monte-Carlo (MC) evaluations to enable kinetic +Monte Carlo (kMC)-type behavior during MD simulation through only allowing +neighboring atom swaps. This creates a hybrid type simulation of MDkMC simulation +where atoms are only swapped with their neighbors, but the swapping acceptance is +perfomed by evaluating the change in system energy using the Metropolis Criterion. +Neighboring atoms are selected using a Voronoi tesselation approach. A detailed +explination of the original implementation of this procedure can be found in +:ref:`(Tavenner 2023) <_TavennerMDkMC>` as originally intended for simulating +accelerated diffusion in an MD context. + +Simulating inherently kineticly driven behaviors which rely on rare events +(such as atomic diffusion) is challenging for traditional Molecular Dynamics +approaches since simulations are restricted in their time-scale of events. +Since thermal vibration motion occurs on a timescale much shorter than the movement +of vacancies, such behaviors are challenging to model simultaneously. To address +this challenge, an approach from kMC simulations is adpoted where rare events can +be sampled at selected rates. By selecting such swap behaviors, the process +of atomic diffusion can be approximated during an MD simulation, effectively +decoupling the MD atomic vibrational time and the timescale of atomic hopping. + +To achieve such simulations, this algorithm takes the following approach. First, +the MD simulation is stopped after a given number of steps to perform atom swaps. +Given this instantaneous configuration from the MD simulation, Voronoi neighbors +are computed for all valid swap atoms. From the list of valid swap atoms, one atom +I is selected at random across the entire simulation. One if its Voronoi neighbors +that is a valid atom to swap is then selected. The atom ID is communicated to all +processors, such that if the neighbors are on different processors the swap still +occurs. The two atom types are swapped, and the change in system energy from before +the swap is compared using the Metropolis Criterion. This evaluation of the energy +change is a global calculation, such that it has a computational cost similar to +that of an MD timestep. If the swap is accepted from the Metropolis Criterion, the +atoms remain swapped. Else, the atoms are returned to their original types. This +process of MC evaluation is repeated for a given number of iterations until the +original MD simulation is resumed from the new state, where any successfully +swapped atoms have changed type, though the global system balance is preserved. + +A few key notes regarding this implementation are as follows. The parallel +efficiency of this algorithm is similar to that of other MC approaches. I.e, +due to the additional energy calculations for the MC steps, efficiency is +improved with a smaller number of atoms per processor than standalone MD simulation +since there is more weighting on the calculation of a given atomic domain and +minor additonal communication load. Communication of the atom ids to be swapped +between processors is negligible. Efficiency will additionally be much worse for +pair styles with different per-atom cutoffs, since the neighbor list will need to +be rebuilt between swap events. Limitations are imposed on the Voronoi neighbors +to restrict swapping of atoms which are outside of a reasonable cutoff. + +Input Parameters Usage +""""""""""" The fix is called every *N* timesteps and attempts *X* swaps. The system is initialized with a random seed, using a temperature *T* for @@ -128,9 +169,8 @@ voronoi command can be adjusted accordingly. Either the *types* or *diff* keyword must be specified to select atom types for swapping -Keywords +Keyword Summary """""""""""""""""""""""""""""""""""""""""""""""""""""""""" ----------------------------------------------------------- types = Select random atom matching first type as type I, remaining atom types are valid for selecting atom J. From 6dacf5d52c3fe107ef96e4beba9be682f288c7dc Mon Sep 17 00:00:00 2001 From: Aidan Thompson Date: Sat, 15 Mar 2025 11:36:20 -0600 Subject: [PATCH 024/396] Update fix_neighbor_swap.rst I fixed some typos and shortened the text a bit. --- doc/src/fix_neighbor_swap.rst | 75 ++++++++++++++--------------------- 1 file changed, 30 insertions(+), 45 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index 9c87547321..226926b0fb 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -24,7 +24,7 @@ Syntax .. parsed-literal:: - *types* values = two or more atom types (1-Ntypes or type label) + *types* values = two or more atom types (Integers in range [1,Ntypes] or type labels) *ke* value = *no* or *yes* *no* = no conservation of kinetic energy after atom swaps *yes* = kinetic energy is conserved after atom swaps @@ -47,52 +47,50 @@ Description .. versionadded:: TBD -This fix computes Monte-Carlo (MC) evaluations to enable kinetic -Monte Carlo (kMC)-type behavior during MD simulation through only allowing -neighboring atom swaps. This creates a hybrid type simulation of MDkMC simulation -where atoms are only swapped with their neighbors, but the swapping acceptance is -perfomed by evaluating the change in system energy using the Metropolis Criterion. +This fix computes Monte Carlo (MC) evaluations to enable kinetic +Monte Carlo (kMC) behavior during an MD simulation by allowing +neighboring atoms to swap their positions. This creates a hybrid MD/kMC +simulation +where atoms are swapped only with their neighbors, and the swapping acceptance is +perfomed by evaluating the change in system energy using the Metropolis criterion. Neighboring atoms are selected using a Voronoi tesselation approach. A detailed explination of the original implementation of this procedure can be found in :ref:`(Tavenner 2023) <_TavennerMDkMC>` as originally intended for simulating accelerated diffusion in an MD context. -Simulating inherently kineticly driven behaviors which rely on rare events +Simulating inherently kinetically-limited behaviors which rely on rare events (such as atomic diffusion) is challenging for traditional Molecular Dynamics -approaches since simulations are restricted in their time-scale of events. -Since thermal vibration motion occurs on a timescale much shorter than the movement -of vacancies, such behaviors are challenging to model simultaneously. To address -this challenge, an approach from kMC simulations is adpoted where rare events can +approaches, since thermal vibration motion occurs on a timescale much +shorter than local structural changes such as vacancy hopping. +To address +this challenge, an approach from kMC simulations is adopted where rare events can be sampled at selected rates. By selecting such swap behaviors, the process of atomic diffusion can be approximated during an MD simulation, effectively decoupling the MD atomic vibrational time and the timescale of atomic hopping. To achieve such simulations, this algorithm takes the following approach. First, -the MD simulation is stopped after a given number of steps to perform atom swaps. -Given this instantaneous configuration from the MD simulation, Voronoi neighbors -are computed for all valid swap atoms. From the list of valid swap atoms, one atom -I is selected at random across the entire simulation. One if its Voronoi neighbors -that is a valid atom to swap is then selected. The atom ID is communicated to all -processors, such that if the neighbors are on different processors the swap still -occurs. The two atom types are swapped, and the change in system energy from before -the swap is compared using the Metropolis Criterion. This evaluation of the energy +the MD simulation is stopped *N* steps to attempt *X* atom swaps. +Voronoi neighbors are computed for all valid swap atoms. +For each swap attempt, one atom +I is selected at random from the global list of valid atoms. One if its Voronoi neighbors +that is a valid atom to swap is then selected. The neighbor atom ID is communicated to all +processors, as it may be owned by a different processor. +The two atom types are then swapped, and the change in system energy from before +the swap is used to evaluate the Metropolis acceptance criterion. This evaluation of the energy change is a global calculation, such that it has a computational cost similar to -that of an MD timestep. If the swap is accepted from the Metropolis Criterion, the -atoms remain swapped. Else, the atoms are returned to their original types. This +that of an MD timestep. If the swap is accepted from the Metropolis criterion, the +atoms remain swapped. If the swap is rejected, the atoms are reverted to their original types. This process of MC evaluation is repeated for a given number of iterations until the original MD simulation is resumed from the new state, where any successfully swapped atoms have changed type, though the global system balance is preserved. A few key notes regarding this implementation are as follows. The parallel -efficiency of this algorithm is similar to that of other MC approaches. I.e, -due to the additional energy calculations for the MC steps, efficiency is -improved with a smaller number of atoms per processor than standalone MD simulation -since there is more weighting on the calculation of a given atomic domain and -minor additonal communication load. Communication of the atom ids to be swapped -between processors is negligible. Efficiency will additionally be much worse for -pair styles with different per-atom cutoffs, since the neighbor list will need to -be rebuilt between swap events. Limitations are imposed on the Voronoi neighbors -to restrict swapping of atoms which are outside of a reasonable cutoff. +efficiency of this algorithm is similar to that of other MC approaches, i.e, +the global potential energy must be calculated after each attempted swap. +Efficiency is sensitive to the maximum cutoff distance for the pair style, +since the neighbor list will need to be rebuilt between swap events. +Limitations are imposed on the Voronoi neighbors +to restrict swapping of atoms that are outside of a reasonable cutoff. Input Parameters Usage """"""""""" @@ -111,7 +109,7 @@ where :math:`p_{ij}` is the probability of selecting atoms :math:`i` and :math:`j` for an evaluated swap. Typically, a value around the average nearest-neighbor spacing is appropriate -for *R0*. Since this is simply a proability weighting, behavior is not +for *R0*. Since this is simply a probability weighting, behavior is not particularly sensitive to the exact value of *R0*. The keyword *types* is submitted with two or more atom types as the @@ -121,7 +119,7 @@ all the remaining atom types. The keyword *diff* is used for implementation of simulated diffusion of a given atom type as given by *diff type*. This command selects all atom types as acceptable swap types to a centrally selected atom of type -*type*. This includes the atom type specified by the diff keyword to +*type*. This includes the atom type specified by the *diff* keyword to account for self-diffusion hops of an atom type with itself. Keyword *voro* is currently required, and is implemented as @@ -169,19 +167,6 @@ voronoi command can be adjusted accordingly. Either the *types* or *diff* keyword must be specified to select atom types for swapping -Keyword Summary -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -types = Select random atom matching first type as type I, remaining -atom types are valid for selecting atom J. -diff = Select random atom of this type as atom I, all atoms are valid -for type J. -ke = re-scale velocities when atoms are swapped based on difference in -mass -region = select only atoms I and J from region -rates = pre-factor modification to the J atom selection probability -based on atom type. - Restart, fix_modify, output, run start/stop, minimize info """""""""""""""""""""""""""""""""""""""""""""""""""""""""" From 9d01ac2caf1c0946399c438bfd717f2d653b647c Mon Sep 17 00:00:00 2001 From: William Zunker Date: Wed, 26 Mar 2025 10:43:51 -0400 Subject: [PATCH 025/396] Stablized radius update, added WFM, added outputs --- src/GRANULAR/fix_granular_mdr.cpp | 42 +++++- src/GRANULAR/fix_granular_mdr.h | 3 +- src/GRANULAR/gran_sub_mod_damping.cpp | 10 +- src/GRANULAR/gran_sub_mod_normal.cpp | 189 ++++++++++++++++++++++---- src/GRANULAR/gran_sub_mod_normal.h | 3 +- src/GRANULAR/granular_model.cpp | 4 +- src/csv_writer.h | 25 ++++ 7 files changed, 236 insertions(+), 40 deletions(-) create mode 100644 src/csv_writer.h diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index 9efabdf465..712d4ad1ff 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -38,6 +38,10 @@ #include "update.h" #include "variable.h" +// wzunker +#include "csv_writer.h" +#include + using namespace LAMMPS_NS; using namespace Granular_NS; using namespace Granular_MDR_NS; @@ -45,7 +49,7 @@ using namespace FixConst; using MathConst::MY_PI; static constexpr double EPSILON = 1e-16; -static constexpr double OVERLAP_LIMIT = 0.75; +static constexpr double OVERLAP_LIMIT = 0.95; enum { COMM_1, COMM_2 }; @@ -85,7 +89,7 @@ void FixGranularMDR::post_constructor() modify->add_fix( fmt::format("{} all property/atom d_Ro d_Vcaps d_Vgeo d_Velas d_eps_bar d_dRnumerator " "d_dRdenominator d_Acon0 d_Acon1 d_Atot d_Atot_sum d_ddelta_bar d_psi " - "d_history_setup_flag d_sigmaxx d_sigmayy d_sigmazz ghost yes", + "d_history_setup_flag d_sigmaxx d_sigmayy d_sigmazz d_dRavg ghost yes", id_fix)); index_Ro = atom->find_custom("Ro", tmp1, tmp2); @@ -105,6 +109,7 @@ void FixGranularMDR::post_constructor() index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2); index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2); index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2); + index_dRavg = atom->find_custom("dRavg", tmp1, tmp2); } /* ---------------------------------------------------------------------- */ @@ -208,6 +213,7 @@ void FixGranularMDR::pre_force(int) double *sigmayy = atom->dvector[index_sigmayy]; double *sigmazz = atom->dvector[index_sigmazz]; double *history_setup_flag = atom->dvector[index_history_setup_flag]; + double *dRavg = atom->dvector[index_dRavg]; int new_atom; int nlocal = atom->nlocal; @@ -250,10 +256,35 @@ void FixGranularMDR::pre_force(int) psi[i] = (Atot[i] - Acon1[i]) / Atot[i]; if (psi_b_coeff < psi[i]) { - const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)), 0.0); - if ((radius[i] + dR) < (1.5 * Ro[i])) radius[i] += dR; + double w_confinement; + ( psi[i] > 0.1 ) ? w_confinement = 1.0/(1.0 + exp(-75.0*(psi[i]-0.2))) : w_confinement = 0.0; + const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0))*w_confinement, 0.0); + + const double N_window = 10.0; + if (dR > 0.0) dRavg[i] += (dR - dRavg[i]) / N_window; + + if (((radius[i] + dR) < (1.5 * Ro[i])) && (dR > 0.0)) radius[i] += dRavg[i]; + + //(dR + dRavg[i])/2.0; + //dRavg[i] = (dR + dRavg[i])/2.0; + + //// wzunker + //const double dRdenominatorTrue = (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)); + //if (i == 0) { + // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/compression_sleeve/dR_parameters.csv"); + // std::stringstream rowDataStream; + // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision + // rowDataStream << dRnumerator[i] << ", " << dRdenominator[i] << ", " << dRavg[i] << ", " << R << ", " << dRdenominatorTrue << ", " << lmp->update->ntimestep; + // std::string rowData = rowDataStream.str(); + // csvWriter.writeRow(rowData); + //} + } Acon0[i] = Acon1[i]; + + // wzunker + //const double dR_tmp = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)), 0.0); + //printf("i = %d, psi_b = %f, psi = %f, Atot = %f, Acon = %f, dRnumerator = %f, dRdenominator = %f, R = %f, dR = %f \n", i, psi_b_coeff, psi[i], Atot[i], Acon1[i], dRnumerator[i], dRdenominator[i],radius[i],dR_tmp); } comm_stage = COMM_1; @@ -510,6 +541,9 @@ void FixGranularMDR::calculate_contact_penalty() "(e.g. increase the skin distance)."); pjk[0] += 1.0 / (1.0 + std::exp(-50.0 * (alpha / MY_PI - 0.5))); + + // wzunker + //printf("i = %d, j = %d, k = %d, pij = %f, pik = %f, pjk = %f \n", i, j, k, pij[0], pik[0], pjk[0]); } } } diff --git a/src/GRANULAR/fix_granular_mdr.h b/src/GRANULAR/fix_granular_mdr.h index f0ba76d155..56c576d79b 100644 --- a/src/GRANULAR/fix_granular_mdr.h +++ b/src/GRANULAR/fix_granular_mdr.h @@ -97,8 +97,7 @@ class FixGranularMDR : public Fix { int index_sigmayy; // yy-component of the stress tensor, not necessary forforce calculation int index_sigmazz; // zz-component of the stress tensor, not necessary forforce calculation int index_history_setup_flag; // flag to check if history variables have beeninitialized - int index_contacts; // total contacts on particle - int index_adhesive_length; // total length of adhesive contact on a particle + int index_dRavg; // total contacts on particle }; } // namespace LAMMPS_NS diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 2fdd7e1f82..4072944d5e 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -18,6 +18,8 @@ #include "math_special.h" #include "math_const.h" +#include "style_gran_sub_mod.h" // IWYU pragma: keep + #include using namespace LAMMPS_NS; @@ -74,8 +76,12 @@ GranSubModDampingVelocity::GranSubModDampingVelocity(GranularModel *gm, LAMMPS * double GranSubModDampingVelocity::calculate_forces() { - damp_prefactor = damp; - return -damp_prefactor * gm->vnnr; + if (gm->normal_model->name == "mdr") { + return 0.0; + } else { + damp_prefactor = damp; + return -damp_prefactor * gm->vnnr; + } } /* ---------------------------------------------------------------------- diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 226d26d86b..6511f75c30 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -26,6 +26,9 @@ #include #include +// wzunker +#include "csv_writer.h" + using namespace LAMMPS_NS; using namespace Granular_NS; using namespace MathConst; @@ -47,7 +50,7 @@ static constexpr int MDR_MAX_IT = 100; // Newton-Raphs static constexpr double MDR_EPSILON1 = 1e-10; // Newton-Raphson for MDR static constexpr double MDR_EPSILON2 = 1e-16; // Newton-Raphson for MDR static constexpr double MDR_EPSILON3 = 1e-20; // For precision checks -static constexpr double MDR_OVERLAP_LIMIT = 0.75; // Maximum contact overlap for MDR +static constexpr double MDR_OVERLAP_LIMIT = 0.95; // Maximum contact overlap for MDR static const char cite_mdr[] = "MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289\n\n" @@ -472,14 +475,16 @@ void GranSubModNormalMDR::coeffs_to_local() Y = coeffs[2]; // yield stress gamma = coeffs[3]; // effective surface energy psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} - CoR = coeffs[5]; // coefficent of restitution + //CoR = coeffs[5]; // coefficent of restitution + damp = coeffs[5]; // coefficent of restitution if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); if (nu < 0.0 || nu > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); if (Y < 0.0) error->all(FLERR, "Illegal MDR normal model, yield stress must be greater than or equal to 0"); if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); - if (CoR < 0.0 || CoR > 1.0) error->all(FLERR, "Illegal MDR normal model, coefficent of restitution must be between 0 and 1.0"); + //if (CoR < 0.0 || CoR > 1.0) error->all(FLERR, "Illegal MDR normal model, coefficent of restitution must be between 0 and 1.0"); + if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than 1"); G = E / (2.0 * (1.0 + nu)); // shear modulus kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus @@ -490,6 +495,7 @@ void GranSubModNormalMDR::coeffs_to_local() Eeffinv = 1.0 / Eeff; Eeffsq = Eeff * Eeff; Eeffsqinv = Eeffinv * Eeffinv; + Eeff2particle = 0.5 * Eeff; gammasq = gamma * gamma; gamma3 = gammasq * gamma; @@ -528,6 +534,7 @@ void GranSubModNormalMDR::init() index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2); // xx-component of the stress tensor, not necessary for force calculation index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2); // yy-component of the stress tensor, not necessary for force calculation index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2); // zz-component of the stress tensor, not necessary for force calculation + index_dRavg = atom->find_custom("dRavg", tmp1, tmp2); // radius update increment } /* ---------------------------------------------------------------------- */ @@ -566,6 +573,7 @@ double GranSubModNormalMDR::calculate_forces() double *sigmaxx = atom->dvector[index_sigmaxx]; double *sigmayy = atom->dvector[index_sigmayy]; double *sigmazz = atom->dvector[index_sigmazz]; + double *dRavg = atom->dvector[index_dRavg]; const int itag_true = atom->tag[gm->i]; // true i particle tag const int jtag_true = atom->tag[gm->j]; // true j particle tag @@ -579,6 +587,7 @@ double GranSubModNormalMDR::calculate_forces() double F1 = 0.0; // force on contact side 1 double delta = gm->delta; // apparent overlap double Ac_avg = 0.0; // average contact area across both sides + double a_damp = 0.0; // damping contact radius double *history = & gm->history[history_index]; // load in all history variables int history_update = gm->history_update; @@ -596,6 +605,11 @@ double GranSubModNormalMDR::calculate_forces() if (gm->delta >= *deltamax_offset) *deltamax_offset = gm->delta; double deltamax = *deltamax_offset; + //wzunker + double F_MDR0; + double F_BULK0; + double F_MDR1; + double F_BULK1; for (int contactSide = 0; contactSide < 2; contactSide++) { @@ -607,7 +621,7 @@ double GranSubModNormalMDR::calculate_forces() // displacement partitioning only necessary for particle-particle contact // itag and jtag persist after neighbor list builds, use tags to compare to match - // contact history variables consistently across steps for a particle pair. + // contact history variables consistently across steps for a particle pair. if ((contactSide == 0 && itag_true > jtag_true) || (contactSide != 0 && itag_true < jtag_true)) { gm->i = i_true; gm->j = j_true; @@ -804,8 +818,10 @@ double GranSubModNormalMDR::calculate_forces() F_MDR = calculate_nonadhesive_mdr_force(deltae1D, Ainv, Eeff, A, B); } - if (std::isnan(F_MDR)) + if (std::isnan(F_MDR)) { + printf("itag = %d, jtag = %d \n", itag_true, jtag_true); error->one(FLERR, "F_MDR is NaN, case 1: no tensile springs"); + } if (history_update) *aAdh_offset = a_fac * a_na; } else { @@ -861,15 +877,20 @@ double GranSubModNormalMDR::calculate_forces() } aAdh = aAdh_tmp; - g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2)); - g_aAdh = round_up_negative_epsilon(g_aAdh); + if (aAdh < acrit) { + aAdh = 0.0; + F_MDR = 0.0; + } else { + g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2)); + g_aAdh = round_up_negative_epsilon(g_aAdh); - const double deltaeAdh = g_aAdh; - const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B); - const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh; - F_MDR = F_na + F_Adhes; - if (std::isnan(F_MDR)) - error->one(FLERR, "F_MDR is NaN, case 3: tensile springs exceed critical length"); + const double deltaeAdh = g_aAdh; + const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B); + const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh; + F_MDR = F_na + F_Adhes; + if (std::isnan(F_MDR)) + error->one(FLERR, "F_MDR is NaN, case 3: tensile springs exceed critical length"); + } } if (history_update) *aAdh_offset = aAdh; } @@ -891,13 +912,22 @@ double GranSubModNormalMDR::calculate_forces() } Ac_avg += wij * Ac; + // wzunker damping contact area related things + (gamma > 0.0) ? a_damp += aAdh : a_damp += a_na; + // bulk force calculation double F_BULK; (delta_BULK <= 0.0) ? F_BULK = 0.0 : F_BULK = (1.0 / Vgeo[i]) * Acon0[i] * delta_BULK * kappa * Ac; + // force-magnifier + // total force calculation (contactSide == 0) ? F0 = F_MDR + F_BULK : F1 = F_MDR + F_BULK; + // wzunker + (contactSide == 0) ? F_MDR0 = F_MDR : F_MDR1 = F_MDR; + (contactSide == 0) ? F_BULK0 = F_BULK : F_BULK1 = F_BULK; + if (history_update) { // mean surface displacement calculation *Ac_offset = wij * Ac; @@ -921,6 +951,32 @@ double GranSubModNormalMDR::calculate_forces() dRnumerator[i] -= Vo * (eps_bar_contact - *eps_bar_offset); dRnumerator[i] -= wij * MY_PI * ddeltao * (2 * deltao * Ro - pow(deltao, 2) + pow(R, 2) - pow(Ro, 2)); dRdenominator[i] += wij * 2.0 * MY_PI * R * (deltao + R - Ro); + + + // wzunker + //if (gm->contact_type == PAIR && i == 0) { + // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/compression_sleeve/dR_parameters_0.csv"); + // std::stringstream rowDataStream; + // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision + // rowDataStream << wij << ", " << dRnumerator[i] << ", " << dRdenominator[i] << ", " << eps_bar_contact << ", " << *eps_bar_offset << ", " << ddeltao << ", " << deltao << ", " << R << ", " << Fntmp << ", " << lmp->update->ntimestep; + // std::string rowData = rowDataStream.str(); + // csvWriter.writeRow(rowData); + //} +// + //if (gm->contact_type == PAIR && i == 1) { + // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/compression_sleeve/dR_parameters_1.csv"); + // std::stringstream rowDataStream; + // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision + // rowDataStream << wij << ", " << dRnumerator[i] << ", " << dRdenominator[i] << ", " << eps_bar_contact << ", " << *eps_bar_offset << ", " << ddeltao << ", " << deltao << ", " << R << ", " << Fntmp << ", " << lmp->update->ntimestep; + // std::string rowData = rowDataStream.str(); + // csvWriter.writeRow(rowData); + //} + + // wzunker + //if (gm->contact_type == PAIR) { + // printf("i = %d, j = %d, contact_type = %d, dRnumerator = %f, dRdenominator = %f, eps_bar_contact = %f, eps_bar_offset = %f, wij = %f, ddelto = %f, deltao = %f, R = %f, Fntmp = %f \n", i, gm->j, gm->contact_type, dRnumerator[i], dRdenominator[i], eps_bar_contact, *eps_bar_offset, wij, ddeltao, deltao, R, Fntmp); + //} + } if (history_update) { @@ -944,31 +1000,106 @@ double GranSubModNormalMDR::calculate_forces() const double wij = MAX(1.0 - pij, 0.0); // assign final force + double damp_prefactor; if (gm->contact_type != PAIR) { - F = wij * F0; + a_damp = a_damp/2.0; + damp_prefactor = 0.5*sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); + double *deltao_offset = &history[DELTAO_0]; + const double wfm = std::exp(10.7*(*deltao_offset)/Rinitial[gm->i] - 10.0) + 1.0; // wall force magnifier + //const double wfm = 1.0; + F = wij * F0 * wfm; } else { + damp_prefactor = 0.5*sqrt(gm->meff * 2.0 * Eeff * a_damp); F = wij * (F0 + F1) * 0.5; } // calculate damping force - if (F > 0.0) { - double Eeff2; - double Reff2; - if (gm->contact_type == PAIR) { - Eeff2 = E / (2.0 * (1.0 - pow(nu, 2))); - Reff2 = 1.0 / ((1.0 / gm->radi + 1.0 / gm->radj)); - } else { - Eeff2 = E / (1.0 - pow(nu, 2)); - Reff2 = gm->radi; - } - const double kn = Eeff2 * Reff2; - const double beta = -log(CoR) / sqrt(pow(log(CoR), 2) + PISQ); - const double damp_prefactor = beta * sqrt(gm->meff * kn); - const double F_DAMP = -damp_prefactor * gm->vnnr; + //if (F > 0.0) { + // double Eeff2; + // double Reff2; + // if (gm->contact_type == PAIR) { + // Eeff2 = E / (2.0 * (1.0 - pow(nu, 2))); + // Reff2 = 1.0 / ((1.0 / gm->radi + 1.0 / gm->radj)); + // } else { + // Eeff2 = E / (1.0 - pow(nu, 2)); + // Reff2 = gm->radi; + // } + // const double kn = Eeff2 * Reff2; + // const double beta = -log(CoR) / sqrt(pow(log(CoR), 2) + PISQ); + // const double damp_prefactor = beta * sqrt(gm->meff * kn); + // const double F_DAMP = -damp_prefactor * gm->vnnr; + // + // F += wij * F_DAMP; + //} - F += wij * F_DAMP; + // calculate damping force + if (F > 0.0) F += -wij * damp * gm->vnnr; + + //F += -wij * damp_prefactor * gm->vnnr; + + //printf("i = %d, j = %d, wij = %f, damp = %f, vnnr = %e, F_DAMP = %e \n", gm->i, gm->j, wij, damp, gm->vnnr, -wij * damp * gm->vnnr); + + // wzunker + double *delta_offset_0 = &history[DELTA_0]; + double *delta_offset_1 = &history[DELTA_0 + 1]; + const double delta0 = *delta_offset_0; + const double delta1 = *delta_offset_1; + double *delta_BULK_offset_0 = &history[DELTA_BULK_0]; + double *delta_BULK_offset_1 = &history[DELTA_BULK_0 + 1]; + const double deltaBULK0 = *delta_BULK_offset_0; + const double deltaBULK1 = *delta_BULK_offset_1; + double *aAdh_offset_0 = &history[AADH_0]; + double *aAdh_offset_1 = &history[AADH_0 + 1]; + const double aAdh0 = *aAdh_offset_0; + const double aAdh1 = *aAdh_offset_1; + double *Ac_offset_0 = &history[AC_0]; + double *Ac_offset_1 = &history[AC_0 + 1]; + const double Ac0 = *Ac_offset_0; + const double Ac1 = *Ac_offset_1; + double F_DAMP = -wij * damp * gm->vnnr; + + const double i_0 = 0; + const double i_1 = 1; + double psi_0; + double psi_1; + double Acon_0; + double Acon_1; + double Vgeo_0; + double Vgeo_1; + if (itag_true == i_0) { + psi_0 = psi[gm->i]; + psi_1 = psi[gm->j]; + Acon_0 = Acon0[gm->i]; + Acon_1 = Acon0[gm->j]; + Vgeo_0 = Vgeo[gm->i]; + Vgeo_1 = Vgeo[gm->j]; + } else { + psi_0 = psi[gm->j]; + psi_1 = psi[gm->i]; + Acon_0 = Acon0[gm->j]; + Acon_1 = Acon0[gm->i]; + Vgeo_0 = Vgeo[gm->j]; + Vgeo_1 = Vgeo[gm->i]; } + //if ( (itag_true == i_0 && jtag_true == i_1) || (itag_true == i_1 && jtag_true == i_0) ) { + // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/avicel_tableting/avicel_tableting_pair_info.csv"); + // std::stringstream rowDataStream; + // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision + // rowDataStream << itag_true << ", " << jtag_true << ", " << delta0 << ", " << delta1 << ", " << F0 << ", " << F1 << ", " << F << ", " << gm->radi << ", " << gm->radj << ", " << wij << ", " << psi_0 << ", " << psi_1 << ", " << aAdh0 << ", " << aAdh1 << ", " << Ac0 << ", " << Ac1 << ", " << F_MDR0 << ", " << F_MDR1 << ", " << F_BULK0 << ", " << F_BULK1 << ", " << deltaBULK0 << ", " << deltaBULK1 << ", " << Acon_0 << ", " << Acon_1 << ", " << Vgeo_0 << ", " << Vgeo_1 << ", " << kappa << ", " << lmp->update->ntimestep; + // std::string rowData = rowDataStream.str(); + // csvWriter.writeRow(rowData); + //} + + //if ( (gm->contact_type == PAIR) ) { + // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/sticky/pair_info.csv"); + // std::stringstream rowDataStream; + // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision + // rowDataStream << itag_true << ", " << jtag_true << ", " << delta0 << ", " << delta1 << ", " << F0 << ", " << F1 << ", " << F << ", " << gm->radi << ", " << gm->radj << ", " << wij << ", " << psi_0 << ", " << psi_1 << ", " << aAdh0 << ", " << aAdh1 << ", " << Ac0 << ", " << Ac1 << ", " << F_MDR0 << ", " << F_MDR1 << ", " << F_BULK0 << ", " << F_BULK1 << ", " << deltaBULK0 << ", " << deltaBULK1 << ", " << Acon_0 << ", " << Acon_1 << ", " << Vgeo_0 << ", " << Vgeo_1 << ", " << kappa << ", " << F_DAMP << ", " << gm->vnnr << ", " << delta << ", " << lmp->update->ntimestep; + // std::string rowData = rowDataStream.str(); + // csvWriter.writeRow(rowData); + //} + return F; } diff --git a/src/GRANULAR/gran_sub_mod_normal.h b/src/GRANULAR/gran_sub_mod_normal.h index db96227f13..b096e03ca8 100644 --- a/src/GRANULAR/gran_sub_mod_normal.h +++ b/src/GRANULAR/gran_sub_mod_normal.h @@ -147,7 +147,7 @@ namespace Granular_NS { protected: double G, kappa, Eeff; // derived coeffs - double Eeffsq, Eeffinv, Eeffsqinv; + double Eeffsq, Eeffinv, Eeffsqinv, Eeff2particle; double gammasq, gamma3, gamma4; int warn_flag; @@ -155,6 +155,7 @@ namespace Granular_NS { int index_Ro, index_Vgeo, index_Velas, index_Vcaps, index_eps_bar, index_dRnumerator; int index_dRdenominator, index_Acon0, index_Acon1, index_Atot, index_Atot_sum, index_ddelta_bar; int index_psi, index_sigmaxx, index_sigmayy, index_sigmazz, index_contacts, index_adhesive_length; + int index_dRavg; int fix_mdr_flag; char *id_fix; diff --git a/src/GRANULAR/granular_model.cpp b/src/GRANULAR/granular_model.cpp index e96debd59e..448281cfa6 100644 --- a/src/GRANULAR/granular_model.cpp +++ b/src/GRANULAR/granular_model.cpp @@ -251,8 +251,8 @@ void GranularModel::init() // Must have valid normal, damping, and tangential models if (normal_model->name == "none") error->all(FLERR, "Must specify normal granular model"); if (normal_model->name == "mdr") { - if (damping_model->name != "none") - error->all(FLERR, "MDR require 'none' damping model. To damp, specify a coefficient of restitution < 1."); + //if (damping_model->name != "none") + //error->all(FLERR, "MDR require 'none' damping model. To damp, specify a coefficient of restitution < 1."); } else { if (damping_model->name == "none") error->all(FLERR, "Must specify damping granular model"); } diff --git a/src/csv_writer.h b/src/csv_writer.h new file mode 100644 index 0000000000..0a01604393 --- /dev/null +++ b/src/csv_writer.h @@ -0,0 +1,25 @@ +#include +#include +#include + +class CSVWriter { +public: + CSVWriter(const std::string& filename) : filename_(filename) {} + + void writeRow(const std::string& data) { + std::ofstream file; + // Use the append mode to add data to the end of the file if it exists + file.open(filename_, std::ios::out | std::ios::app); + + if (!file.is_open()) { + std::cerr << "Failed to open file: " << filename_ << std::endl; + return; + } + + file << data << std::endl; + file.close(); + } + +private: + std::string filename_; +}; \ No newline at end of file From 3aafe2831b7c2d925a1c6fc5d3f4dd85053eb1a8 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Thu, 27 Mar 2025 16:50:54 -0400 Subject: [PATCH 026/396] added MDR damping method --- src/GRANULAR/fix_granular_mdr.h | 5 +++-- src/GRANULAR/gran_sub_mod_damping.cpp | 26 ++++++++++++++++++++++++++ src/GRANULAR/gran_sub_mod_damping.h | 9 +++++++++ src/GRANULAR/gran_sub_mod_normal.cpp | 20 ++++++++++++++------ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/GRANULAR/fix_granular_mdr.h b/src/GRANULAR/fix_granular_mdr.h index 56c576d79b..fce727fe5d 100644 --- a/src/GRANULAR/fix_granular_mdr.h +++ b/src/GRANULAR/fix_granular_mdr.h @@ -51,7 +51,8 @@ namespace Granular_MDR_NS { PENALTY, // contact penalty DELTA_MAX, DELTAP_0, - DELTAP_1 + DELTAP_1, + DAMP_SCALE }; } // namespace Granular_MDR_NS @@ -97,7 +98,7 @@ class FixGranularMDR : public Fix { int index_sigmayy; // yy-component of the stress tensor, not necessary forforce calculation int index_sigmazz; // zz-component of the stress tensor, not necessary forforce calculation int index_history_setup_flag; // flag to check if history variables have beeninitialized - int index_dRavg; // total contacts on particle + int index_dRavg; // average radius update increment }; } // namespace LAMMPS_NS diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 4072944d5e..a9b7f68d4e 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -14,6 +14,7 @@ #include "gran_sub_mod_damping.h" #include "gran_sub_mod_normal.h" +#include "fix_granular_mdr.h" #include "granular_model.h" #include "math_special.h" #include "math_const.h" @@ -176,3 +177,28 @@ void GranSubModDampingCoeffRestitution::init() damp /= sqrt(MY_PI * MY_PI + logcor * logcor); } } + +/* ---------------------------------------------------------------------- + MDR damping +------------------------------------------------------------------------- */ + +GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : + GranSubModDamping(gm, lmp) +{ + contact_radius_flag = 1; +} + +/* ---------------------------------------------------------------------- */ + +double GranSubModDampingMDR::calculate_forces() +{ + using namespace Granular_MDR_NS; + double *history = & gm->history[gm->normal_model->history_index]; // load in all history variables + //printf("%p %d damping\n", (void*)& history[DAMP_SCALE], gm->normal_model->history_index); + damp_prefactor = damp * history[DAMP_SCALE]; + return -damp_prefactor * gm->vnnr; +} + + + + //printf("DAMP_SCALE = %d, damp_scale_history = %e, damp = %e, damp_prefactor = %e, F_DAMP = %e \n", DAMP_SCALE, history[DAMP_SCALE], damp, damp_prefactor, -damp_prefactor * gm->vnnr); diff --git a/src/GRANULAR/gran_sub_mod_damping.h b/src/GRANULAR/gran_sub_mod_damping.h index 98c31d680a..06aabbc5ca 100644 --- a/src/GRANULAR/gran_sub_mod_damping.h +++ b/src/GRANULAR/gran_sub_mod_damping.h @@ -19,6 +19,7 @@ GranSubModStyle(mass_velocity,GranSubModDampingMassVelocity,DAMPING); GranSubModStyle(viscoelastic,GranSubModDampingViscoelastic,DAMPING); GranSubModStyle(tsuji,GranSubModDampingTsuji,DAMPING); GranSubModStyle(coeff_restitution,GranSubModDampingCoeffRestitution,DAMPING); +GranSubModStyle(mdr,GranSubModDampingMDR,DAMPING); // clang-format on #else @@ -95,6 +96,14 @@ namespace Granular_NS { /* ---------------------------------------------------------------------- */ + class GranSubModDampingMDR : public GranSubModDamping { + public: + GranSubModDampingMDR(class GranularModel *, class LAMMPS *); + double calculate_forces() override; + }; + + /* ---------------------------------------------------------------------- */ + } // namespace Granular_NS } // namespace LAMMPS_NS diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 6511f75c30..37ae769016 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -445,7 +445,7 @@ GranSubModNormalMDR::GranSubModNormalMDR(GranularModel *gm, LAMMPS *lmp) : num_coeffs = 6; contact_radius_flag = 1; - size_history = 26; + size_history = 27; nsvector = 1; fix_mdr_flag = 0; id_fix = nullptr; @@ -484,7 +484,7 @@ void GranSubModNormalMDR::coeffs_to_local() if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); //if (CoR < 0.0 || CoR > 1.0) error->all(FLERR, "Illegal MDR normal model, coefficent of restitution must be between 0 and 1.0"); - if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than 1"); + if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); G = E / (2.0 * (1.0 + nu)); // shear modulus kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus @@ -1000,19 +1000,27 @@ double GranSubModNormalMDR::calculate_forces() const double wij = MAX(1.0 - pij, 0.0); // assign final force - double damp_prefactor; + double damp_scale; if (gm->contact_type != PAIR) { a_damp = a_damp/2.0; - damp_prefactor = 0.5*sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); + damp_scale = 0.5*sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); double *deltao_offset = &history[DELTAO_0]; const double wfm = std::exp(10.7*(*deltao_offset)/Rinitial[gm->i] - 10.0) + 1.0; // wall force magnifier //const double wfm = 1.0; F = wij * F0 * wfm; } else { - damp_prefactor = 0.5*sqrt(gm->meff * 2.0 * Eeff * a_damp); + damp_scale = 0.5*sqrt(gm->meff * 2.0 * Eeff * a_damp); F = wij * (F0 + F1) * 0.5; } + if (history_update) { + double *damp_scale_offset = & history[DAMP_SCALE]; + //printf("damp_scale_history = %e \n", history[DAMP_SCALE]); + (a_damp < 0.0) ? *damp_scale_offset = 0.0 : *damp_scale_offset = damp_scale; + //printf("DAMP_SCALE = %d, damp_scale_history = %e, damp = %e, a_damp = %e, damp_scale = %e \n", DAMP_SCALE, history[DAMP_SCALE], damp, a_damp, damp_scale); + //printf("%p %d normal\n", (void*)& history[DAMP_SCALE], history_index); + } + // calculate damping force //if (F > 0.0) { // double Eeff2; @@ -1033,7 +1041,7 @@ double GranSubModNormalMDR::calculate_forces() //} // calculate damping force - if (F > 0.0) F += -wij * damp * gm->vnnr; + // if (F > 0.0) F += -wij * damp * gm->vnnr; //F += -wij * damp_prefactor * gm->vnnr; From 8ee8cb1aa339103b09ed8e7daccb6296ab329957 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Thu, 27 Mar 2025 20:40:35 -0400 Subject: [PATCH 027/396] code clean-up --- src/GRANULAR/fix_granular_mdr.cpp | 26 ----- src/GRANULAR/gran_sub_mod_damping.cpp | 8 +- src/GRANULAR/gran_sub_mod_normal.cpp | 133 +------------------------- 3 files changed, 3 insertions(+), 164 deletions(-) diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index 712d4ad1ff..ebe3288d22 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -38,10 +38,6 @@ #include "update.h" #include "variable.h" -// wzunker -#include "csv_writer.h" -#include - using namespace LAMMPS_NS; using namespace Granular_NS; using namespace Granular_MDR_NS; @@ -264,27 +260,8 @@ void FixGranularMDR::pre_force(int) if (dR > 0.0) dRavg[i] += (dR - dRavg[i]) / N_window; if (((radius[i] + dR) < (1.5 * Ro[i])) && (dR > 0.0)) radius[i] += dRavg[i]; - - //(dR + dRavg[i])/2.0; - //dRavg[i] = (dR + dRavg[i])/2.0; - - //// wzunker - //const double dRdenominatorTrue = (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)); - //if (i == 0) { - // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/compression_sleeve/dR_parameters.csv"); - // std::stringstream rowDataStream; - // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision - // rowDataStream << dRnumerator[i] << ", " << dRdenominator[i] << ", " << dRavg[i] << ", " << R << ", " << dRdenominatorTrue << ", " << lmp->update->ntimestep; - // std::string rowData = rowDataStream.str(); - // csvWriter.writeRow(rowData); - //} - } Acon0[i] = Acon1[i]; - - // wzunker - //const double dR_tmp = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0)), 0.0); - //printf("i = %d, psi_b = %f, psi = %f, Atot = %f, Acon = %f, dRnumerator = %f, dRdenominator = %f, R = %f, dR = %f \n", i, psi_b_coeff, psi[i], Atot[i], Acon1[i], dRnumerator[i], dRdenominator[i],radius[i],dR_tmp); } comm_stage = COMM_1; @@ -541,9 +518,6 @@ void FixGranularMDR::calculate_contact_penalty() "(e.g. increase the skin distance)."); pjk[0] += 1.0 / (1.0 + std::exp(-50.0 * (alpha / MY_PI - 0.5))); - - // wzunker - //printf("i = %d, j = %d, k = %d, pij = %f, pik = %f, pjk = %f \n", i, j, k, pij[0], pik[0], pjk[0]); } } } diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index a9b7f68d4e..1229c92842 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -77,12 +77,8 @@ GranSubModDampingVelocity::GranSubModDampingVelocity(GranularModel *gm, LAMMPS * double GranSubModDampingVelocity::calculate_forces() { - if (gm->normal_model->name == "mdr") { - return 0.0; - } else { - damp_prefactor = damp; - return -damp_prefactor * gm->vnnr; - } + damp_prefactor = damp; + return -damp_prefactor * gm->vnnr; } /* ---------------------------------------------------------------------- diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 37ae769016..cebaf72283 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -26,9 +26,6 @@ #include #include -// wzunker -#include "csv_writer.h" - using namespace LAMMPS_NS; using namespace Granular_NS; using namespace MathConst; @@ -605,12 +602,6 @@ double GranSubModNormalMDR::calculate_forces() if (gm->delta >= *deltamax_offset) *deltamax_offset = gm->delta; double deltamax = *deltamax_offset; - //wzunker - double F_MDR0; - double F_BULK0; - double F_MDR1; - double F_BULK1; - for (int contactSide = 0; contactSide < 2; contactSide++) { double *delta_offset, *deltao_offset, *delta_MDR_offset, *delta_BULK_offset; @@ -912,22 +903,16 @@ double GranSubModNormalMDR::calculate_forces() } Ac_avg += wij * Ac; - // wzunker damping contact area related things + // contact radius for damping (gamma > 0.0) ? a_damp += aAdh : a_damp += a_na; // bulk force calculation double F_BULK; (delta_BULK <= 0.0) ? F_BULK = 0.0 : F_BULK = (1.0 / Vgeo[i]) * Acon0[i] * delta_BULK * kappa * Ac; - // force-magnifier - // total force calculation (contactSide == 0) ? F0 = F_MDR + F_BULK : F1 = F_MDR + F_BULK; - // wzunker - (contactSide == 0) ? F_MDR0 = F_MDR : F_MDR1 = F_MDR; - (contactSide == 0) ? F_BULK0 = F_BULK : F_BULK1 = F_BULK; - if (history_update) { // mean surface displacement calculation *Ac_offset = wij * Ac; @@ -951,32 +936,6 @@ double GranSubModNormalMDR::calculate_forces() dRnumerator[i] -= Vo * (eps_bar_contact - *eps_bar_offset); dRnumerator[i] -= wij * MY_PI * ddeltao * (2 * deltao * Ro - pow(deltao, 2) + pow(R, 2) - pow(Ro, 2)); dRdenominator[i] += wij * 2.0 * MY_PI * R * (deltao + R - Ro); - - - // wzunker - //if (gm->contact_type == PAIR && i == 0) { - // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/compression_sleeve/dR_parameters_0.csv"); - // std::stringstream rowDataStream; - // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision - // rowDataStream << wij << ", " << dRnumerator[i] << ", " << dRdenominator[i] << ", " << eps_bar_contact << ", " << *eps_bar_offset << ", " << ddeltao << ", " << deltao << ", " << R << ", " << Fntmp << ", " << lmp->update->ntimestep; - // std::string rowData = rowDataStream.str(); - // csvWriter.writeRow(rowData); - //} -// - //if (gm->contact_type == PAIR && i == 1) { - // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/compression_sleeve/dR_parameters_1.csv"); - // std::stringstream rowDataStream; - // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision - // rowDataStream << wij << ", " << dRnumerator[i] << ", " << dRdenominator[i] << ", " << eps_bar_contact << ", " << *eps_bar_offset << ", " << ddeltao << ", " << deltao << ", " << R << ", " << Fntmp << ", " << lmp->update->ntimestep; - // std::string rowData = rowDataStream.str(); - // csvWriter.writeRow(rowData); - //} - - // wzunker - //if (gm->contact_type == PAIR) { - // printf("i = %d, j = %d, contact_type = %d, dRnumerator = %f, dRdenominator = %f, eps_bar_contact = %f, eps_bar_offset = %f, wij = %f, ddelto = %f, deltao = %f, R = %f, Fntmp = %f \n", i, gm->j, gm->contact_type, dRnumerator[i], dRdenominator[i], eps_bar_contact, *eps_bar_offset, wij, ddeltao, deltao, R, Fntmp); - //} - } if (history_update) { @@ -1015,99 +974,9 @@ double GranSubModNormalMDR::calculate_forces() if (history_update) { double *damp_scale_offset = & history[DAMP_SCALE]; - //printf("damp_scale_history = %e \n", history[DAMP_SCALE]); (a_damp < 0.0) ? *damp_scale_offset = 0.0 : *damp_scale_offset = damp_scale; - //printf("DAMP_SCALE = %d, damp_scale_history = %e, damp = %e, a_damp = %e, damp_scale = %e \n", DAMP_SCALE, history[DAMP_SCALE], damp, a_damp, damp_scale); - //printf("%p %d normal\n", (void*)& history[DAMP_SCALE], history_index); } - // calculate damping force - //if (F > 0.0) { - // double Eeff2; - // double Reff2; - // if (gm->contact_type == PAIR) { - // Eeff2 = E / (2.0 * (1.0 - pow(nu, 2))); - // Reff2 = 1.0 / ((1.0 / gm->radi + 1.0 / gm->radj)); - // } else { - // Eeff2 = E / (1.0 - pow(nu, 2)); - // Reff2 = gm->radi; - // } - // const double kn = Eeff2 * Reff2; - // const double beta = -log(CoR) / sqrt(pow(log(CoR), 2) + PISQ); - // const double damp_prefactor = beta * sqrt(gm->meff * kn); - // const double F_DAMP = -damp_prefactor * gm->vnnr; - // - // F += wij * F_DAMP; - //} - - // calculate damping force - // if (F > 0.0) F += -wij * damp * gm->vnnr; - - //F += -wij * damp_prefactor * gm->vnnr; - - //printf("i = %d, j = %d, wij = %f, damp = %f, vnnr = %e, F_DAMP = %e \n", gm->i, gm->j, wij, damp, gm->vnnr, -wij * damp * gm->vnnr); - - // wzunker - double *delta_offset_0 = &history[DELTA_0]; - double *delta_offset_1 = &history[DELTA_0 + 1]; - const double delta0 = *delta_offset_0; - const double delta1 = *delta_offset_1; - double *delta_BULK_offset_0 = &history[DELTA_BULK_0]; - double *delta_BULK_offset_1 = &history[DELTA_BULK_0 + 1]; - const double deltaBULK0 = *delta_BULK_offset_0; - const double deltaBULK1 = *delta_BULK_offset_1; - double *aAdh_offset_0 = &history[AADH_0]; - double *aAdh_offset_1 = &history[AADH_0 + 1]; - const double aAdh0 = *aAdh_offset_0; - const double aAdh1 = *aAdh_offset_1; - double *Ac_offset_0 = &history[AC_0]; - double *Ac_offset_1 = &history[AC_0 + 1]; - const double Ac0 = *Ac_offset_0; - const double Ac1 = *Ac_offset_1; - double F_DAMP = -wij * damp * gm->vnnr; - - const double i_0 = 0; - const double i_1 = 1; - double psi_0; - double psi_1; - double Acon_0; - double Acon_1; - double Vgeo_0; - double Vgeo_1; - if (itag_true == i_0) { - psi_0 = psi[gm->i]; - psi_1 = psi[gm->j]; - Acon_0 = Acon0[gm->i]; - Acon_1 = Acon0[gm->j]; - Vgeo_0 = Vgeo[gm->i]; - Vgeo_1 = Vgeo[gm->j]; - } else { - psi_0 = psi[gm->j]; - psi_1 = psi[gm->i]; - Acon_0 = Acon0[gm->j]; - Acon_1 = Acon0[gm->i]; - Vgeo_0 = Vgeo[gm->j]; - Vgeo_1 = Vgeo[gm->i]; - } - - //if ( (itag_true == i_0 && jtag_true == i_1) || (itag_true == i_1 && jtag_true == i_0) ) { - // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/avicel_tableting/avicel_tableting_pair_info.csv"); - // std::stringstream rowDataStream; - // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision - // rowDataStream << itag_true << ", " << jtag_true << ", " << delta0 << ", " << delta1 << ", " << F0 << ", " << F1 << ", " << F << ", " << gm->radi << ", " << gm->radj << ", " << wij << ", " << psi_0 << ", " << psi_1 << ", " << aAdh0 << ", " << aAdh1 << ", " << Ac0 << ", " << Ac1 << ", " << F_MDR0 << ", " << F_MDR1 << ", " << F_BULK0 << ", " << F_BULK1 << ", " << deltaBULK0 << ", " << deltaBULK1 << ", " << Acon_0 << ", " << Acon_1 << ", " << Vgeo_0 << ", " << Vgeo_1 << ", " << kappa << ", " << lmp->update->ntimestep; - // std::string rowData = rowDataStream.str(); - // csvWriter.writeRow(rowData); - //} - - //if ( (gm->contact_type == PAIR) ) { - // CSVWriter csvWriter("/Users/willzunker/simulations/lammps/bulk_response/sticky/pair_info.csv"); - // std::stringstream rowDataStream; - // rowDataStream << std::scientific << std::setprecision(8); // Set the format and precision - // rowDataStream << itag_true << ", " << jtag_true << ", " << delta0 << ", " << delta1 << ", " << F0 << ", " << F1 << ", " << F << ", " << gm->radi << ", " << gm->radj << ", " << wij << ", " << psi_0 << ", " << psi_1 << ", " << aAdh0 << ", " << aAdh1 << ", " << Ac0 << ", " << Ac1 << ", " << F_MDR0 << ", " << F_MDR1 << ", " << F_BULK0 << ", " << F_BULK1 << ", " << deltaBULK0 << ", " << deltaBULK1 << ", " << Acon_0 << ", " << Acon_1 << ", " << Vgeo_0 << ", " << Vgeo_1 << ", " << kappa << ", " << F_DAMP << ", " << gm->vnnr << ", " << delta << ", " << lmp->update->ntimestep; - // std::string rowData = rowDataStream.str(); - // csvWriter.writeRow(rowData); - //} - return F; } From eeaf0694ad7142a7d39c2726dfbf37ecedd03837 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Mon, 31 Mar 2025 22:13:29 -0400 Subject: [PATCH 028/396] white space and comment removal --- src/GRANULAR/fix_granular_mdr.cpp | 2 +- src/GRANULAR/gran_sub_mod_damping.cpp | 10 ++-------- src/GRANULAR/gran_sub_mod_normal.cpp | 10 ++++------ src/GRANULAR/granular_model.cpp | 7 +------ 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index ebe3288d22..0e9a5ada7f 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -256,7 +256,7 @@ void FixGranularMDR::pre_force(int) ( psi[i] > 0.1 ) ? w_confinement = 1.0/(1.0 + exp(-75.0*(psi[i]-0.2))) : w_confinement = 0.0; const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0))*w_confinement, 0.0); - const double N_window = 10.0; + const double N_window = 10.0; if (dR > 0.0) dRavg[i] += (dR - dRavg[i]) / N_window; if (((radius[i] + dR) < (1.5 * Ro[i])) && (dR > 0.0)) radius[i] += dRavg[i]; diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 1229c92842..1e233de38e 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -20,7 +20,6 @@ #include "math_const.h" #include "style_gran_sub_mod.h" // IWYU pragma: keep - #include using namespace LAMMPS_NS; @@ -189,12 +188,7 @@ GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : double GranSubModDampingMDR::calculate_forces() { using namespace Granular_MDR_NS; - double *history = & gm->history[gm->normal_model->history_index]; // load in all history variables - //printf("%p %d damping\n", (void*)& history[DAMP_SCALE], gm->normal_model->history_index); + double *history = & gm->history[gm->normal_model->history_index]; damp_prefactor = damp * history[DAMP_SCALE]; return -damp_prefactor * gm->vnnr; -} - - - - //printf("DAMP_SCALE = %d, damp_scale_history = %e, damp = %e, damp_prefactor = %e, F_DAMP = %e \n", DAMP_SCALE, history[DAMP_SCALE], damp, damp_prefactor, -damp_prefactor * gm->vnnr); +} \ No newline at end of file diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index cebaf72283..f27057e5b2 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -472,7 +472,6 @@ void GranSubModNormalMDR::coeffs_to_local() Y = coeffs[2]; // yield stress gamma = coeffs[3]; // effective surface energy psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} - //CoR = coeffs[5]; // coefficent of restitution damp = coeffs[5]; // coefficent of restitution if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); @@ -480,7 +479,6 @@ void GranSubModNormalMDR::coeffs_to_local() if (Y < 0.0) error->all(FLERR, "Illegal MDR normal model, yield stress must be greater than or equal to 0"); if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); - //if (CoR < 0.0 || CoR > 1.0) error->all(FLERR, "Illegal MDR normal model, coefficent of restitution must be between 0 and 1.0"); if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); G = E / (2.0 * (1.0 + nu)); // shear modulus @@ -531,7 +529,7 @@ void GranSubModNormalMDR::init() index_sigmaxx = atom->find_custom("sigmaxx", tmp1, tmp2); // xx-component of the stress tensor, not necessary for force calculation index_sigmayy = atom->find_custom("sigmayy", tmp1, tmp2); // yy-component of the stress tensor, not necessary for force calculation index_sigmazz = atom->find_custom("sigmazz", tmp1, tmp2); // zz-component of the stress tensor, not necessary for force calculation - index_dRavg = atom->find_custom("dRavg", tmp1, tmp2); // radius update increment + index_dRavg = atom->find_custom("dRavg", tmp1, tmp2); // radius update increment } /* ---------------------------------------------------------------------- */ @@ -871,7 +869,7 @@ double GranSubModNormalMDR::calculate_forces() if (aAdh < acrit) { aAdh = 0.0; F_MDR = 0.0; - } else { + } else { g_aAdh = A * 0.5 - A * Binv * sqrt(Bsq * 0.25 - pow(aAdh, 2)); g_aAdh = round_up_negative_epsilon(g_aAdh); @@ -879,7 +877,7 @@ double GranSubModNormalMDR::calculate_forces() const double F_na = calculate_nonadhesive_mdr_force(deltaeAdh, Ainv, Eeff, A, B); const double F_Adhes = 2.0 * Eeff * (deltae1D - deltaeAdh) * aAdh; F_MDR = F_na + F_Adhes; - if (std::isnan(F_MDR)) + if (std::isnan(F_MDR)) error->one(FLERR, "F_MDR is NaN, case 3: tensile springs exceed critical length"); } } @@ -904,7 +902,7 @@ double GranSubModNormalMDR::calculate_forces() Ac_avg += wij * Ac; // contact radius for damping - (gamma > 0.0) ? a_damp += aAdh : a_damp += a_na; + (gamma > 0.0) ? a_damp += aAdh : a_damp += a_na; // bulk force calculation double F_BULK; diff --git a/src/GRANULAR/granular_model.cpp b/src/GRANULAR/granular_model.cpp index 448281cfa6..1a3a46b12e 100644 --- a/src/GRANULAR/granular_model.cpp +++ b/src/GRANULAR/granular_model.cpp @@ -250,12 +250,7 @@ void GranularModel::init() // Must have valid normal, damping, and tangential models if (normal_model->name == "none") error->all(FLERR, "Must specify normal granular model"); - if (normal_model->name == "mdr") { - //if (damping_model->name != "none") - //error->all(FLERR, "MDR require 'none' damping model. To damp, specify a coefficient of restitution < 1."); - } else { - if (damping_model->name == "none") error->all(FLERR, "Must specify damping granular model"); - } + if (damping_model->name == "none") error->all(FLERR, "Must specify damping granular model"); if (tangential_model->name == "none") error->all(FLERR, "Must specify tangential granular model"); // Twisting, rolling, and heat are optional From 3c1ed34753d5f6a3997a4a1244e13c53c629c709 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Mon, 31 Mar 2025 22:16:09 -0400 Subject: [PATCH 029/396] removed csv_writer.h --- src/csv_writer.h | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 src/csv_writer.h diff --git a/src/csv_writer.h b/src/csv_writer.h deleted file mode 100644 index 0a01604393..0000000000 --- a/src/csv_writer.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -class CSVWriter { -public: - CSVWriter(const std::string& filename) : filename_(filename) {} - - void writeRow(const std::string& data) { - std::ofstream file; - // Use the append mode to add data to the end of the file if it exists - file.open(filename_, std::ios::out | std::ios::app); - - if (!file.is_open()) { - std::cerr << "Failed to open file: " << filename_ << std::endl; - return; - } - - file << data << std::endl; - file.close(); - } - -private: - std::string filename_; -}; \ No newline at end of file From b8aaa8d60ff52bc874546639ff2db548d3ab7686 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Mon, 31 Mar 2025 22:55:42 -0400 Subject: [PATCH 030/396] modified doc to include mdr damping model --- doc/src/pair_granular.rst | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 4ae59a587f..40339ab476 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -44,7 +44,7 @@ Examples pair_coeff * * hertz 1000.0 50.0 tangential mindlin 1000.0 1.0 0.4 heat area 0.1 pair_style granular - pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping none + pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping mdr Description """"""""""" @@ -88,7 +88,8 @@ and their required arguments are: 3. *hertz/material* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu` 4. *dmt* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 5. *jkr* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` -6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, :math:`\psi_b`, :math:`e` +6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, +:math:`\psi_b`, :math:`\eta_{n0}` Here, :math:`k_n` is spring stiffness (with units that depend on model choice, see below); :math:`\eta_{n0}` is a damping prefactor (or, in its @@ -253,13 +254,6 @@ algorithm see :ref:`Zunker et al. `. newton off -The damping model must be set to *none*. The *mdr* model already has a built -in damping model. - -.. code-block:: LAMMPS - - pair_coeff * * mdr 5e6 0.4 1.9e5 2 0.5 0.5 damping none - The definition of multiple *mdr* models in the *pair_style* is currently not supported. Similarly, the *mdr* model cannot be combined with a different normal model in the *pair_style*. Physically this means that only one homogeneous @@ -336,6 +330,12 @@ for the damping model currently supported are: 3. *viscoelastic* 4. *tsuji* 5. *coeff_restitution* +6. *mdr* + +.. note:: + + It is suggested to use the *mdr* damping model with when the normal + *mdr* contact model is defined. If the *damping* keyword is not specified, the *viscoelastic* model is used by default. @@ -425,6 +425,24 @@ the damping coefficient, it accurately reproduces the specified coefficient of restitution for both monodisperse and polydisperse particle pairs. This damping model is not compatible with cohesive normal models such as *JKR* or *DMT*. +The *mdr* damping model is only compatible with the normal *mdr* contact model. +It takes into account the contact stiffness :math:`k_{mdr}` calulated +by the normal *mdr* contact model to determine the damping coefficent: + +.. math:: + + \eta_n = \eta_{n0} (m_{eff}k_{mdr})^{1/2}, + +where :math:`k_{mdr}` is proportional to contact radius :math:`a_{mdr}` tracked by the +normal *mdr* contact model: + +.. math:: + + k_{mdr} = 2 E_{eff} a_{mdr}. + +In this case, :math:`\eta_{n0}` is simply a dimensionless coefficent that scales the +the overall damping coefficent. + The total normal force is computed as the sum of the elastic and damping components: From 384d7f446b099d8be2325a5fdb5803776bc2ebb0 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Thu, 3 Apr 2025 11:56:16 -0400 Subject: [PATCH 031/396] updated damping in mdr example sims --- examples/granular/in.tableting.200 | 12 ++++++------ examples/granular/in.triaxial.compaction.12 | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/granular/in.tableting.200 b/examples/granular/in.tableting.200 index 41723c72af..4ea5801bf5 100644 --- a/examples/granular/in.tableting.200 +++ b/examples/granular/in.tableting.200 @@ -28,19 +28,19 @@ variable dieHeight equal 1e-2 pair_style granular -# mdr = E, nu, Y, gamma, psi_b, CoR +# mdr = E, nu, Y, gamma, psi_b, damp variable YoungsModulus equal 5e6 variable YieldStress equal 1.9e5 variable PoissonsRatio equal 0.4 variable SurfaceEnergy equal 2 variable SurfaceEnergyWall equal 0.0 -variable CoR equal 0.5 +variable damp equal 1.0 variable psi_b equal 0.5 # linear_history = k_t, x_gammat, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable kt_wall equal 2/7*${YoungsModulus}*${atomRadius} -variable xgammat equal 0.0 +variable xgammat equal 1.0 variable mu_s equal 0.7 variable mu_s_wall equal 0.1 @@ -49,14 +49,14 @@ variable mu_roll equal 0.6 variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} variable gamma_roll equal 0.0 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} damping none +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} ######################################### ADD DIE AND PUNCH WALLS ############################################ variable disp_upper equal 0.0 variable disp_lower equal 0.0 -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${CoR} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} damping none" +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" variable dieHeight2 equal 2*${dieHeight} @@ -115,7 +115,7 @@ dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diam ############################################## RUN SIMULATION ################################################# -variable upper_punch_stroke equal 0.6733*${dieHeight} +variable upper_punch_stroke equal 0.7*${dieHeight} variable vel_upper equal 0.25 variable settling_steps equal round(0.02/dt) diff --git a/examples/granular/in.triaxial.compaction.12 b/examples/granular/in.triaxial.compaction.12 index eee9a2bfd8..8287bb22ba 100644 --- a/examples/granular/in.triaxial.compaction.12 +++ b/examples/granular/in.triaxial.compaction.12 @@ -24,20 +24,20 @@ variable atomRadius equal 0.5 pair_style granular -# mdr = E, nu, Y, gamma, psi_b, CoR +# mdr = E, nu, Y, gamma, psi_b, damp variable YoungsModulus equal 1e9 variable PoissonsRatio equal 0.3 variable YieldStress equal 50e6 variable SurfaceEnergy equal 0.0 variable psi_b equal 0.5 -variable CoR equal 0.5 +variable damp equal 1.0 # linear_history = k_t, x_gamma,t, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable xgammat equal 0.0 variable mu_s equal 0.5 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} damping none +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} ######################################### ADD IN PLANES ################################################ @@ -54,7 +54,7 @@ region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_d region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${CoR} tangential linear_history ${kt} ${xgammat} ${mu_s} damping none" +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} " fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts From ccd6eeb8af38b6c37f9b1517835aa0a13891f729 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Fri, 4 Apr 2025 16:53:57 +0200 Subject: [PATCH 032/396] unit test --- unittest/force-styles/test_dihedral_style.cpp | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/unittest/force-styles/test_dihedral_style.cpp b/unittest/force-styles/test_dihedral_style.cpp index 5d0bd86d2b..b2f1a36346 100644 --- a/unittest/force-styles/test_dihedral_style.cpp +++ b/unittest/force-styles/test_dihedral_style.cpp @@ -746,3 +746,44 @@ TEST(DihedralStyle, numdiff) cleanup_lammps(lmp, test_config); if (!verbose) ::testing::internal::GetCapturedStdout(); } + +TEST(DihedralStyle, extract) +{ + if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); + + LAMMPS::argv args = {"DihedralStyle", "-log", "none", "-echo", "screen", "-nocite"}; + + if (!verbose) ::testing::internal::CaptureStdout(); + LAMMPS *lmp = nullptr; + try { + lmp = init_lammps(args, test_config, true); + } catch (std::exception &e) { + if (!verbose) ::testing::internal::GetCapturedStdout(); + FAIL() << e.what(); + } + if (!verbose) ::testing::internal::GetCapturedStdout(); + + if (!lmp) { + std::cerr << "One or more prerequisite styles are not available " + "in this LAMMPS configuration:\n"; + for (auto prerequisite : test_config.prerequisites) { + std::cerr << prerequisite.first << "_style " << prerequisite.second << "\n"; + } + GTEST_SKIP(); + } + + auto *dihedral = lmp->force->dihedral; + void *ptr = nullptr; + int dim = 0; + for (auto extract : test_config.extract) { + ptr = dihedral->extract(extract.first.c_str(), dim); + EXPECT_NE(ptr, nullptr); + EXPECT_EQ(dim, extract.second); + } + ptr = dihedral->extract("does_not_exist", dim); + EXPECT_EQ(ptr, nullptr); + + if (!verbose) ::testing::internal::CaptureStdout(); + cleanup_lammps(lmp, test_config); + if (!verbose) ::testing::internal::GetCapturedStdout(); +} From 54d7f46151e22187cbe7716f3701dfd96dca68bb Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Fri, 4 Apr 2025 17:00:52 +0200 Subject: [PATCH 033/396] modifications in dihedral & dihedral_hybrid --- src/dihedral.cpp | 13 +++++++++++++ src/dihedral.h | 5 +++++ src/dihedral_hybrid.cpp | 8 ++++++++ src/dihedral_hybrid.h | 2 ++ 4 files changed, 28 insertions(+) diff --git a/src/dihedral.cpp b/src/dihedral.cpp index 14b59d2542..a6e66ac9cf 100644 --- a/src/dihedral.cpp +++ b/src/dihedral.cpp @@ -33,6 +33,7 @@ Dihedral::Dihedral(LAMMPS *_lmp) : Pointers(_lmp) { energy = 0.0; writedata = 0; + reinitflag = 1; allocated = 0; suffix_flag = Suffix::NONE; @@ -428,3 +429,15 @@ double Dihedral::memory_usage() bytes += (double) comm->nthreads * maxcvatom * 9 * sizeof(double); return bytes; } + +/* ----------------------------------------------------------------------- + reset all type-based dihedral params via init() +-------------------------------------------------------------------------- */ + +void Dihedral::reinit() +{ + if (!reinitflag) + error->all(FLERR, "Fix adapt interface to this dihedral style not supported"); + + init(); +} diff --git a/src/dihedral.h b/src/dihedral.h index 03a5690a49..7ca3379e44 100644 --- a/src/dihedral.h +++ b/src/dihedral.h @@ -37,6 +37,9 @@ class Dihedral : protected Pointers { // CENTROID_AVAIL = different and implemented // CENTROID_NOTAVAIL = different, not yet implemented + int reinitflag; // 0 if not compatible with fix adapt + // extract() method may still need to be added + // KOKKOS host/device flag and data masks ExecutionSpace execution_space; @@ -62,6 +65,8 @@ class Dihedral : protected Pointers { du = 0.0; du2 = 0.0; } + virtual void *extract(const char *, int &) { return nullptr; } + void reinit(); protected: int suffix_flag; // suffix compatibility flag diff --git a/src/dihedral_hybrid.cpp b/src/dihedral_hybrid.cpp index 3671391f5d..6210009170 100644 --- a/src/dihedral_hybrid.cpp +++ b/src/dihedral_hybrid.cpp @@ -326,6 +326,14 @@ void DihedralHybrid::init_style() if (styles[m]) styles[m]->init_style(); } +/* ---------------------------------------------------------------------- */ + +int DihedralHybrid::check_itype(int itype, char *substyle) +{ + if (strcmp(keywords[map[itype]], substyle) == 0) return 1; + return 0; +} + /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ diff --git a/src/dihedral_hybrid.h b/src/dihedral_hybrid.h index debc8a9d8d..4dcadcb67a 100644 --- a/src/dihedral_hybrid.h +++ b/src/dihedral_hybrid.h @@ -40,6 +40,8 @@ class DihedralHybrid : public Dihedral { void read_restart(FILE *) override; double memory_usage() override; + int check_itype(int, char *); + protected: int *map; // which style each dihedral type points to From 08795487374ea477e3a413bd26986b9bdfe7daf4 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Fri, 4 Apr 2025 17:03:58 +0200 Subject: [PATCH 034/396] change fix adapt header file --- src/fix_adapt.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/fix_adapt.h b/src/fix_adapt.h index 9f064a163e..5ed6559ef1 100644 --- a/src/fix_adapt.h +++ b/src/fix_adapt.h @@ -44,7 +44,7 @@ class FixAdapt : public Fix { private: int nadapt, resetflag, scaleflag, massflag; - int anypair, anybond, anyangle, anyimproper; + int anypair, anybond, anyangle, anydihedral, anyimproper; int nlevels_respa; char *id_fix_diam, *id_fix_chg; class FixStoreAtom *fix_diam, *fix_chg; @@ -57,9 +57,10 @@ class FixAdapt : public Fix { char *pstyle, *pparam; char *bstyle, *bparam; char *astyle, *aparam; + char *dstyle, *dparam; char *istyle, *iparam; int ilo, ihi, jlo, jhi; - int pdim, bdim, adim, idim; + int pdim, bdim, adim, ddim, idim; double *scalar, scalar_orig; double *vector, *vector_orig; double **array, **array_orig; @@ -67,6 +68,7 @@ class FixAdapt : public Fix { class Pair *pair; class Bond *bond; class Angle *angle; + class Dihedral *dihedral; class Improper *improper; }; From 3182dc26da3402463ad4aceb0e4ac506598e9dcb Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Fri, 4 Apr 2025 17:06:29 +0200 Subject: [PATCH 035/396] extract() implementation for dihedral quadratic --- src/EXTRA-MOLECULE/dihedral_quadratic.cpp | 12 ++++++++++++ src/EXTRA-MOLECULE/dihedral_quadratic.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/EXTRA-MOLECULE/dihedral_quadratic.cpp b/src/EXTRA-MOLECULE/dihedral_quadratic.cpp index 2350095f0d..e61f9eff74 100644 --- a/src/EXTRA-MOLECULE/dihedral_quadratic.cpp +++ b/src/EXTRA-MOLECULE/dihedral_quadratic.cpp @@ -435,3 +435,15 @@ void DihedralQuadratic::born_matrix(int nd, int i1, int i2, int i3, int i4, du = - 2.0 * k[type] * dphi * siinv; du2 = 2.0 * k[type] * siinv * siinv * ( 1.0 - dphi * c * siinv) ; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralQuadratic::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "phi0") == 0) return (void *) phi0; + return nullptr; +} diff --git a/src/EXTRA-MOLECULE/dihedral_quadratic.h b/src/EXTRA-MOLECULE/dihedral_quadratic.h index 89f6fa3b25..c584f1ae09 100644 --- a/src/EXTRA-MOLECULE/dihedral_quadratic.h +++ b/src/EXTRA-MOLECULE/dihedral_quadratic.h @@ -34,6 +34,7 @@ class DihedralQuadratic : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *k, *phi0; From 996faf7a94675286682273d425365369f7e44d46 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Fri, 4 Apr 2025 17:11:30 +0200 Subject: [PATCH 036/396] update documentation --- doc/src/fix_adapt.rst | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 2eec2eb457..681f9bb0af 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -14,7 +14,7 @@ Syntax * adapt = style name of this fix command * N = adapt simulation settings every this many timesteps * one or more attribute/arg pairs may be appended -* attribute = *pair* or *bond* or *angle* or *improper* or *kspace* or *atom* +* attribute = *pair* or *bond* or *angle* or *dihedral* or *improper* or *kspace* or *atom* .. parsed-literal:: @@ -33,6 +33,11 @@ Syntax aparam = parameter to adapt over time I = type angle to set parameter for (integer or type label) v_name = variable with name that calculates value of aparam + *dihedral* args = dstyle dparam I v_name + dstyle = dihedral style name (e.g., quadratic) + dparam = parameter to adapt over time + I = type dihedral to set parameter for (integer or type label) + v_name = variable with name that calculates value of iparam *improper* args = istyle iparam I v_name istyle = improper style name (e.g., cvff) iparam = parameter to adapt over time @@ -433,6 +438,34 @@ this fix uses to reset theta0 needs to generate values in radians. ---------- +.. versionadded:: TBD + +The *dihedral* keyword uses the specified variable to change the value of +a dihedral coefficient over time, very similar to how the *angle* keyword +operates. The only difference is that now a dihedral coefficient for a +given dihedral type is adapted. + +A wild-card asterisk can be used in place of or in conjunction with the +dihedral type argument to set the coefficients for multiple dihedral types. +This takes the form "\*" or "\*n" or "m\*" or "m\*n". If :math:`N` is +the number of dihedral types, then an asterisk with no numeric values means +all types from 1 to :math:`N`. A leading asterisk means all types from +1 to n (inclusive). A trailing asterisk means all types from m to +:math:`N` (inclusive). A middle asterisk means all types from m to n +(inclusive). + +If :doc:`dihedral_style hybrid ` is used, *dstyle* should be a +sub-style name. The dihedral styles that currently work with fix adapt are: + ++---------------------------------------------------------+----------------+----------------+ +| :doc:`quadratic ` | k,phi0 | type dihedrals | ++---------------------------------------------------------+----------------+----------------+ + +Note that internally, phi0 is stored in radians, so the variable +this fix use to reset phi0 needs to generate values in radians. + +---------- + .. versionadded:: 2Apr2025 The *improper* keyword uses the specified variable to change the value of From d1dd05bf4e3de907401cc75f9eb38e4d53873fa1 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Fri, 4 Apr 2025 17:19:54 +0200 Subject: [PATCH 037/396] update unit test for quadratic dihedral --- unittest/force-styles/tests/dihedral-quadratic.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unittest/force-styles/tests/dihedral-quadratic.yaml b/unittest/force-styles/tests/dihedral-quadratic.yaml index 21ddf42df0..3780ec61e4 100644 --- a/unittest/force-styles/tests/dihedral-quadratic.yaml +++ b/unittest/force-styles/tests/dihedral-quadratic.yaml @@ -17,7 +17,9 @@ dihedral_coeff: ! | 3 25 100 4 35 110 5 85 120 -extract: ! "" +extract: ! | + k 1 + phi0 1 natoms: 29 init_energy: 6216.314347066598 init_stress: ! |2- From 30bbbafd9d55d52a0a434bf0071ae825d032b2ec Mon Sep 17 00:00:00 2001 From: jtclemm Date: Fri, 4 Apr 2025 09:57:43 -0600 Subject: [PATCH 038/396] Cleaning up MDR files --- doc/src/pair_granular.rst | 12 +- examples/granular/in.tableting.200 | 15 +- examples/granular/in.triaxial.compaction.12 | 20 +- .../granular/log.4Feb25.tableting.200.g++.1 | 791 ++++++++++++++++++ .../log.4Feb25.triaxial.compaction.12.g++.1 | 779 +++++++++++++++++ src/GRANULAR/fix_granular_mdr.cpp | 19 +- src/GRANULAR/gran_sub_mod_damping.cpp | 11 +- src/GRANULAR/gran_sub_mod_damping.h | 2 +- src/GRANULAR/gran_sub_mod_normal.cpp | 1 - 9 files changed, 1615 insertions(+), 35 deletions(-) create mode 100644 examples/granular/log.4Feb25.tableting.200.g++.1 create mode 100644 examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 40339ab476..9804c90cef 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -178,6 +178,8 @@ two-part series :ref:`Zunker and Kamrin Part I ` and :ref:`Zunker and Kamrin Part II `. Further development and demonstrations of its application to industrially relevant powder compaction processes are presented in :ref:`Zunker et al. `. +If you use the *mdr* normal model, is recommended you use the *mdr* damping model +described below. The model requires the following inputs: @@ -220,12 +222,6 @@ effective stiffness related to the bulk elastic response. Here, :math:`\kappa = E/(3(1-2\nu))` is the bulk modulus and :math:`R_\textrm{min}` is the radius of the smallest particle. -.. note:: - - The *mdr* model requires some specific settings to function properly, - please read the following text carefully to ensure all requirements are - followed. - The *atom_style* must be set to *sphere 1* to enable dynamic particle radii. The *mdr* model is designed to respect the incompressibility of plastic deformation and inherently tracks free surface displacements @@ -335,7 +331,7 @@ for the damping model currently supported are: .. note:: It is suggested to use the *mdr* damping model with when the normal - *mdr* contact model is defined. + *mdr* contact model is defined. If the *damping* keyword is not specified, the *viscoelastic* model is used by default. @@ -431,7 +427,7 @@ by the normal *mdr* contact model to determine the damping coefficent: .. math:: - \eta_n = \eta_{n0} (m_{eff}k_{mdr})^{1/2}, + \eta_n = \eta_{n0} (m_{eff}k_{mdr})^{1/2}, where :math:`k_{mdr}` is proportional to contact radius :math:`a_{mdr}` tracked by the normal *mdr* contact model: diff --git a/examples/granular/in.tableting.200 b/examples/granular/in.tableting.200 index 4ea5801bf5..b9443cc36d 100644 --- a/examples/granular/in.tableting.200 +++ b/examples/granular/in.tableting.200 @@ -40,7 +40,7 @@ variable psi_b equal 0.5 # linear_history = k_t, x_gammat, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable kt_wall equal 2/7*${YoungsModulus}*${atomRadius} -variable xgammat equal 1.0 +variable xgammat equal 1.0 variable mu_s equal 0.7 variable mu_s_wall equal 0.1 @@ -49,7 +49,10 @@ variable mu_roll equal 0.6 variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} variable gamma_roll equal 0.0 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & + damping mdr & + tangential linear_history ${kt} ${xgammat} ${mu_s} & + rolling sds ${k_roll} ${gamma_roll} ${mu_roll} ######################################### ADD DIE AND PUNCH WALLS ############################################ @@ -73,7 +76,7 @@ variable avgUpperPunchForce equal c_avgUpperPunchForce compute avgLowerPunchForce all reduce sum f_lowerPunch[4] variable avgLowerPunchForce equal c_avgLowerPunchForce -fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no +#fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no ##################################### INTEGRATION AND GRAVITY ################################################# @@ -109,8 +112,8 @@ variable syy_ave equal c_sigmayy_ave variable szz_ave equal c_sigmazz_ave variable Vparticles equal c_Velas_sum -fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no -dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz +#fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no +#dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz #dump dumpParticlesVTK all vtk ${output_rate} post/particles_*.vtk id x y z fx fy fz vx vy vz c_ke radius c_sigmaxx c_sigmayy c_sigmazz ############################################## RUN SIMULATION ################################################# @@ -146,4 +149,4 @@ run ${ejection_steps} variable disp_lower equal ${dieHeight} variable disp_upper equal ${dieHeight}*0.9 variable max_disp equal ${dieRadius}*0.75 -run ${free_float_steps} \ No newline at end of file +run ${free_float_steps} diff --git a/examples/granular/in.triaxial.compaction.12 b/examples/granular/in.triaxial.compaction.12 index 8287bb22ba..d10e325721 100644 --- a/examples/granular/in.triaxial.compaction.12 +++ b/examples/granular/in.triaxial.compaction.12 @@ -1,7 +1,7 @@ ############################### SIMULATION SETTINGS ################################################### atom_style sphere 1 -atom_modify map array +atom_modify map array comm_modify vel yes units si newton off @@ -24,7 +24,7 @@ variable atomRadius equal 0.5 pair_style granular -# mdr = E, nu, Y, gamma, psi_b, damp +# mdr = E, nu, Y, gamma, psi_b, damp variable YoungsModulus equal 1e9 variable PoissonsRatio equal 0.3 variable YieldStress equal 50e6 @@ -37,7 +37,9 @@ variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable xgammat equal 0.0 variable mu_s equal 0.5 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & + damping mdr & + tangential linear_history ${kt} ${xgammat} ${mu_s} ######################################### ADD IN PLANES ################################################ @@ -72,12 +74,12 @@ variable plane_xz_neg_force equal c_plane_xz_neg_force compute plane_yz_neg_force all reduce sum f_plane_yz_neg[2] variable plane_yz_neg_force equal c_plane_yz_neg_force -fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no +#fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no -######################################## SCREEN OUTPUT #################################################### +######################################## SCREEN OUTPUT #################################################### compute 1 all erotate/sphere -thermo_style custom dt step atoms ke c_1 vol +thermo_style custom dt step atoms ke c_1 vol thermo 100 thermo_modify lost ignore norm no @@ -89,8 +91,8 @@ variable compression_steps equal round(${disp_max}/${ddisp}) variable output_rate equal round(${compression_steps}/100) ##################################### SET UP DUMP OUTPUTS #################################################### - -dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius + +#dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius #dump dmp all vtk ${output_rate} post/triaxial12particles_*.vtk id type mass x y z vx vy vz fx fy fz radius #################################### COMPRESS THE PARTICLES ################################################## @@ -101,7 +103,7 @@ run 0 compute Ac_1_12 particles_1_12 pair/local p13 cutoff radius compute Ac_1_12_sum particles_1_12 reduce sum c_Ac_1_12 inputs local variable Ac_1_12 equal c_Ac_1_12_sum -fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no +#fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no variable plane_disp equal ${ddisp}*elapsed variable plane_disp_neg equal -${ddisp}*elapsed diff --git a/examples/granular/log.4Feb25.tableting.200.g++.1 b/examples/granular/log.4Feb25.tableting.200.g++.1 new file mode 100644 index 0000000000..df6428ff1a --- /dev/null +++ b/examples/granular/log.4Feb25.tableting.200.g++.1 @@ -0,0 +1,791 @@ +LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-581-g384d7f446b-modified) +##################################### SIMULATION SETTINGS ################################################### + +atom_style sphere 1 +atom_modify map array +comm_modify vel yes +units si +newton off +neighbor 1.0e-3 bin +neigh_modify every 10 delay 60 check no +timestep 4e-6 +#processors 2 2 1 + +############################## SIMULATION BOUNDING BOX AND INSERT PARTICLES ################################# + +boundary f f f +read_data spheres200.data +Reading data file ... + orthogonal box = (-0.005 -0.005 -0.001) to (0.005 0.005 0.02) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 200 atoms + read_data CPU = 0.004 seconds + +#################################### ADD DIE AND ATOM PARAMETERIZATION ###################################### + +variable atomRadius equal 0.44e-3*1.25 +variable atomDiameter equal 2*${atomRadius} +variable atomDiameter equal 2*0.00055 +variable atomDensity equal 1560 +variable atomMassAvg equal ${atomDensity}*4.0/3.0*PI*${atomRadius}^3.0 +variable atomMassAvg equal 1560*4.0/3.0*PI*${atomRadius}^3.0 +variable atomMassAvg equal 1560*4.0/3.0*PI*0.00055^3.0 +variable dieRadius equal 4e-3 +variable dieHeight equal 1e-2 + +############################## PARTICLE MATERIAL PROPERTIES AND FORCE MODEL ################################## + +pair_style granular + +# mdr = E, nu, Y, gamma, psi_b, damp +variable YoungsModulus equal 5e6 +variable YieldStress equal 1.9e5 +variable PoissonsRatio equal 0.4 +variable SurfaceEnergy equal 2 +variable SurfaceEnergyWall equal 0.0 +variable damp equal 1.0 +variable psi_b equal 0.5 + +# linear_history = k_t, x_gammat, mu_s +variable kt equal 2/7*${YoungsModulus}*${atomRadius} +variable kt equal 2/7*5000000*${atomRadius} +variable kt equal 2/7*5000000*0.00055 +variable kt_wall equal 2/7*${YoungsModulus}*${atomRadius} +variable kt_wall equal 2/7*5000000*${atomRadius} +variable kt_wall equal 2/7*5000000*0.00055 +variable xgammat equal 1.0 +variable mu_s equal 0.7 +variable mu_s_wall equal 0.1 + +# sds = mu_roll, k_roll, gamma_roll +variable mu_roll equal 0.6 +variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} +variable k_roll equal 2.25*0.6*${mu_roll}*${YoungsModulus}*${atomRadius} +variable k_roll equal 2.25*0.6*0.6*${YoungsModulus}*${atomRadius} +variable k_roll equal 2.25*0.6*0.6*5000000*${atomRadius} +variable k_roll equal 2.25*0.6*0.6*5000000*0.00055 +variable gamma_roll equal 0.0 + +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 0.6 + +######################################### ADD DIE AND PUNCH WALLS ############################################ + +variable disp_upper equal 0.0 +variable disp_lower equal 0.0 + +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" +granular mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 + +variable dieHeight2 equal 2*${dieHeight} +variable dieHeight2 equal 2*0.01 + +region lowerPunch plane 0 0 0 0 0 1 side in units box move NULL NULL v_disp_lower units box +region upperPunch plane 0 0 ${dieHeight} 0 0 -1 side in move NULL NULL v_disp_upper units box +region upperPunch plane 0 0 0.01 0 0 -1 side in move NULL NULL v_disp_upper units box +region die cylinder z 0 0 ${dieRadius} 0 ${dieHeight2} side in units box +region die cylinder z 0 0 0.004 0 ${dieHeight2} side in units box +region die cylinder z 0 0 0.004 0 0.02 side in units box + +fix lowerPunch all wall/gran/region ${wall_contact_string} region lowerPunch contacts +fix lowerPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region lowerPunch contacts +fix upperPunch all wall/gran/region ${wall_contact_string} region upperPunch contacts +fix upperPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region upperPunch contacts +fix die all wall/gran/region ${wall_contact_string} region die contacts +fix die all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region die contacts + +compute avgUpperPunchForce all reduce sum f_upperPunch[4] +variable avgUpperPunchForce equal c_avgUpperPunchForce +compute avgLowerPunchForce all reduce sum f_lowerPunch[4] +variable avgLowerPunchForce equal c_avgLowerPunchForce + +#fix printFD all print 1 "${disp_upper} ${avgUpperPunchForce} ${avgLowerPunchForce}" file punch_force_disp_tableting200.csv screen no + +##################################### INTEGRATION AND GRAVITY ################################################# + +fix 1 all nve/sphere +fix grav all gravity 9.81 vector 0 0 -1 + +########################################### SCREEN OUTPUT #################################################### + +compute 1 all erotate/sphere +thermo_style custom dt step atoms ke vol v_disp_upper +thermo 100 +thermo_modify lost ignore norm no + +##################################### SET UP DUMP OUTPUTS #################################################### + +compute ke all ke/atom +variable output_rate equal round(1e-3/dt) + +run 0 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289 + +@Article{zunker2024mechanicallyI, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part I: Utilizing the method of dimensionality reduction}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105492}, +} + +@Article{zunker2024mechanicallyII, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part II: Contact under high compaction—modeling a bulk elastic response}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105493}, +} + +@Article{zunker2025experimentally, + author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken}, + title = {Experimentally validated DEM for large deformation powder compaction: + mechanically-derived contact model and screening of non-physical contacts}, + year = {2025}, + journal = {engrXiv}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 10 steps, delay = 60 steps, check = no + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 0.002318 + ghost atom cutoff = 0.002318 + binsize = 0.001159, bins = 9 9 19 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair granular, perpetual + attributes: half, newton off, size, history + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 0 200 0 2.1e-06 0 +Loop time of 8.51e-07 on 1 procs for 0 steps with 200 atoms + +117.5% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 8.51e-07 | | |100.00 + +Nlocal: 200 ave 200 max 200 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 1341 ave 1341 max 1341 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 1341 +Ave neighs/atom = 6.705 +Neighbor list builds = 0 +Dangerous builds not checked + +compute sigmaxx all property/atom d_sigmaxx +compute sigmayy all property/atom d_sigmayy +compute sigmazz all property/atom d_sigmazz +compute Velas all property/atom d_Velas + +compute sigmaxx_ave all reduce ave c_sigmaxx +compute sigmayy_ave all reduce ave c_sigmayy +compute sigmazz_ave all reduce ave c_sigmazz +compute Velas_sum all reduce sum c_Velas + +variable sxx_ave equal c_sigmaxx_ave +variable syy_ave equal c_sigmayy_ave +variable szz_ave equal c_sigmazz_ave +variable Vparticles equal c_Velas_sum + +#fix log all print 1 "${sxx_ave} ${syy_ave} ${szz_ave} ${Vparticles}" file average_normal_stresses_tableting200.csv screen no +#dump dumpParticles all custom ${output_rate} tableting200.dump id type mass diameter x y z vx vy vz fx fy fz c_ke c_sigmaxx c_sigmayy c_sigmazz +#dump dumpParticlesVTK all vtk ${output_rate} post/particles_*.vtk id x y z fx fy fz vx vy vz c_ke radius c_sigmaxx c_sigmayy c_sigmazz + +############################################## RUN SIMULATION ################################################# + +variable upper_punch_stroke equal 0.7*${dieHeight} +variable upper_punch_stroke equal 0.7*0.01 +variable vel_upper equal 0.25 + +variable settling_steps equal round(0.02/dt) +variable compression_steps equal 2*round(${upper_punch_stroke}/${vel_upper}/dt) +variable compression_steps equal 2*round(0.007/${vel_upper}/dt) +variable compression_steps equal 2*round(0.007/0.25/dt) +variable ejection_steps equal ${compression_steps} +variable ejection_steps equal 14000 +variable free_float_steps equal round(0.02/dt) + +##### SETTLING ##### + +run ${settling_steps} +run 5000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 0 200 0 2.1e-06 0 + 4e-06 100 200 1.5945503e-09 2.1e-06 0 + 4e-06 200 200 6.3770738e-09 2.1e-06 0 + 4e-06 300 200 1.4245359e-08 2.1e-06 0 + 4e-06 400 200 2.5260505e-08 2.1e-06 0 + 4e-06 500 200 3.9464751e-08 2.1e-06 0 + 4e-06 600 200 5.6858098e-08 2.1e-06 0 + 4e-06 700 200 7.7385952e-08 2.1e-06 0 + 4e-06 800 198 1.0059548e-07 2.1e-06 0 + 4e-06 900 196 1.2599473e-07 2.1e-06 0 + 4e-06 1000 194 1.5428578e-07 2.1e-06 0 + 4e-06 1100 194 1.8644695e-07 2.1e-06 0 + 4e-06 1200 192 2.2088698e-07 2.1e-06 0 + 4e-06 1300 192 2.5897366e-07 2.1e-06 0 + 4e-06 1400 192 3.0013683e-07 2.1e-06 0 + 4e-06 1500 192 3.4277758e-07 2.1e-06 0 + 4e-06 1600 192 3.9077177e-07 2.1e-06 0 + 4e-06 1700 192 4.3898925e-07 2.1e-06 0 + 4e-06 1800 186 4.736674e-07 2.1e-06 0 + 4e-06 1900 184 5.2110858e-07 2.1e-06 0 + 4e-06 2000 184 5.7848899e-07 2.1e-06 0 + 4e-06 2100 184 6.3492469e-07 2.1e-06 0 + 4e-06 2200 184 6.9441989e-07 2.1e-06 0 + 4e-06 2300 182 inf 2.1e-06 0 + 4e-06 2400 176 7.9307687e-07 2.1e-06 0 + 4e-06 2500 176 8.599965e-07 2.1e-06 0 + 4e-06 2600 176 9.2970927e-07 2.1e-06 0 + 4e-06 2700 176 1.0022152e-06 2.1e-06 0 + 4e-06 2800 176 inf 2.1e-06 0 + 4e-06 2900 174 1.1458142e-06 2.1e-06 0 + 4e-06 3000 172 1.2159972e-06 2.1e-06 0 + 4e-06 3100 172 inf 2.1e-06 0 + 4e-06 3200 170 1.3640273e-06 2.1e-06 0 + 4e-06 3300 164 1.4023496e-06 2.1e-06 0 + 4e-06 3400 164 1.4878891e-06 2.1e-06 0 + 4e-06 3500 164 1.5760184e-06 2.1e-06 0 + 4e-06 3600 164 1.6667377e-06 2.1e-06 0 + 4e-06 3700 162 1.7486967e-06 2.1e-06 0 + 4e-06 3800 160 1.8165262e-06 2.1e-06 0 + 4e-06 3900 158 1.8886488e-06 2.1e-06 0 + 4e-06 4000 158 1.9853138e-06 2.1e-06 0 + 4e-06 4100 158 inf 2.1e-06 0 + 4e-06 4200 156 2.1616605e-06 2.1e-06 0 + 4e-06 4300 156 2.2655984e-06 2.1e-06 0 + 4e-06 4400 156 inf 2.1e-06 0 + 4e-06 4500 152 2.4161761e-06 2.1e-06 0 + 4e-06 4600 152 2.497822e-06 2.1e-06 0 + 4e-06 4700 150 2.6001287e-06 2.1e-06 0 + 4e-06 4800 148 inf 2.1e-06 0 + 4e-06 4900 146 inf 2.1e-06 0 + 4e-06 5000 140 2.7812394e-06 2.1e-06 0 +Loop time of 0.432192 on 1 procs for 5000 steps with 140 atoms + +99.7% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.10597 | 0.10597 | 0.10597 | 0.0 | 24.52 +Neigh | 0.011871 | 0.011871 | 0.011871 | 0.0 | 2.75 +Comm | 0.00034652 | 0.00034652 | 0.00034652 | 0.0 | 0.08 +Output | 0.00027596 | 0.00027596 | 0.00027596 | 0.0 | 0.06 +Modify | 0.31284 | 0.31284 | 0.31284 | 0.0 | 72.39 +Other | | 0.0008893 | | | 0.21 + +Nlocal: 140 ave 140 max 140 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 865 ave 865 max 865 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 865 +Ave neighs/atom = 6.1785714 +Neighbor list builds = 83 +Dangerous builds not checked + +##### Compression & Release ##### + +variable punch_frequency equal PI/2/(dt*${compression_steps}/2) +variable punch_frequency equal PI/2/(dt*14000/2) +variable disp_upper equal -${upper_punch_stroke}*sin(${punch_frequency}*elapsed*dt) +variable disp_upper equal -0.007*sin(${punch_frequency}*elapsed*dt) +variable disp_upper equal -0.007*sin(56.0998688141035*elapsed*dt) +variable short_release equal round(${compression_steps}*1.0) +variable short_release equal round(14000*1.0) +run ${short_release} +run 14000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 5000 140 2.7812394e-06 2.1e-06 0 + 4e-06 5100 140 2.8895541e-06 2.1e-06 -0.00015706645 + 4e-06 5200 136 2.9030642e-06 2.1e-06 -0.00031405381 + 4e-06 5300 134 2.9801402e-06 2.1e-06 -0.00047088304 + 4e-06 5400 134 inf 2.1e-06 -0.00062747516 + 4e-06 5500 130 3.1361708e-06 2.1e-06 -0.00078375133 + 4e-06 5600 130 3.224988e-06 2.1e-06 -0.00093963286 + 4e-06 5700 128 3.2981553e-06 2.1e-06 -0.0010950413 + 4e-06 5800 126 3.3346425e-06 2.1e-06 -0.0012498983 + 4e-06 5900 126 3.4495324e-06 2.1e-06 -0.0014041259 + 4e-06 6000 124 3.4436288e-06 2.1e-06 -0.0015576465 + 4e-06 6100 122 3.5108806e-06 2.1e-06 -0.0017103828 + 4e-06 6200 118 3.4808187e-06 2.1e-06 -0.0018622579 + 4e-06 6300 116 3.5520892e-06 2.1e-06 -0.0020131953 + 4e-06 6400 116 3.6651266e-06 2.1e-06 -0.002163119 + 4e-06 6500 116 3.7768528e-06 2.1e-06 -0.0023119534 + 4e-06 6600 114 3.8296982e-06 2.1e-06 -0.0024596238 + 4e-06 6700 110 3.8220731e-06 2.1e-06 -0.0026060556 + 4e-06 6800 108 3.8409573e-06 2.1e-06 -0.0027511752 + 4e-06 6900 108 inf 2.1e-06 -0.0028949095 + 4e-06 7000 104 3.9206342e-06 2.1e-06 -0.0030371862 + 4e-06 7100 102 3.9647246e-06 2.1e-06 -0.0031779335 + 4e-06 7200 102 inf 2.1e-06 -0.0033170806 + 4e-06 7300 98 3.9766723e-06 2.1e-06 -0.0034545575 + 4e-06 7400 90 3.7821936e-06 2.1e-06 -0.0035902949 + 4e-06 7500 90 inf 2.1e-06 -0.0037242245 + 4e-06 7600 86 3.8144737e-06 2.1e-06 -0.0038562789 + 4e-06 7700 84 3.7897749e-06 2.1e-06 -0.0039863915 + 4e-06 7800 82 3.8008682e-06 2.1e-06 -0.0041144968 + 4e-06 7900 80 3.791409e-06 2.1e-06 -0.0042405303 + 4e-06 8000 76 3.7336309e-06 2.1e-06 -0.0043644286 + 4e-06 8100 76 inf 2.1e-06 -0.0044861293 + 4e-06 8200 72 3.7708462e-06 2.1e-06 -0.0046055711 + 4e-06 8300 72 3.8690393e-06 2.1e-06 -0.0047226938 + 4e-06 8400 68 inf 2.1e-06 -0.0048374385 + 4e-06 8500 64 3.6623177e-06 2.1e-06 -0.0049497475 + 4e-06 8600 62 3.6134274e-06 2.1e-06 -0.005059564 + 4e-06 8700 62 3.6965363e-06 2.1e-06 -0.005166833 + 4e-06 8800 60 3.5674683e-06 2.1e-06 -0.0052715003 + 4e-06 8900 54 3.3423076e-06 2.1e-06 -0.0053735132 + 4e-06 9000 50 3.1486697e-06 2.1e-06 -0.0054728204 + 4e-06 9100 48 3.0716142e-06 2.1e-06 -0.0055693718 + 4e-06 9200 46 2.9984533e-06 2.1e-06 -0.005663119 + 4e-06 9300 46 inf 2.1e-06 -0.0057540145 + 4e-06 9400 34 inf 2.1e-06 -0.0058420128 + 4e-06 9500 32 2.4147256e-06 2.1e-06 -0.0059270694 + 4e-06 9600 32 inf 2.1e-06 -0.0060091416 + 4e-06 9700 26 inf 2.1e-06 -0.0060881879 + 4e-06 9800 20 1.5991947e-06 2.1e-06 -0.0061641687 + 4e-06 9900 20 inf 2.1e-06 -0.0062370457 + 4e-06 10000 16 1.3327917e-06 2.1e-06 -0.0063067821 + 4e-06 10100 10 8.8157027e-07 2.1e-06 -0.0063733428 + 4e-06 10200 10 8.9614642e-07 2.1e-06 -0.0064366944 + 4e-06 10300 10 8.9775988e-07 2.1e-06 -0.0064968049 + 4e-06 10400 10 9.0812889e-07 2.1e-06 -0.0065536441 + 4e-06 10500 10 9.003094e-07 2.1e-06 -0.0066071833 + 4e-06 10600 10 8.8275797e-07 2.1e-06 -0.0066573956 + 4e-06 10700 10 8.6537937e-07 2.1e-06 -0.0067042557 + 4e-06 10800 10 8.4817361e-07 2.1e-06 -0.00674774 + 4e-06 10900 10 8.311407e-07 2.1e-06 -0.0067878266 + 4e-06 11000 10 8.1428062e-07 2.1e-06 -0.0068244954 + 4e-06 11100 10 7.9759338e-07 2.1e-06 -0.0068577278 + 4e-06 11200 10 7.8107899e-07 2.1e-06 -0.0068875071 + 4e-06 11300 10 7.6473743e-07 2.1e-06 -0.0069138184 + 4e-06 11400 10 7.4856871e-07 2.1e-06 -0.0069366483 + 4e-06 11500 10 6.5214996e-07 2.1e-06 -0.0069559855 + 4e-06 11600 10 8.9415748e-07 2.1e-06 -0.0069718201 + 4e-06 11700 10 8.718476e-07 2.1e-06 -0.0069841441 + 4e-06 11800 10 1.0390866e-06 2.1e-06 -0.0069929515 + 4e-06 11900 10 1.058099e-06 2.1e-06 -0.0069982376 + 4e-06 12000 10 1.0772841e-06 2.1e-06 -0.007 + 4e-06 12100 10 1.0966421e-06 2.1e-06 -0.0069982376 + 4e-06 12200 10 1.116173e-06 2.1e-06 -0.0069929515 + 4e-06 12300 10 1.1358767e-06 2.1e-06 -0.0069841441 + 4e-06 12400 10 1.1557532e-06 2.1e-06 -0.0069718201 + 4e-06 12500 10 1.1709163e-06 2.1e-06 -0.0069559855 + 4e-06 12600 10 1.1781568e-06 2.1e-06 -0.0069366483 + 4e-06 12700 10 1.1814023e-06 2.1e-06 -0.0069138184 + 4e-06 12800 10 1.182238e-06 2.1e-06 -0.0068875071 + 4e-06 12900 10 1.1321834e-06 2.1e-06 -0.0068577278 + 4e-06 13000 10 1.1602658e-06 2.1e-06 -0.0068244954 + 4e-06 13100 10 1.1403281e-06 2.1e-06 -0.0067878266 + 4e-06 13200 10 1.1205632e-06 2.1e-06 -0.00674774 + 4e-06 13300 10 1.1009712e-06 2.1e-06 -0.0067042557 + 4e-06 13400 10 1.081552e-06 2.1e-06 -0.0066573956 + 4e-06 13500 10 1.0623057e-06 2.1e-06 -0.0066071833 + 4e-06 13600 10 9.7690472e-07 2.1e-06 -0.0065536441 + 4e-06 13700 10 8.7554649e-07 2.1e-06 -0.0064968049 + 4e-06 13800 10 8.6114161e-07 2.1e-06 -0.0064366944 + 4e-06 13900 10 7.2229969e-07 2.1e-06 -0.0063733428 + 4e-06 14000 10 6.0299298e-07 2.1e-06 -0.0063067821 + 4e-06 14100 10 5.9691906e-07 2.1e-06 -0.0062370457 + 4e-06 14200 10 5.8877052e-07 2.1e-06 -0.0061641687 + 4e-06 14300 10 5.8079481e-07 2.1e-06 -0.0060881879 + 4e-06 14400 10 5.0821182e-07 2.1e-06 -0.0060091416 + 4e-06 14500 10 4.5974587e-07 2.1e-06 -0.0059270694 + 4e-06 14600 10 4.5438391e-07 2.1e-06 -0.0058420128 + 4e-06 14700 10 4.4919479e-07 2.1e-06 -0.0057540145 + 4e-06 14800 10 3.6176002e-07 2.1e-06 -0.005663119 + 4e-06 14900 10 3.5835307e-07 2.1e-06 -0.0055693718 + 4e-06 15000 10 3.5511897e-07 2.1e-06 -0.0054728204 + 4e-06 15100 10 3.5205771e-07 2.1e-06 -0.0053735132 + 4e-06 15200 10 2.4180157e-07 2.1e-06 -0.0052715003 + 4e-06 15300 10 1.9792566e-07 2.1e-06 -0.005166833 + 4e-06 15400 10 1.9768384e-07 2.1e-06 -0.005059564 + 4e-06 15500 10 1.6550345e-07 2.1e-06 -0.0049497475 + 4e-06 15600 10 1.6608824e-07 2.1e-06 -0.0048374385 + 4e-06 15700 10 1.4780766e-07 2.1e-06 -0.0047226938 + 4e-06 15800 10 1.4899916e-07 2.1e-06 -0.0046055711 + 4e-06 15900 10 1.503635e-07 2.1e-06 -0.0044861293 + 4e-06 16000 10 1.5190069e-07 2.1e-06 -0.0043644286 + 4e-06 16100 10 1.5361071e-07 2.1e-06 -0.0042405303 + 4e-06 16200 10 1.5373505e-07 2.1e-06 -0.0041144968 + 4e-06 16300 10 1.5202036e-07 2.1e-06 -0.0039863915 + 4e-06 16400 10 1.5047851e-07 2.1e-06 -0.0038562789 + 4e-06 16500 10 1.491095e-07 2.1e-06 -0.0037242245 + 4e-06 16600 10 1.4791333e-07 2.1e-06 -0.0035902949 + 4e-06 16700 10 1.4689e-07 2.1e-06 -0.0034545575 + 4e-06 16800 10 1.460395e-07 2.1e-06 -0.0033170806 + 4e-06 16900 10 1.4536185e-07 2.1e-06 -0.0031779335 + 4e-06 17000 10 1.4485704e-07 2.1e-06 -0.0030371862 + 4e-06 17100 10 1.4452507e-07 2.1e-06 -0.0028949095 + 4e-06 17200 10 1.4436594e-07 2.1e-06 -0.0027511752 + 4e-06 17300 10 1.4297672e-07 2.1e-06 -0.0026060556 + 4e-06 17400 10 1.4034469e-07 2.1e-06 -0.0024596238 + 4e-06 17500 10 1.378855e-07 2.1e-06 -0.0023119534 + 4e-06 17600 10 1.3559914e-07 2.1e-06 -0.002163119 + 4e-06 17700 10 1.3348563e-07 2.1e-06 -0.0020131953 + 4e-06 17800 10 1.3154496e-07 2.1e-06 -0.0018622579 + 4e-06 17900 10 1.2977712e-07 2.1e-06 -0.0017103828 + 4e-06 18000 10 1.2659132e-07 2.1e-06 -0.0015576465 + 4e-06 18100 10 1.241758e-07 2.1e-06 -0.0014041259 + 4e-06 18200 10 1.2060433e-07 2.1e-06 -0.0012498983 + 4e-06 18300 10 1.172057e-07 2.1e-06 -0.0010950413 + 4e-06 18400 10 1.1397991e-07 2.1e-06 -0.00093963286 + 4e-06 18500 10 1.1092695e-07 2.1e-06 -0.00078375133 + 4e-06 18600 10 1.0804684e-07 2.1e-06 -0.00062747516 + 4e-06 18700 10 1.0533957e-07 2.1e-06 -0.00047088304 + 4e-06 18800 10 1.0280514e-07 2.1e-06 -0.00031405381 + 4e-06 18900 10 1.0044354e-07 2.1e-06 -0.00015706645 + 4e-06 19000 10 9.8254791e-08 2.1e-06 2.0903119e-17 +Loop time of 0.287179 on 1 procs for 14000 steps with 10 atoms + +99.8% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.049189 | 0.049189 | 0.049189 | 0.0 | 17.13 +Neigh | 0.0057064 | 0.0057064 | 0.0057064 | 0.0 | 1.99 +Comm | 0.00064863 | 0.00064863 | 0.00064863 | 0.0 | 0.23 +Output | 0.00089611 | 0.00089611 | 0.00089611 | 0.0 | 0.31 +Modify | 0.22899 | 0.22899 | 0.22899 | 0.0 | 79.74 +Other | | 0.001749 | | | 0.61 + +Nlocal: 10 ave 10 max 10 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 2 ave 2 max 2 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 2 +Ave neighs/atom = 0.2 +Neighbor list builds = 233 +Dangerous builds not checked + +##### EJECTION ##### + +variable punch_frequency equal PI/2/(dt*${ejection_steps}) +variable punch_frequency equal PI/2/(dt*14000) +variable disp_lower equal ${dieHeight}*sin(${punch_frequency}*elapsed*dt) +variable disp_lower equal 0.01*sin(${punch_frequency}*elapsed*dt) +variable disp_lower equal 0.01*sin(28.0499344070517*elapsed*dt) +variable disp_upper equal 0.9*v_disp_lower +run ${ejection_steps} +run 14000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 19000 10 9.8254791e-08 2.1e-06 0 + 4e-06 19100 10 9.6238878e-08 2.1e-06 0.00010097765 + 4e-06 19200 10 9.4395806e-08 2.1e-06 0.00020194258 + 4e-06 19300 10 9.2725573e-08 2.1e-06 0.00030288209 + 4e-06 19400 10 9.1228181e-08 2.1e-06 0.00040378347 + 4e-06 19500 10 8.9903628e-08 2.1e-06 0.00050463403 + 4e-06 19600 10 8.8751915e-08 2.1e-06 0.00060542105 + 4e-06 19700 10 6.9553679e-08 2.1e-06 0.00070613186 + 4e-06 19800 10 3.855161e-07 2.1e-06 0.00080675378 + 4e-06 19900 10 3.8006492e-07 2.1e-06 0.00090727414 + 4e-06 20000 10 3.7478659e-07 2.1e-06 0.0010076803 + 4e-06 20100 10 3.6968109e-07 2.1e-06 0.0011079596 + 4e-06 20200 10 3.6474843e-07 2.1e-06 0.0012080994 + 4e-06 20300 10 3.5998861e-07 2.1e-06 0.0013080871 + 4e-06 20400 10 3.5540163e-07 2.1e-06 0.0014079102 + 4e-06 20500 10 3.509875e-07 2.1e-06 0.001507556 + 4e-06 20600 10 3.467462e-07 2.1e-06 0.0016070121 + 4e-06 20700 10 3.4267774e-07 2.1e-06 0.0017062658 + 4e-06 20800 10 3.3878212e-07 2.1e-06 0.0018053047 + 4e-06 20900 10 6.2902098e-07 2.1e-06 0.0019041164 + 4e-06 21000 10 7.1567323e-07 2.1e-06 0.0020026884 + 4e-06 21100 10 7.0670404e-07 2.1e-06 0.0021010083 + 4e-06 21200 10 6.9790769e-07 2.1e-06 0.0021990637 + 4e-06 21300 10 6.8928417e-07 2.1e-06 0.0022968422 + 4e-06 21400 10 6.808335e-07 2.1e-06 0.0023943316 + 4e-06 21500 10 8.228831e-07 2.1e-06 0.0024915196 + 4e-06 21600 10 8.1258059e-07 2.1e-06 0.0025883939 + 4e-06 21700 10 8.0245093e-07 2.1e-06 0.0026849424 + 4e-06 21800 10 7.924941e-07 2.1e-06 0.0027811529 + 4e-06 21900 10 7.8271011e-07 2.1e-06 0.0028770133 + 4e-06 22000 10 7.7309896e-07 2.1e-06 0.0029725116 + 4e-06 22100 10 7.6366066e-07 2.1e-06 0.0030676356 + 4e-06 22200 10 7.5439519e-07 2.1e-06 0.0031623734 + 4e-06 22300 10 9.6736756e-07 2.1e-06 0.0032567132 + 4e-06 22400 10 9.5508751e-07 2.1e-06 0.0033506429 + 4e-06 22500 10 1.146027e-06 2.1e-06 0.0034441509 + 4e-06 22600 10 1.3340747e-06 2.1e-06 0.0035372253 + 4e-06 22700 10 1.3161012e-06 2.1e-06 0.0036298544 + 4e-06 22800 10 1.3780346e-06 2.1e-06 0.0037220265 + 4e-06 22900 10 1.4437449e-06 2.1e-06 0.0038137301 + 4e-06 23000 10 1.4237439e-06 2.1e-06 0.0039049537 + 4e-06 23100 10 1.4039157e-06 2.1e-06 0.0039956856 + 4e-06 23200 10 1.3842603e-06 2.1e-06 0.0040859145 + 4e-06 23300 10 1.3647778e-06 2.1e-06 0.0041756291 + 4e-06 23400 10 1.3454681e-06 2.1e-06 0.004264818 + 4e-06 23500 10 1.3263312e-06 2.1e-06 0.00435347 + 4e-06 23600 10 1.3073672e-06 2.1e-06 0.004441574 + 4e-06 23700 10 1.4224882e-06 2.1e-06 0.0045291188 + 4e-06 23800 10 1.4016962e-06 2.1e-06 0.0046160935 + 4e-06 23900 10 1.381077e-06 2.1e-06 0.0047024871 + 4e-06 24000 10 1.3606307e-06 2.1e-06 0.0047882887 + 4e-06 24100 10 1.3403572e-06 2.1e-06 0.0048734875 + 4e-06 24200 10 1.3202566e-06 2.1e-06 0.0049580728 + 4e-06 24300 10 1.3003288e-06 2.1e-06 0.005042034 + 4e-06 24400 10 1.2805739e-06 2.1e-06 0.0051253604 + 4e-06 24500 10 1.2609917e-06 2.1e-06 0.0052080417 + 4e-06 24600 10 1.2415825e-06 2.1e-06 0.0052900673 + 4e-06 24700 10 1.222346e-06 2.1e-06 0.0053714269 + 4e-06 24800 10 1.2032824e-06 2.1e-06 0.0054521104 + 4e-06 24900 10 1.1843917e-06 2.1e-06 0.0055321075 + 4e-06 25000 10 1.2550315e-06 2.1e-06 0.0056114082 + 4e-06 25100 10 1.2348763e-06 2.1e-06 0.0056900025 + 4e-06 25200 10 1.2148941e-06 2.1e-06 0.0057678805 + 4e-06 25300 10 1.1950846e-06 2.1e-06 0.0058450324 + 4e-06 25400 10 1.175448e-06 2.1e-06 0.0059214485 + 4e-06 25500 10 1.1559842e-06 2.1e-06 0.0059971192 + 4e-06 25600 10 1.1366933e-06 2.1e-06 0.0060720349 + 4e-06 25700 10 1.1175752e-06 2.1e-06 0.0061461862 + 4e-06 25800 10 1.0986299e-06 2.1e-06 0.0062195638 + 4e-06 25900 10 1.0798575e-06 2.1e-06 0.0062921585 + 4e-06 26000 10 1.061258e-06 2.1e-06 0.006363961 + 4e-06 26100 10 9.1373064e-07 2.1e-06 0.0064349624 + 4e-06 26200 10 8.9836765e-07 2.1e-06 0.0065051538 + 4e-06 26300 10 8.8317749e-07 2.1e-06 0.0065745262 + 4e-06 26400 10 8.6816018e-07 2.1e-06 0.006643071 + 4e-06 26500 10 7.2232503e-07 2.1e-06 0.0067107795 + 4e-06 26600 10 7.1072319e-07 2.1e-06 0.0067776432 + 4e-06 26700 10 6.9929419e-07 2.1e-06 0.0068436537 + 4e-06 26800 10 6.8803803e-07 2.1e-06 0.0069088027 + 4e-06 26900 10 6.7695471e-07 2.1e-06 0.0069730819 + 4e-06 27000 10 6.6604423e-07 2.1e-06 0.0070364833 + 4e-06 27100 10 6.5530659e-07 2.1e-06 0.007098999 + 4e-06 27200 10 6.4474179e-07 2.1e-06 0.0071606209 + 4e-06 27300 10 6.3434984e-07 2.1e-06 0.0072213415 + 4e-06 27400 10 6.2413072e-07 2.1e-06 0.0072811529 + 4e-06 27500 10 6.1408444e-07 2.1e-06 0.0073400478 + 4e-06 27600 10 6.04211e-07 2.1e-06 0.0073980187 + 4e-06 27700 10 5.945104e-07 2.1e-06 0.0074550582 + 4e-06 27800 10 5.8498264e-07 2.1e-06 0.0075111593 + 4e-06 27900 10 5.7562772e-07 2.1e-06 0.0075663148 + 4e-06 28000 10 5.6644564e-07 2.1e-06 0.0076205178 + 4e-06 28100 10 5.574364e-07 2.1e-06 0.0076737615 + 4e-06 28200 10 5.486e-07 2.1e-06 0.0077260391 + 4e-06 28300 10 5.3993644e-07 2.1e-06 0.0077773442 + 4e-06 28400 10 5.3144572e-07 2.1e-06 0.0078276702 + 4e-06 28500 10 5.1027539e-07 2.1e-06 0.0078770108 + 4e-06 28600 10 3.5840723e-07 2.1e-06 0.0079253598 + 4e-06 28700 10 3.7060273e-07 2.1e-06 0.0079727111 + 4e-06 28800 10 3.6745652e-07 2.1e-06 0.0080190587 + 4e-06 28900 10 3.6448315e-07 2.1e-06 0.0080643969 + 4e-06 29000 10 3.0843931e-07 2.1e-06 0.0081087198 + 4e-06 29100 10 3.0772799e-07 2.1e-06 0.008152022 + 4e-06 29200 10 3.0718951e-07 2.1e-06 0.0081942979 + 4e-06 29300 10 3.0682387e-07 2.1e-06 0.0082355423 + 4e-06 29400 10 3.0663107e-07 2.1e-06 0.00827575 + 4e-06 29500 10 3.0661111e-07 2.1e-06 0.0083149158 + 4e-06 29600 10 3.0676399e-07 2.1e-06 0.0083530349 + 4e-06 29700 10 3.0708971e-07 2.1e-06 0.0083901025 + 4e-06 29800 10 3.0758827e-07 2.1e-06 0.0084261138 + 4e-06 29900 10 3.0825967e-07 2.1e-06 0.0084610645 + 4e-06 30000 10 3.0910391e-07 2.1e-06 0.00849495 + 4e-06 30100 10 2.7633224e-07 2.1e-06 0.0085277661 + 4e-06 30200 10 2.7917696e-07 2.1e-06 0.0085595086 + 4e-06 30300 10 2.8219452e-07 2.1e-06 0.0085901737 + 4e-06 30400 10 2.8538492e-07 2.1e-06 0.0086197574 + 4e-06 30500 10 2.8874816e-07 2.1e-06 0.0086482559 + 4e-06 30600 10 2.9228424e-07 2.1e-06 0.0086756657 + 4e-06 30700 10 2.9599316e-07 2.1e-06 0.0087019834 + 4e-06 30800 10 2.9987493e-07 2.1e-06 0.0087272057 + 4e-06 30900 10 3.0392953e-07 2.1e-06 0.0087513293 + 4e-06 31000 10 3.0815697e-07 2.1e-06 0.0087743512 + 4e-06 31100 10 3.1255725e-07 2.1e-06 0.0087962686 + 4e-06 31200 10 3.1713037e-07 2.1e-06 0.0088170786 + 4e-06 31300 10 3.2187633e-07 2.1e-06 0.0088367787 + 4e-06 31400 10 3.2679513e-07 2.1e-06 0.0088553663 + 4e-06 31500 10 3.3188677e-07 2.1e-06 0.0088728392 + 4e-06 31600 10 3.3522008e-07 2.1e-06 0.0088891951 + 4e-06 31700 10 3.3129412e-07 2.1e-06 0.0089044319 + 4e-06 31800 10 3.3814673e-07 2.1e-06 0.0089185479 + 4e-06 31900 10 3.7840167e-07 2.1e-06 0.0089315411 + 4e-06 32000 10 3.8178891e-07 2.1e-06 0.0089434099 + 4e-06 32100 10 3.8534899e-07 2.1e-06 0.0089541529 + 4e-06 32200 10 3.8908191e-07 2.1e-06 0.0089637686 + 4e-06 32300 10 4.1410686e-07 2.1e-06 0.008972256 + 4e-06 32400 10 4.1433199e-07 2.1e-06 0.0089796139 + 4e-06 32500 10 4.1472995e-07 2.1e-06 0.0089858413 + 4e-06 32600 10 4.1530076e-07 2.1e-06 0.0089909376 + 4e-06 32700 10 4.1604441e-07 2.1e-06 0.008994902 + 4e-06 32800 10 4.169609e-07 2.1e-06 0.0089977341 + 4e-06 32900 10 4.1805022e-07 2.1e-06 0.0089994335 + 4e-06 33000 10 4.1931239e-07 2.1e-06 0.009 +Loop time of 0.177773 on 1 procs for 14000 steps with 10 atoms + +99.8% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.0020062 | 0.0020062 | 0.0020062 | 0.0 | 1.13 +Neigh | 0.00084671 | 0.00084671 | 0.00084671 | 0.0 | 0.48 +Comm | 0.00056289 | 0.00056289 | 0.00056289 | 0.0 | 0.32 +Output | 0.0010356 | 0.0010356 | 0.0010356 | 0.0 | 0.58 +Modify | 0.17178 | 0.17178 | 0.17178 | 0.0 | 96.63 +Other | | 0.001546 | | | 0.87 + +Nlocal: 10 ave 10 max 10 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 3 ave 3 max 3 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 3 +Ave neighs/atom = 0.3 +Neighbor list builds = 233 +Dangerous builds not checked + +##### FREE FLOAT ##### + +variable disp_lower equal ${dieHeight} +variable disp_lower equal 0.01 +variable disp_upper equal ${dieHeight}*0.9 +variable disp_upper equal 0.01*0.9 +variable max_disp equal ${dieRadius}*0.75 +variable max_disp equal 0.004*0.75 +run ${free_float_steps} +run 5000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes + Dt Step Atoms KinEng Volume v_disp_upper + 4e-06 33000 10 4.1931239e-07 2.1e-06 0.009 + 4e-06 33100 10 4.207474e-07 2.1e-06 0.009 + 4e-06 33200 10 4.2235525e-07 2.1e-06 0.009 + 4e-06 33300 10 4.2413593e-07 2.1e-06 0.009 + 4e-06 33400 10 4.2608946e-07 2.1e-06 0.009 + 4e-06 33500 10 4.2821583e-07 2.1e-06 0.009 + 4e-06 33600 10 4.3051504e-07 2.1e-06 0.009 + 4e-06 33700 10 4.3298709e-07 2.1e-06 0.009 + 4e-06 33800 10 4.3563197e-07 2.1e-06 0.009 + 4e-06 33900 10 4.384497e-07 2.1e-06 0.009 + 4e-06 34000 10 4.4144027e-07 2.1e-06 0.009 + 4e-06 34100 10 4.4460367e-07 2.1e-06 0.009 + 4e-06 34200 10 4.4793992e-07 2.1e-06 0.009 + 4e-06 34300 10 4.5144901e-07 2.1e-06 0.009 + 4e-06 34400 10 4.5465956e-07 2.1e-06 0.009 + 4e-06 34500 10 4.5470653e-07 2.1e-06 0.009 + 4e-06 34600 10 4.5236426e-07 2.1e-06 0.009 + 4e-06 34700 10 4.5019483e-07 2.1e-06 0.009 + 4e-06 34800 10 4.4819824e-07 2.1e-06 0.009 + 4e-06 34900 10 4.4590448e-07 2.1e-06 0.009 + 4e-06 35000 10 4.4154693e-07 2.1e-06 0.009 + 4e-06 35100 10 4.3736222e-07 2.1e-06 0.009 + 4e-06 35200 10 4.3335035e-07 2.1e-06 0.009 + 4e-06 35300 10 4.2951132e-07 2.1e-06 0.009 + 4e-06 35400 10 4.2584514e-07 2.1e-06 0.009 + 4e-06 35500 10 4.2235179e-07 2.1e-06 0.009 + 4e-06 35600 10 4.1903128e-07 2.1e-06 0.009 + 4e-06 35700 10 4.1034829e-07 2.1e-06 0.009 + 4e-06 35800 10 4.1153836e-07 2.1e-06 0.009 + 4e-06 35900 10 4.0720986e-07 2.1e-06 0.009 + 4e-06 36000 10 4.0259092e-07 2.1e-06 0.009 + 4e-06 36100 10 3.9607992e-07 2.1e-06 0.009 + 4e-06 36200 10 3.8974177e-07 2.1e-06 0.009 + 4e-06 36300 10 3.8357646e-07 2.1e-06 0.009 + 4e-06 36400 10 3.7758398e-07 2.1e-06 0.009 + 4e-06 36500 10 3.7176435e-07 2.1e-06 0.009 + 4e-06 36600 10 3.6611755e-07 2.1e-06 0.009 + 4e-06 36700 10 3.606436e-07 2.1e-06 0.009 + 4e-06 36800 10 3.5534248e-07 2.1e-06 0.009 + 4e-06 36900 10 3.5021421e-07 2.1e-06 0.009 + 4e-06 37000 10 3.4525877e-07 2.1e-06 0.009 + 4e-06 37100 10 3.4047618e-07 2.1e-06 0.009 + 4e-06 37200 10 3.3586643e-07 2.1e-06 0.009 + 4e-06 37300 10 3.3142951e-07 2.1e-06 0.009 + 4e-06 37400 10 3.0307307e-07 2.1e-06 0.009 + 4e-06 37500 10 3.208203e-07 2.1e-06 0.009 + 4e-06 37600 10 3.1480548e-07 2.1e-06 0.009 + 4e-06 37700 10 3.0896349e-07 2.1e-06 0.009 + 4e-06 37800 10 3.0329434e-07 2.1e-06 0.009 + 4e-06 37900 10 2.9779804e-07 2.1e-06 0.009 + 4e-06 38000 10 2.9247457e-07 2.1e-06 0.009 +Loop time of 0.0201013 on 1 procs for 5000 steps with 10 atoms + +99.8% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.00055406 | 0.00055406 | 0.00055406 | 0.0 | 2.76 +Neigh | 0.00029074 | 0.00029074 | 0.00029074 | 0.0 | 1.45 +Comm | 0.00017063 | 0.00017063 | 0.00017063 | 0.0 | 0.85 +Output | 0.00023192 | 0.00023192 | 0.00023192 | 0.0 | 1.15 +Modify | 0.018306 | 0.018306 | 0.018306 | 0.0 | 91.07 +Other | | 0.000548 | | | 2.73 + +Nlocal: 10 ave 10 max 10 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 2 ave 2 max 2 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 2 +Ave neighs/atom = 0.2 +Neighbor list builds = 83 +Dangerous builds not checked +Total wall time: 0:00:00 diff --git a/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 new file mode 100644 index 0000000000..8b9562d59f --- /dev/null +++ b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 @@ -0,0 +1,779 @@ +LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-581-g384d7f446b-modified) +############################### SIMULATION SETTINGS ################################################### + +atom_style sphere 1 +atom_modify map array +comm_modify vel yes +units si +newton off +neighbor 2 bin +neigh_modify delay 0 +timestep 1e-6 + +##################### SIMULATION BOUNDING BOX, INSERT PARTICLES, AND INTEGRATION ####################### + +boundary f f f +read_data spheres12.data +Reading data file ... + orthogonal box = (-10 -10 -10) to (10 10 10) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 12 atoms + read_data CPU = 0.002 seconds +fix integr all nve/sphere + +# create pair group for contact area outputs +group particles_1_12 id 1 12 +2 atoms in group particles_1_12 + +########################### PARTICLE MATERIAL PROPERTIES AND FORCE MODEL ############################### + +variable atomRadius equal 0.5 + +pair_style granular + +# mdr = E, nu, Y, gamma, psi_b, damp +variable YoungsModulus equal 1e9 +variable PoissonsRatio equal 0.3 +variable YieldStress equal 50e6 +variable SurfaceEnergy equal 0.0 +variable psi_b equal 0.5 +variable damp equal 1.0 + +# linear_history = k_t, x_gamma,t, mu_s +variable kt equal 2/7*${YoungsModulus}*${atomRadius} +variable kt equal 2/7*1000000000*${atomRadius} +variable kt equal 2/7*1000000000*0.5 +variable xgammat equal 0.0 +variable mu_s equal 0.5 + +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 + +######################################### ADD IN PLANES ################################################ + +variable boxWidth equal 3 +variable halfBoxWidth equal ${boxWidth}/2 +variable halfBoxWidth equal 3/2 + +variable plane_disp equal 0.0 +variable plane_disp_neg equal 0.0 + +region plane_yz_pos plane ${halfBoxWidth} 0 0 -1 0 0 side in move v_plane_disp_neg NULL NULL units box +region plane_yz_pos plane 1.5 0 0 -1 0 0 side in move v_plane_disp_neg NULL NULL units box +region plane_yz_neg plane -${halfBoxWidth} 0 0 1 0 0 side in move v_plane_disp NULL NULL units box +region plane_yz_neg plane -1.5 0 0 1 0 0 side in move v_plane_disp NULL NULL units box +region plane_xz_pos plane 0 ${halfBoxWidth} 0 0 -1 0 side in move NULL v_plane_disp_neg NULL units box +region plane_xz_pos plane 0 1.5 0 0 -1 0 side in move NULL v_plane_disp_neg NULL units box +region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_disp NULL units box +region plane_xz_neg plane 0 -1.5 0 0 1 0 side in move NULL v_plane_disp NULL units box +region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box +region plane_xy_pos plane 0 0 1.5 0 0 -1 side in move NULL NULL v_plane_disp_neg units box +region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box +region plane_xy_neg plane 0 0 -1.5 0 0 1 side in move NULL NULL v_plane_disp units box + +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} " +granular mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 + +fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts +fix plane_yz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_yz_pos contacts +fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts +fix plane_yz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_yz_neg contacts +fix plane_xz_pos all wall/gran/region ${wall_contact_string} region plane_xz_pos contacts +fix plane_xz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xz_pos contacts +fix plane_xz_neg all wall/gran/region ${wall_contact_string} region plane_xz_neg contacts +fix plane_xz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xz_neg contacts +fix plane_xy_pos all wall/gran/region ${wall_contact_string} region plane_xy_pos contacts +fix plane_xy_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xy_pos contacts +fix plane_xy_neg all wall/gran/region ${wall_contact_string} region plane_xy_neg contacts +fix plane_xy_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xy_neg contacts + +compute plane_xy_neg_force all reduce sum f_plane_xy_neg[4] +variable plane_xy_neg_force equal c_plane_xy_neg_force + +compute plane_xz_neg_force all reduce sum f_plane_xz_neg[3] +variable plane_xz_neg_force equal c_plane_xz_neg_force + +compute plane_yz_neg_force all reduce sum f_plane_yz_neg[2] +variable plane_yz_neg_force equal c_plane_yz_neg_force + +#fix print1 all print 1 "${plane_disp} ${plane_xy_neg_force} ${plane_xz_neg_force} ${plane_yz_neg_force}" file force_disp_triaxial12.csv screen no + +######################################## SCREEN OUTPUT #################################################### + +compute 1 all erotate/sphere +thermo_style custom dt step atoms ke c_1 vol +thermo 100 +thermo_modify lost ignore norm no + +##################################### DEFINE WALL MOVEMENT ################################################# + +variable disp_max equal 0.499 +variable ddisp equal 0.00001 +variable compression_steps equal round(${disp_max}/${ddisp}) +variable compression_steps equal round(0.499/${ddisp}) +variable compression_steps equal round(0.499/1e-05) +variable output_rate equal round(${compression_steps}/100) +variable output_rate equal round(49900/100) + +##################################### SET UP DUMP OUTPUTS #################################################### + +#dump dumpParticles all custom ${output_rate} triaxial_compaction_12.dump id type mass x y z vx vy vz fx fy fz radius +#dump dmp all vtk ${output_rate} post/triaxial12particles_*.vtk id type mass x y z vx vy vz fx fy fz radius + +#################################### COMPRESS THE PARTICLES ################################################## + +run 0 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- MDR contact model command: (i) https://doi.org/10.1016/j.jmps.2023.105492 || (ii) https://doi.org/10.1016/j.jmps.2023.105493 || (iii) https://doi.org/10.31224/4289 + +@Article{zunker2024mechanicallyI, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part I: Utilizing the method of dimensionality reduction}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105492}, +} + +@Article{zunker2024mechanicallyII, + author = {Zunker, William and Kamrin, Ken}, + title = {A mechanically-derived contact model for adhesive elastic-perfectly plastic particles, + Part II: Contact under high compaction—modeling a bulk elastic response}, + journal = {Journal of the Mechanics and Physics of Solids}, + year = {2024}, + volume = {183}, + pages = {105493}, +} + +@Article{zunker2025experimentally, + author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken}, + title = {Experimentally validated DEM for large deformation powder compaction: + mechanically-derived contact model and screening of non-physical contacts}, + year = {2025}, + journal = {engrXiv}, +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.2 + ghost atom cutoff = 3.2 + binsize = 1.6, bins = 13 13 13 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair granular, perpetual + attributes: half, newton off, size, history + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 74.54 | 74.54 | 74.54 Mbytes + Dt Step Atoms KinEng c_1 Volume + 1e-06 0 12 0 0 8000 +Loop time of 1.135e-06 on 1 procs for 0 steps with 12 atoms + +88.1% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0 | 0 | 0 | 0.0 | 0.00 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0 | 0 | 0 | 0.0 | 0.00 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 1.135e-06 | | |100.00 + +Nlocal: 12 ave 12 max 12 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 66 ave 66 max 66 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 66 +Ave neighs/atom = 5.5 +Neighbor list builds = 0 +Dangerous builds = 0 + +# print out contact area evolution for particles 1 and 12 +compute Ac_1_12 particles_1_12 pair/local p13 cutoff radius +compute Ac_1_12_sum particles_1_12 reduce sum c_Ac_1_12 inputs local +variable Ac_1_12 equal c_Ac_1_12_sum +#fix logArea all print 100 "${plane_disp} ${Ac_1_12}" file pair_1_12_contact_area_triaxial12.csv screen no + +variable plane_disp equal ${ddisp}*elapsed +variable plane_disp equal 1e-05*elapsed +variable plane_disp_neg equal -${ddisp}*elapsed +variable plane_disp_neg equal -1e-05*elapsed + +run ${compression_steps} +run 49900 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 3.2 + ghost atom cutoff = 3.2 + binsize = 1.6, bins = 13 13 13 + 2 neighbor lists, perpetual/occasional/extra = 1 1 0 + (1) pair granular, perpetual + attributes: half, newton off, size, history + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard + (2) compute pair/local, occasional + attributes: half, newton off, size + pair build: half/size/bin/atomonly/newtoff + stencil: full/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 75.17 | 75.17 | 75.17 Mbytes + Dt Step Atoms KinEng c_1 Volume + 1e-06 0 12 0 0 8000 + 1e-06 100 12 0.00013054111 0 8000 + 1e-06 200 12 0.013855547 0 8000 + 1e-06 300 12 0.14822185 0 8000 + 1e-06 400 12 0.73507149 0 8000 + 1e-06 500 12 2.4874475 0 8000 + 1e-06 600 12 6.7258963 0 8000 + 1e-06 700 12 15.636026 0 8000 + 1e-06 800 12 32.517811 0 8000 + 1e-06 900 12 62.020123 0 8000 + 1e-06 1000 12 110.35576 0 8000 + 1e-06 1100 12 185.492 0 8000 + 1e-06 1200 12 297.31164 0 8000 + 1e-06 1300 12 457.73953 0 8000 + 1e-06 1400 12 680.82988 0 8000 + 1e-06 1500 12 982.80999 0 8000 + 1e-06 1600 12 1382.0767 0 8000 + 1e-06 1700 12 1899.1422 0 8000 + 1e-06 1800 12 2556.5278 0 8000 + 1e-06 1900 12 3378.6026 0 8000 + 1e-06 2000 12 4391.3694 0 8000 + 1e-06 2100 12 5622.1967 0 8000 + 1e-06 2200 12 7099.4998 0 8000 + 1e-06 2300 12 8852.3743 0 8000 + 1e-06 2400 10 6989.9205 0 8000 + 1e-06 2500 10 8429.3452 0 8000 + 1e-06 2600 10 10069.898 0 8000 + 1e-06 2700 10 11924.3 0 8000 + 1e-06 2800 10 14004.078 0 8000 + 1e-06 2900 10 16319.307 0 8000 + 1e-06 3000 10 18878.365 0 8000 + 1e-06 3100 10 21687.702 0 8000 + 1e-06 3200 10 24751.634 0 8000 + 1e-06 3300 10 28072.177 0 8000 + 1e-06 3400 10 31649.069 0 8000 + 1e-06 3500 10 35479.937 0 8000 + 1e-06 3600 10 39560.508 0 8000 + 1e-06 3700 10 43884.837 0 8000 + 1e-06 3800 10 48445.544 0 8000 + 1e-06 3900 10 53234.048 0 8000 + 1e-06 4000 10 58240.786 0 8000 + 1e-06 4100 10 63455.398 0 8000 + 1e-06 4200 10 68866.878 0 8000 + 1e-06 4300 10 74463.666 0 8000 + 1e-06 4400 10 80233.692 0 8000 + 1e-06 4500 10 86164.354 0 8000 + 1e-06 4600 10 92242.435 0 8000 + 1e-06 4700 10 98453.963 0 8000 + 1e-06 4800 10 104784.03 0 8000 + 1e-06 4900 10 111216.58 0 8000 + 1e-06 5000 10 117734.15 0 8000 + 1e-06 5100 10 124317.68 0 8000 + 1e-06 5200 10 130946.27 0 8000 + 1e-06 5300 10 137597 0 8000 + 1e-06 5400 10 144244.91 0 8000 + 1e-06 5500 10 150862.88 0 8000 + 1e-06 5600 10 157421.78 0 8000 + 1e-06 5700 10 163890.67 0 8000 + 1e-06 5800 10 170237.02 0 8000 + 1e-06 5900 10 176427.24 0 8000 + 1e-06 6000 10 182427.1 0 8000 + 1e-06 6100 10 188202.4 0 8000 + 1e-06 6200 10 193719.65 0 8000 + 1e-06 6300 10 198946.82 0 8000 + 1e-06 6400 10 203854.11 0 8000 + 1e-06 6500 10 208414.76 0 8000 + 1e-06 6600 10 212605.82 0 8000 + 1e-06 6700 10 216408.93 0 8000 + 1e-06 6800 10 219811.02 0 8000 + 1e-06 6900 10 222804.99 0 8000 + 1e-06 7000 10 225390.45 0 8000 + 1e-06 7100 10 227574.39 0 8000 + 1e-06 7200 10 229372.23 0 8000 + 1e-06 7300 10 230809.43 0 8000 + 1e-06 7400 10 231925.78 0 8000 + 1e-06 7500 10 232793.77 0 8000 + 1e-06 7600 10 233468.99 0 8000 + 1e-06 7700 10 233964.52 1.1292815e-08 8000 + 1e-06 7800 10 234297.53 3.2638536e-06 8000 + 1e-06 7900 10 234490.97 4.5245711e-05 8000 + 1e-06 8000 10 234575.58 0.00027361033 8000 + 1e-06 8100 10 234598.71 0.001096929 8000 + 1e-06 8200 10 234623.44 0.0034192164 8000 + 1e-06 8300 10 234664.37 0.0089703149 8000 + 1e-06 8400 10 234728.48 0.020734818 8000 + 1e-06 8500 10 234824.44 0.043473962 8000 + 1e-06 8600 10 234962.62 0.084326224 8000 + 1e-06 8700 10 235155.17 0.15346362 8000 + 1e-06 8800 10 235415.94 0.26477255 8000 + 1e-06 8900 10 235760.43 0.43652067 8000 + 1e-06 9000 10 236205.62 0.69196571 8000 + 1e-06 9100 10 236769.75 1.0598579 8000 + 1e-06 9200 10 237472.3 1.5747862 8000 + 1e-06 9300 10 238334.06 2.2773199 8000 + 1e-06 9400 10 239377.46 3.2138993 8000 + 1e-06 9500 10 240626.63 4.4364369 8000 + 1e-06 9600 10 242107.53 6.0015993 8000 + 1e-06 9700 10 243847.86 7.9697503 8000 + 1e-06 9800 10 245876.93 10.403551 8000 + 1e-06 9900 10 248225.31 13.366224 8000 + 1e-06 10000 10 250924.44 16.919517 8000 + 1e-06 10100 8 234934.58 0 8000 + 1e-06 10200 8 235124.58 0 8000 + 1e-06 10300 8 235382.91 0 8000 + 1e-06 10400 8 235723.84 0 8000 + 1e-06 10500 8 236162.16 0 8000 + 1e-06 10600 8 236712.7 0 8000 + 1e-06 10700 8 237389.77 0 8000 + 1e-06 10800 8 238206.63 0 8000 + 1e-06 10900 8 239174.87 0 8000 + 1e-06 11000 8 240303.83 0 8000 + 1e-06 11100 8 241600.1 0 8000 + 1e-06 11200 8 243067 0 8000 + 1e-06 11300 8 244704.22 0 8000 + 1e-06 11400 8 246507.57 0 8000 + 1e-06 11500 8 248468.78 0 8000 + 1e-06 11600 8 250575.55 0 8000 + 1e-06 11700 8 252811.67 0 8000 + 1e-06 11800 6 201540.76 0 8000 + 1e-06 11900 6 203972.8 0 8000 + 1e-06 12000 6 206465.55 0 8000 + 1e-06 12100 6 208991.23 0 8000 + 1e-06 12200 6 211520.76 0 8000 + 1e-06 12300 6 214024.53 0 8000 + 1e-06 12400 6 216473.14 0 8000 + 1e-06 12500 6 218838.23 0 8000 + 1e-06 12600 6 221093.18 0 8000 + 1e-06 12700 6 223213.84 0 8000 + 1e-06 12800 6 225179.08 0 8000 + 1e-06 12900 6 226971.32 0 8000 + 1e-06 13000 6 228576.94 0 8000 + 1e-06 13100 6 229986.52 0 8000 + 1e-06 13200 6 231195.09 0 8000 + 1e-06 13300 6 232202.15 0 8000 + 1e-06 13400 6 233011.77 0 8000 + 1e-06 13500 6 233632.53 0 8000 + 1e-06 13600 6 234077.63 0 8000 + 1e-06 13700 6 234365.12 0 8000 + 1e-06 13800 6 234518.64 0 8000 + 1e-06 13900 6 234569.99 0 8000 + 1e-06 14000 6 234572.25 0 8000 + 1e-06 14100 6 234572.25 0 8000 + 1e-06 14200 6 234572.25 0 8000 + 1e-06 14300 6 234572.25 0 8000 + 1e-06 14400 6 234572.25 0 8000 + 1e-06 14500 6 234572.25 0 8000 + 1e-06 14600 6 234572.25 0 8000 + 1e-06 14700 6 234572.25 0 8000 + 1e-06 14800 6 234572.29 0 8000 + 1e-06 14900 6 234572.53 0 8000 + 1e-06 15000 6 234573.43 0 8000 + 1e-06 15100 6 234575.83 0 8000 + 1e-06 15200 6 234581.15 0 8000 + 1e-06 15300 6 234591.61 0 8000 + 1e-06 15400 6 234610.69 0 8000 + 1e-06 15500 6 234643.46 0 8000 + 1e-06 15600 6 234697 0 8000 + 1e-06 15700 6 234780.66 0 8000 + 1e-06 15800 6 234906.33 0 8000 + 1e-06 15900 6 235088.62 0 8000 + 1e-06 16000 6 235344.92 0 8000 + 1e-06 16100 6 235695.54 0 8000 + 1e-06 16200 6 236163.79 0 8000 + 1e-06 16300 6 236775.81 0 8000 + 1e-06 16400 6 237560.44 0 8000 + 1e-06 16500 6 238548.84 0 8000 + 1e-06 16600 6 239774.02 0 8000 + 1e-06 16700 6 241270.31 0 8000 + 1e-06 16800 6 243072.61 0 8000 + 1e-06 16900 6 245211.28 6.7509561e-05 8000 + 1e-06 17000 6 247685.18 0.0080448801 8000 + 1e-06 17100 6 250497.91 0.088500606 8000 + 1e-06 17200 6 253660.58 0.44413361 8000 + 1e-06 17300 6 257184.97 1.4994335 8000 + 1e-06 17400 6 261081.58 3.9820483 8000 + 1e-06 17500 6 265358.51 9.0005574 8000 + 1e-06 17600 6 270020.73 18.117195 8000 + 1e-06 17700 6 275069.6 33.413964 8000 + 1e-06 17800 6 280502.61 57.550525 8000 + 1e-06 17900 6 286303.62 93.814333 8000 + 1e-06 18000 6 292426.19 146.2099 8000 + 1e-06 18100 6 298823.02 219.66922 8000 + 1e-06 18200 6 305448.57 320.29091 8000 + 1e-06 18300 6 312257.06 455.50977 8000 + 1e-06 18400 6 319203.29 634.16436 8000 + 1e-06 18500 6 326243.62 866.44452 8000 + 1e-06 18600 6 333337.05 1163.7119 8000 + 1e-06 18700 6 340446.07 1538.1992 8000 + 1e-06 18800 6 347537.26 2002.6065 8000 + 1e-06 18900 6 354581.63 2569.6256 8000 + 1e-06 19000 6 361554.66 3251.4317 8000 + 1e-06 19100 6 368436.16 4059.1895 8000 + 1e-06 19200 6 375209.78 5002.6224 8000 + 1e-06 19300 6 381882.2 6109.6539 8000 + 1e-06 19400 6 388474.8 7416.2947 8000 + 1e-06 19500 6 395001.33 8944.9067 8000 + 1e-06 19600 6 401479.91 10717.67 8000 + 1e-06 19700 6 407931.4 12755.438 8000 + 1e-06 19800 6 414377.59 15076.566 8000 + 1e-06 19900 6 420839.43 17695.777 8000 + 1e-06 20000 6 427335.35 20623.111 8000 + 1e-06 20100 6 433879.62 23863.014 8000 + 1e-06 20200 6 440481.15 27413.577 8000 + 1e-06 20300 6 447142.48 31265.951 8000 + 1e-06 20400 6 453859.41 35403.784 8000 + 1e-06 20500 6 460622.17 39801.729 8000 + 1e-06 20600 6 467431.36 44452.106 8000 + 1e-06 20700 6 474330.29 49397.748 8000 + 1e-06 20800 6 481309.26 54624.638 8000 + 1e-06 20900 6 488358.84 60103.827 8000 + 1e-06 21000 6 495475.98 65790.173 8000 + 1e-06 21100 6 502655.34 71632.552 8000 + 1e-06 21200 6 509889.38 77576.424 8000 + 1e-06 21300 6 517172.66 83561.469 8000 + 1e-06 21400 6 524502.62 89522.951 8000 + 1e-06 21500 6 531876.86 95398.198 8000 + 1e-06 21600 6 539294.19 101129.04 8000 + 1e-06 21700 6 546755.8 106663.72 8000 + 1e-06 21800 6 554266.99 111958.45 8000 + 1e-06 21900 6 561839.98 116978.4 8000 + 1e-06 22000 6 569504.77 121698.15 8000 + 1e-06 22100 6 577194.68 126299.67 8000 + 1e-06 22200 6 584793.35 130939.81 8000 + 1e-06 22300 6 592287.59 135570.38 8000 + 1e-06 22400 6 599668.12 140143.02 8000 + 1e-06 22500 6 606930.15 144609.51 8000 + 1e-06 22600 6 614053.56 148921.72 8000 + 1e-06 22700 6 621008.46 153030.89 8000 + 1e-06 22800 6 627801.12 156883.57 8000 + 1e-06 22900 6 634468.16 160420.58 8000 + 1e-06 23000 6 640978.09 163613.12 8000 + 1e-06 23100 6 647287.63 166442.2 8000 + 1e-06 23200 6 653357.63 168893.16 8000 + 1e-06 23300 6 659133.28 170996.37 8000 + 1e-06 23400 6 664395.28 173122 8000 + 1e-06 23500 6 669082.71 175330.06 8000 + 1e-06 23600 6 673190.8 177582.02 8000 + 1e-06 23700 6 676722.56 179839.98 8000 + 1e-06 23800 6 679689.62 182067.03 8000 + 1e-06 23900 6 682113 184227.49 8000 + 1e-06 24000 6 684024.19 186286.94 8000 + 1e-06 24100 6 685466.31 188212.09 8000 + 1e-06 24200 6 686496.31 189970.05 8000 + 1e-06 24300 6 687194.14 191524.49 8000 + 1e-06 24400 6 687664.3 192834.65 8000 + 1e-06 24500 6 687952.12 193892.14 8000 + 1e-06 24600 6 688095.09 194698.81 8000 + 1e-06 24700 6 688136.6 195260.51 8000 + 1e-06 24800 6 688125.44 195586.96 8000 + 1e-06 24900 6 688096.3 195728.68 8000 + 1e-06 25000 6 687921.9 196064.13 8000 + 1e-06 25100 6 687620.45 196683.53 8000 + 1e-06 25200 6 687262.22 197578.87 8000 + 1e-06 25300 6 686921.27 198739.39 8000 + 1e-06 25400 6 686676.56 200150.16 8000 + 1e-06 25500 6 686616.59 201789.73 8000 + 1e-06 25600 6 686864.53 203620.41 8000 + 1e-06 25700 6 687515.07 205612.65 8000 + 1e-06 25800 6 688581.75 207765.95 8000 + 1e-06 25900 6 690068.86 210079.27 8000 + 1e-06 26000 6 691973.66 212549.89 8000 + 1e-06 26100 6 694286.34 215173.38 8000 + 1e-06 26200 6 696990.21 217943.63 8000 + 1e-06 26300 6 700062.02 220852.8 8000 + 1e-06 26400 6 703472.51 223891.43 8000 + 1e-06 26500 6 707187.07 227048.44 8000 + 1e-06 26600 6 711166.57 230311.27 8000 + 1e-06 26700 6 715368.28 233666 8000 + 1e-06 26800 6 719746.83 237097.44 8000 + 1e-06 26900 4 611074.01 219866.64 8000 + 1e-06 27000 4 613405.75 223401.9 8000 + 1e-06 27100 4 615906.25 226962.69 8000 + 1e-06 27200 4 618550.98 230530.7 8000 + 1e-06 27300 4 621314.15 234087.34 8000 + 1e-06 27400 4 624169.04 237613.98 8000 + 1e-06 27500 4 627088.41 241092.16 8000 + 1e-06 27600 4 630045.27 244503.29 8000 + 1e-06 27700 4 633017.68 247822.39 8000 + 1e-06 27800 4 635987.37 251019.87 8000 + 1e-06 27900 4 638936.67 254066.27 8000 + 1e-06 28000 4 641848.81 256932.77 8000 + 1e-06 28100 4 644708.19 259591.65 8000 + 1e-06 28200 4 647500.76 262016.69 8000 + 1e-06 28300 4 650214.19 264183.55 8000 + 1e-06 28400 4 652838.21 266070.17 8000 + 1e-06 28500 4 655364.7 267657.12 8000 + 1e-06 28600 4 657787.94 268927.87 8000 + 1e-06 28700 4 660104.66 269869.08 8000 + 1e-06 28800 4 662314.19 270470.82 8000 + 1e-06 28900 4 664418.47 270726.71 8000 + 1e-06 29000 4 666422.08 270634.03 8000 + 1e-06 29100 4 668332.27 270193.77 8000 + 1e-06 29200 4 670133.21 269455.46 8000 + 1e-06 29300 4 671623.88 268795.91 8000 + 1e-06 29400 4 672777.96 268288.08 8000 + 1e-06 29500 4 673622.53 267917.97 8000 + 1e-06 29600 4 674189.83 267670.08 8000 + 1e-06 29700 4 674518.57 267526.71 8000 + 1e-06 29800 4 674657.04 267466.37 8000 + 1e-06 29900 4 674676.17 267458.04 8000 + 1e-06 30000 4 674676.17 267458.04 8000 + 1e-06 30100 4 674676.17 267458.04 8000 + 1e-06 30200 2 304425.26 84084.197 8000 + 1e-06 30300 2 304425.26 84084.197 8000 + 1e-06 30400 2 304425.26 84084.197 8000 + 1e-06 30500 2 304425.26 84084.197 8000 + 1e-06 30600 2 304425.26 84084.197 8000 + 1e-06 30700 2 304425.26 84084.197 8000 + 1e-06 30800 2 304425.26 84084.197 8000 + 1e-06 30900 2 304425.26 84084.197 8000 + 1e-06 31000 2 304425.26 84084.197 8000 + 1e-06 31100 2 304425.26 84084.197 8000 + 1e-06 31200 2 304425.26 84084.197 8000 + 1e-06 31300 2 304425.26 84084.197 8000 + 1e-06 31400 2 304425.26 84084.197 8000 + 1e-06 31500 2 304425.26 84084.197 8000 + 1e-06 31600 2 304425.26 84084.197 8000 + 1e-06 31700 2 304425.26 84084.197 8000 + 1e-06 31800 2 304425.26 84084.197 8000 + 1e-06 31900 2 304425.26 84084.197 8000 + 1e-06 32000 2 304425.26 84084.197 8000 + 1e-06 32100 2 304425.26 84084.197 8000 + 1e-06 32200 2 304425.26 84084.197 8000 + 1e-06 32300 2 304425.26 84084.197 8000 + 1e-06 32400 2 304425.26 84084.197 8000 + 1e-06 32500 2 304425.26 84084.197 8000 + 1e-06 32600 2 304425.26 84084.197 8000 + 1e-06 32700 2 304425.26 84084.197 8000 + 1e-06 32800 2 304425.26 84084.197 8000 + 1e-06 32900 2 304425.26 84084.197 8000 + 1e-06 33000 2 304425.26 84084.197 8000 + 1e-06 33100 2 304425.26 84084.197 8000 + 1e-06 33200 2 304425.26 84084.197 8000 + 1e-06 33300 2 304425.26 84084.197 8000 + 1e-06 33400 2 304425.26 84084.197 8000 + 1e-06 33500 2 304425.26 84084.197 8000 + 1e-06 33600 2 304425.26 84084.197 8000 + 1e-06 33700 2 304425.26 84084.197 8000 + 1e-06 33800 2 304425.26 84084.197 8000 + 1e-06 33900 2 304425.26 84084.197 8000 + 1e-06 34000 2 304419.46 84084.197 8000 + 1e-06 34100 2 304377.55 84084.224 8000 + 1e-06 34200 2 304278.4 84084.45 8000 + 1e-06 34300 2 304108.46 84085.385 8000 + 1e-06 34400 2 303858.22 84088.048 8000 + 1e-06 34500 2 303521.62 84094.139 8000 + 1e-06 34600 2 303095.91 84106.182 8000 + 1e-06 34700 2 302581.78 84127.634 8000 + 1e-06 34800 2 301983.37 84162.962 8000 + 1e-06 34900 2 301308.35 84217.674 8000 + 1e-06 35000 2 300567.85 84298.29 8000 + 1e-06 35100 2 299776.31 84412.267 8000 + 1e-06 35200 2 298951.17 84567.862 8000 + 1e-06 35300 2 298112.52 84773.935 8000 + 1e-06 35400 2 297282.57 85039.703 8000 + 1e-06 35500 2 296485.02 85374.448 8000 + 1e-06 35600 2 295744.34 85787.18 8000 + 1e-06 35700 2 295085 86286.286 8000 + 1e-06 35800 2 294530.68 86879.159 8000 + 1e-06 35900 0 0 0 8000 + 1e-06 36000 0 0 0 8000 + 1e-06 36100 0 0 0 8000 + 1e-06 36200 0 0 0 8000 + 1e-06 36300 0 0 0 8000 + 1e-06 36400 0 0 0 8000 + 1e-06 36500 0 0 0 8000 + 1e-06 36600 0 0 0 8000 + 1e-06 36700 0 0 0 8000 + 1e-06 36800 0 0 0 8000 + 1e-06 36900 0 0 0 8000 + 1e-06 37000 0 0 0 8000 + 1e-06 37100 0 0 0 8000 + 1e-06 37200 0 0 0 8000 + 1e-06 37300 0 0 0 8000 + 1e-06 37400 0 0 0 8000 + 1e-06 37500 0 0 0 8000 + 1e-06 37600 0 0 0 8000 + 1e-06 37700 0 0 0 8000 + 1e-06 37800 0 0 0 8000 + 1e-06 37900 0 0 0 8000 + 1e-06 38000 0 0 0 8000 + 1e-06 38100 0 0 0 8000 + 1e-06 38200 0 0 0 8000 + 1e-06 38300 0 0 0 8000 + 1e-06 38400 0 0 0 8000 + 1e-06 38500 0 0 0 8000 + 1e-06 38600 0 0 0 8000 + 1e-06 38700 0 0 0 8000 + 1e-06 38800 0 0 0 8000 + 1e-06 38900 0 0 0 8000 + 1e-06 39000 0 0 0 8000 + 1e-06 39100 0 0 0 8000 + 1e-06 39200 0 0 0 8000 + 1e-06 39300 0 0 0 8000 + 1e-06 39400 0 0 0 8000 + 1e-06 39500 0 0 0 8000 + 1e-06 39600 0 0 0 8000 + 1e-06 39700 0 0 0 8000 + 1e-06 39800 0 0 0 8000 + 1e-06 39900 0 0 0 8000 + 1e-06 40000 0 0 0 8000 + 1e-06 40100 0 0 0 8000 + 1e-06 40200 0 0 0 8000 + 1e-06 40300 0 0 0 8000 + 1e-06 40400 0 0 0 8000 + 1e-06 40500 0 0 0 8000 + 1e-06 40600 0 0 0 8000 + 1e-06 40700 0 0 0 8000 + 1e-06 40800 0 0 0 8000 + 1e-06 40900 0 0 0 8000 + 1e-06 41000 0 0 0 8000 + 1e-06 41100 0 0 0 8000 + 1e-06 41200 0 0 0 8000 + 1e-06 41300 0 0 0 8000 + 1e-06 41400 0 0 0 8000 + 1e-06 41500 0 0 0 8000 + 1e-06 41600 0 0 0 8000 + 1e-06 41700 0 0 0 8000 + 1e-06 41800 0 0 0 8000 + 1e-06 41900 0 0 0 8000 + 1e-06 42000 0 0 0 8000 + 1e-06 42100 0 0 0 8000 + 1e-06 42200 0 0 0 8000 + 1e-06 42300 0 0 0 8000 + 1e-06 42400 0 0 0 8000 + 1e-06 42500 0 0 0 8000 + 1e-06 42600 0 0 0 8000 + 1e-06 42700 0 0 0 8000 + 1e-06 42800 0 0 0 8000 + 1e-06 42900 0 0 0 8000 + 1e-06 43000 0 0 0 8000 + 1e-06 43100 0 0 0 8000 + 1e-06 43200 0 0 0 8000 + 1e-06 43300 0 0 0 8000 + 1e-06 43400 0 0 0 8000 + 1e-06 43500 0 0 0 8000 + 1e-06 43600 0 0 0 8000 + 1e-06 43700 0 0 0 8000 + 1e-06 43800 0 0 0 8000 + 1e-06 43900 0 0 0 8000 + 1e-06 44000 0 0 0 8000 + 1e-06 44100 0 0 0 8000 + 1e-06 44200 0 0 0 8000 + 1e-06 44300 0 0 0 8000 + 1e-06 44400 0 0 0 8000 + 1e-06 44500 0 0 0 8000 + 1e-06 44600 0 0 0 8000 + 1e-06 44700 0 0 0 8000 + 1e-06 44800 0 0 0 8000 + 1e-06 44900 0 0 0 8000 + 1e-06 45000 0 0 0 8000 + 1e-06 45100 0 0 0 8000 + 1e-06 45200 0 0 0 8000 + 1e-06 45300 0 0 0 8000 + 1e-06 45400 0 0 0 8000 + 1e-06 45500 0 0 0 8000 + 1e-06 45600 0 0 0 8000 + 1e-06 45700 0 0 0 8000 + 1e-06 45800 0 0 0 8000 + 1e-06 45900 0 0 0 8000 + 1e-06 46000 0 0 0 8000 + 1e-06 46100 0 0 0 8000 + 1e-06 46200 0 0 0 8000 + 1e-06 46300 0 0 0 8000 + 1e-06 46400 0 0 0 8000 + 1e-06 46500 0 0 0 8000 + 1e-06 46600 0 0 0 8000 + 1e-06 46700 0 0 0 8000 + 1e-06 46800 0 0 0 8000 + 1e-06 46900 0 0 0 8000 + 1e-06 47000 0 0 0 8000 + 1e-06 47100 0 0 0 8000 + 1e-06 47200 0 0 0 8000 + 1e-06 47300 0 0 0 8000 + 1e-06 47400 0 0 0 8000 + 1e-06 47500 0 0 0 8000 + 1e-06 47600 0 0 0 8000 + 1e-06 47700 0 0 0 8000 + 1e-06 47800 0 0 0 8000 + 1e-06 47900 0 0 0 8000 + 1e-06 48000 0 0 0 8000 + 1e-06 48100 0 0 0 8000 + 1e-06 48200 0 0 0 8000 + 1e-06 48300 0 0 0 8000 + 1e-06 48400 0 0 0 8000 + 1e-06 48500 0 0 0 8000 + 1e-06 48600 0 0 0 8000 + 1e-06 48700 0 0 0 8000 + 1e-06 48800 0 0 0 8000 + 1e-06 48900 0 0 0 8000 + 1e-06 49000 0 0 0 8000 + 1e-06 49100 0 0 0 8000 + 1e-06 49200 0 0 0 8000 + 1e-06 49300 0 0 0 8000 + 1e-06 49400 0 0 0 8000 + 1e-06 49500 0 0 0 8000 + 1e-06 49600 0 0 0 8000 + 1e-06 49700 0 0 0 8000 + 1e-06 49800 0 0 0 8000 + 1e-06 49900 0 0 0 8000 +Loop time of 0.419125 on 1 procs for 49900 steps with 0 atoms + +99.7% CPU use with 1 MPI tasks x no OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.015815 | 0.015815 | 0.015815 | 0.0 | 3.77 +Neigh | 1.795e-05 | 1.795e-05 | 1.795e-05 | 0.0 | 0.00 +Comm | 0.0015216 | 0.0015216 | 0.0015216 | 0.0 | 0.36 +Output | 0.0024194 | 0.0024194 | 0.0024194 | 0.0 | 0.58 +Modify | 0.3932 | 0.3932 | 0.3932 | 0.0 | 93.81 +Other | | 0.006155 | | | 1.47 + +Nlocal: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 0 ave 0 max 0 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 0 +Neighbor list builds = 6 +Dangerous builds = 0 +Total wall time: 0:00:00 diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index 0e9a5ada7f..08e3698be5 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -154,27 +154,27 @@ void FixGranularMDR::setup_pre_force(int /*vflag*/) norm_model2 = dynamic_cast(fix->model->normal_model); - if (norm_model && norm_model2 && (norm_model->E != norm_model2->E)) + if (norm_model && norm_model2 && fabs(norm_model->E - norm_model2->E) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Young's modulus in pair style, {}, does not agree with value {} in fix gran/wall/region", norm_model->E, norm_model2->E); - if (norm_model->nu != norm_model2->nu) + if (fabs(norm_model->nu - norm_model2->nu) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Poisson's ratio in pair style, {}, does not agree with value {} in fix gran/wall/region", norm_model->nu, norm_model2->nu); - if (norm_model->Y != norm_model2->Y) + if (fabs(norm_model->Y - norm_model2->Y) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Yield stress in pair style, {}, does not agree with value {} in fix gran/wall/region", norm_model->Y, norm_model2->Y); - if (norm_model->psi_b != norm_model2->psi_b) + if (fabs(norm_model->psi_b - norm_model2->psi_b) > EPSILON) error->all(FLERR, Error::NOLASTLINE, "Bulk response trigger in pair style, {}, does not agree with value {} in fix " "gran/wall/region", norm_model->psi_b, norm_model2->psi_b); - if (norm_model->CoR != norm_model2->CoR) + if (fabs(norm_model->CoR - norm_model2->CoR) > EPSILON) error->all(FLERR, Error::NOLASTLINE, "Coefficient of restitution in pair style, {}, does not agree with value {} in " "fix gran/wall/region", @@ -243,18 +243,19 @@ void FixGranularMDR::pre_force(int) if (update->setupflag && (!new_atom)) continue; const double R = radius[i]; + const double Rsq = R * R; const double Vo = 4.0 / 3.0 * MY_PI * pow(Ro[i], 3.0); - const double Vgeoi = 4.0 / 3.0 * MY_PI * pow(R, 3.0) - Vcaps[i]; + const double Vgeoi = 4.0 / 3.0 * MY_PI * Rsq * R - Vcaps[i]; Vgeo[i] = MIN(Vgeoi, Vo); Velas[i] = Vo * (1.0 + eps_bar[i]); - Atot[i] = 4.0 * MY_PI * pow(R, 2.0) + Atot_sum[i]; + Atot[i] = 4.0 * MY_PI * Rsq + Atot_sum[i]; psi[i] = (Atot[i] - Acon1[i]) / Atot[i]; if (psi_b_coeff < psi[i]) { double w_confinement; - ( psi[i] > 0.1 ) ? w_confinement = 1.0/(1.0 + exp(-75.0*(psi[i]-0.2))) : w_confinement = 0.0; - const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * pow(R, 2.0))*w_confinement, 0.0); + ( psi[i] > 0.1 ) ? w_confinement = 1.0 / (1.0 + exp(-75.0 * (psi[i] - 0.2))) : w_confinement = 0.0; + const double dR = MAX(dRnumerator[i] / (dRdenominator[i] - 4.0 * MY_PI * Rsq) * w_confinement, 0.0); const double N_window = 10.0; if (dR > 0.0) dRavg[i] += (dR - dRavg[i]) / N_window; diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 1e233de38e..1c62c92c76 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -13,6 +13,7 @@ #include "gran_sub_mod_damping.h" +#include "error.h" #include "gran_sub_mod_normal.h" #include "fix_granular_mdr.h" #include "granular_model.h" @@ -185,10 +186,18 @@ GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : /* ---------------------------------------------------------------------- */ +void GranSubModDampingMDR::init() +{ + if (gm->normal_model->name != "mdr") + error->all(FLERR, "Damping mdr can only be used with mdr normal model"); +} + +/* ---------------------------------------------------------------------- */ + double GranSubModDampingMDR::calculate_forces() { using namespace Granular_MDR_NS; double *history = & gm->history[gm->normal_model->history_index]; damp_prefactor = damp * history[DAMP_SCALE]; return -damp_prefactor * gm->vnnr; -} \ No newline at end of file +} diff --git a/src/GRANULAR/gran_sub_mod_damping.h b/src/GRANULAR/gran_sub_mod_damping.h index 06aabbc5ca..cd7ee3bf1a 100644 --- a/src/GRANULAR/gran_sub_mod_damping.h +++ b/src/GRANULAR/gran_sub_mod_damping.h @@ -49,7 +49,6 @@ namespace Granular_NS { class GranSubModDampingNone : public GranSubModDamping { public: GranSubModDampingNone(class GranularModel *, class LAMMPS *); - void init() override{}; double calculate_forces() override; }; @@ -99,6 +98,7 @@ namespace Granular_NS { class GranSubModDampingMDR : public GranSubModDamping { public: GranSubModDampingMDR(class GranularModel *, class LAMMPS *); + void init() override; double calculate_forces() override; }; diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index f27057e5b2..5683f54fc2 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -978,7 +978,6 @@ double GranSubModNormalMDR::calculate_forces() return F; } - /* ---------------------------------------------------------------------- */ double GranSubModNormalMDR::calculate_nonadhesive_mdr_force(double delta, double Ainv, double Eeff, double A, double B) From a970f946a7b7de82cc11f3276cb811ffcae41216 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 4 Apr 2025 12:05:58 -0400 Subject: [PATCH 039/396] some more MPICH suppressions --- tools/valgrind/MPICH.supp | 218 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/tools/valgrind/MPICH.supp b/tools/valgrind/MPICH.supp index 53c090e215..80c6b66624 100644 --- a/tools/valgrind/MPICH.supp +++ b/tools/valgrind/MPICH.supp @@ -121,3 +121,221 @@ fun:PMPI_Init ... } +{ + MPICH_library1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... + fun:Run + fun:* + fun:* + fun:Run + ... +} +{ + MPICH_json1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:parse_json_tree + fun:MPIR_Csel_create_from_buf + fun:* + fun:* +} +{ + MPICH_comm1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:MPIR_Find_local + fun:* + fun:MPIR_Comm_commit + fun:MPIR_init_comm_world + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... + fun:Run + fun:* + fun:* +} +{ + MPICH_comm2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:MPIR_Find_external + fun:* + fun:MPIR_Comm_commit + fun:MPIR_init_comm_world + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... + fun:Run + fun:* + fun:* +} +{ + MPICH_comm3 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:MPIR_Find_local + fun:* + fun:MPIR_Comm_commit + fun:MPIR_init_comm_self + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... + fun:Run + fun:* + fun:* +} +{ + MPICH_comm4 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:MPIR_Find_external + fun:* + fun:MPIR_Comm_commit + fun:MPIR_init_comm_self + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... + fun:Run + fun:* + fun:* +} +{ + MPICH_psm3_1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:psm3_ep_open_internal + fun:psm3_ep_open + fun:* + fun:psmx3_sep_open + fun:* + fun:* + fun:MPIDI_OFI_init_local + fun:* + fun:* +} +{ + MPICH_psm3_2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:psm3_strdup_internal + fun:psm3_hal_pre_init_cache_func + fun:* + fun:psm3_info_query + fun:psmx3_update_nic_info + ... + fun:MPIDI_OFI_init_local + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init +} +{ + MPICH_psm3_3 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:psm3_strdup_internal + fun:psm3_stats_register_type_internal.part.0.lto_priv.0 + fun:* + fun:* + fun:ips_proto_register_stats + fun:psm3_ips_proto_init + fun:* + fun:psm3_ep_open_internal + fun:psm3_ep_open + fun:* + fun:psmx3_sep_open + fun:* + fun:* + fun:MPIDI_OFI_init_local +} +{ + MPICH_psm3_4 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:psm3_ep_open + fun:* + fun:psmx3_sep_open + ... + fun:MPIDI_OFI_init_local + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init +} +{ + MPICH_hwloc1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:hwloc_connect_children + fun:hwloc_connect_children + fun:hwloc_connect_children + fun:hwloc__reconnect + fun:hwloc_x86_discover + fun:* + fun:* + fun:hwloc_topology_load + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open +} +{ + MPICH_hwloc2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:hwloc_connect_children + fun:hwloc__reconnect + fun:hwloc_x86_discover + fun:* + fun:* + fun:hwloc_topology_load + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + fun:* + fun:* + fun:* +} From 3d4b57d7fde7a40f7ee9d683fab6315f22ca8c3c Mon Sep 17 00:00:00 2001 From: jtclemm Date: Fri, 4 Apr 2025 14:40:01 -0600 Subject: [PATCH 040/396] Removing old variable --- src/GRANULAR/fix_granular_mdr.cpp | 6 +++--- src/GRANULAR/gran_sub_mod_normal.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index 08e3698be5..8d9a0f116a 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -174,11 +174,11 @@ void FixGranularMDR::setup_pre_force(int /*vflag*/) "Bulk response trigger in pair style, {}, does not agree with value {} in fix " "gran/wall/region", norm_model->psi_b, norm_model2->psi_b); - if (fabs(norm_model->CoR - norm_model2->CoR) > EPSILON) + if (fabs(norm_model->get_damp() - norm_model2->get_damp()) > EPSILON) error->all(FLERR, Error::NOLASTLINE, - "Coefficient of restitution in pair style, {}, does not agree with value {} in " + "Damping in pair style, {}, does not agree with value {} in " "fix gran/wall/region", - norm_model->CoR, norm_model2->CoR); + norm_model->get_damp(), norm_model2->get_damp()); } fix_history = dynamic_cast(modify->get_fix_by_id("NEIGH_HISTORY_GRANULAR")); diff --git a/src/GRANULAR/gran_sub_mod_normal.h b/src/GRANULAR/gran_sub_mod_normal.h index b096e03ca8..8142d88cea 100644 --- a/src/GRANULAR/gran_sub_mod_normal.h +++ b/src/GRANULAR/gran_sub_mod_normal.h @@ -143,7 +143,7 @@ namespace Granular_NS { void coeffs_to_local() override; void init() override; double calculate_forces() override; - double E, nu, Y, gamma, CoR, psi_b; // specified coeffs + double E, nu, Y, gamma, psi_b; // specified coeffs protected: double G, kappa, Eeff; // derived coeffs From bff980b56faf7b98b422677bbc28a79b9d7da575 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 4 Apr 2025 17:15:56 -0400 Subject: [PATCH 041/396] cutghost is not used anyware; remove to plug memory leaks --- src/KOKKOS/mliap_unified_kokkos.cpp | 3 --- src/ML-IAP/mliap_descriptor.cpp | 3 +-- src/ML-IAP/mliap_descriptor.h | 17 ++++++++--------- src/ML-IAP/mliap_unified.cpp | 3 --- src/ML-IAP/pair_mliap.cpp | 4 ---- 5 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/KOKKOS/mliap_unified_kokkos.cpp b/src/KOKKOS/mliap_unified_kokkos.cpp index 1e57b8888c..bf7d6b46d5 100644 --- a/src/KOKKOS/mliap_unified_kokkos.cpp +++ b/src/KOKKOS/mliap_unified_kokkos.cpp @@ -107,17 +107,14 @@ void MLIAPDummyDescriptorKokkos::init() double cut; cutmax = 0.0; memory->create(cutsq, nelements, nelements, "mliap/descriptor/dummy:cutsq"); - memory->create(cutghost, nelements, nelements, "mliap/descriptor/dummy:cutghost"); for (int ielem = 0; ielem < nelements; ielem++) { // rcutfac set from python, is global cutoff for all elements cut = 2.0 * radelem[ielem] * rcutfac; if (cut > cutmax) cutmax = cut; cutsq[ielem][ielem] = cut * cut; - cutghost[ielem][ielem] = cut * cut; for (int jelem = ielem + 1; jelem < nelements; jelem++) { cut = (radelem[ielem] + radelem[jelem]) * rcutfac; cutsq[ielem][jelem] = cutsq[jelem][ielem] = cut * cut; - cutghost[ielem][jelem] = cutghost[jelem][ielem] = cut * cut; } } } diff --git a/src/ML-IAP/mliap_descriptor.cpp b/src/ML-IAP/mliap_descriptor.cpp index b8acd6329e..615cd75102 100644 --- a/src/ML-IAP/mliap_descriptor.cpp +++ b/src/ML-IAP/mliap_descriptor.cpp @@ -25,7 +25,7 @@ using namespace LAMMPS_NS; MLIAPDescriptor::MLIAPDescriptor(LAMMPS *lmp) : Pointers(lmp), ndescriptors(0), nelements(0), elements(nullptr), cutsq(nullptr), - cutghost(nullptr), radelem(nullptr), wjelem(nullptr) + radelem(nullptr), wjelem(nullptr) { cutmax = 0.0; allocated_elements = 0; @@ -38,7 +38,6 @@ MLIAPDescriptor::~MLIAPDescriptor() for (int i = 0; i < nelements; i++) delete[] elements[i]; delete[] elements; memory->destroy(cutsq); - memory->destroy(cutghost); memory->destroy(radelem); memory->destroy(wjelem); } diff --git a/src/ML-IAP/mliap_descriptor.h b/src/ML-IAP/mliap_descriptor.h index 6d66356960..676d5becbd 100644 --- a/src/ML-IAP/mliap_descriptor.h +++ b/src/ML-IAP/mliap_descriptor.h @@ -29,15 +29,14 @@ class MLIAPDescriptor : virtual protected Pointers { virtual void init() = 0; virtual double memory_usage(); - int ndescriptors; // number of descriptors - int nelements; // # of unique elements - int allocated_elements; // is the element array allocated - char **elements; // names of unique elements - double **cutsq; // nelem x nelem rcutsq values - double **cutghost; // cutoff for each ghost pair - double cutmax; // maximum cutoff needed - double *radelem; // element radii - double *wjelem; // elements weights + int ndescriptors; // number of descriptors + int nelements; // # of unique elements + int allocated_elements; // is the element array allocated + char **elements; // names of unique elements + double **cutsq; // nelem x nelem rcutsq values + double cutmax; // maximum cutoff needed + double *radelem; // element radii + double *wjelem; // elements weights protected: }; diff --git a/src/ML-IAP/mliap_unified.cpp b/src/ML-IAP/mliap_unified.cpp index 9998ff2af4..a7970022f4 100644 --- a/src/ML-IAP/mliap_unified.cpp +++ b/src/ML-IAP/mliap_unified.cpp @@ -95,17 +95,14 @@ void MLIAPDummyDescriptor::init() double cut; cutmax = 0.0; memory->create(cutsq, nelements, nelements, "mliap/descriptor/dummy:cutsq"); - memory->create(cutghost, nelements, nelements, "mliap/descriptor/dummy:cutghost"); for (int ielem = 0; ielem < nelements; ielem++) { // rcutfac set from python, is global cutoff for all elements cut = 2.0 * radelem[ielem] * rcutfac; if (cut > cutmax) cutmax = cut; cutsq[ielem][ielem] = cut * cut; - cutghost[ielem][ielem] = cut * cut; for (int jelem = ielem + 1; jelem < nelements; jelem++) { cut = (radelem[ielem] + radelem[jelem]) * rcutfac; cutsq[ielem][jelem] = cutsq[jelem][ielem] = cut * cut; - cutghost[ielem][jelem] = cutghost[jelem][ielem] = cut * cut; } } } diff --git a/src/ML-IAP/pair_mliap.cpp b/src/ML-IAP/pair_mliap.cpp index a40a0a7afa..5b569702d0 100644 --- a/src/ML-IAP/pair_mliap.cpp +++ b/src/ML-IAP/pair_mliap.cpp @@ -72,7 +72,6 @@ PairMLIAP::~PairMLIAP() if (allocated) { memory->destroy(setflag); memory->destroy(cutsq); - memory->destroy(cutghost); memory->destroy(map); } } @@ -125,7 +124,6 @@ void PairMLIAP::allocate() memory->create(setflag,n+1,n+1,"pair:setflag"); memory->create(cutsq,n+1,n+1,"pair:cutsq"); - memory->create(cutghost,n+1,n+1,"pair:cutghost"); memory->create(map,n+1,"pair:map"); } @@ -361,7 +359,6 @@ double PairMLIAP::init_one(int i, int j) "All pair coeffs are not set. Status\n" + Info::get_pair_coeff_status(lmp)); double cutmax = sqrt(descriptor->cutsq[map[i]][map[j]]); - cutghost[i][j] = cutghost[j][i] = 2.0 * cutmax + neighbor->skin; return cutmax; } @@ -376,7 +373,6 @@ double PairMLIAP::memory_usage() int n = atom->ntypes+1; bytes += (double)n*n*sizeof(int); // setflag bytes += (double)n*n*sizeof(int); // cutsq - bytes += (double)n*n*sizeof(int); // cutghost bytes += (double)n*sizeof(int); // map bytes += descriptor->memory_usage(); // Descriptor object bytes += model->memory_usage(); // Model object From be6acff029a82235f6292e1cfde75fa5f941c624 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 4 Apr 2025 17:17:08 -0400 Subject: [PATCH 042/396] must not allocate eatom and vatom in base class to avoid big memory leak --- src/KOKKOS/pair_mliap_kokkos.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/KOKKOS/pair_mliap_kokkos.cpp b/src/KOKKOS/pair_mliap_kokkos.cpp index bd029e04a2..3340c100a6 100644 --- a/src/KOKKOS/pair_mliap_kokkos.cpp +++ b/src/KOKKOS/pair_mliap_kokkos.cpp @@ -84,10 +84,10 @@ void PairMLIAPKokkos::compute(int eflag, int vflag) if (data->nelements != model->nelements) error->all(FLERR, "Incompatible model and descriptor element count"); - ev_init(eflag, vflag); + ev_init(eflag, vflag, 0); if (eflag_atom && (int)k_eatom.h_view.extent(0) < maxeatom) { - memoryKK->destroy_kokkos(k_eatom,eatom); - memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"pair:eatom"); + memoryKK->destroy_kokkos(k_eatom,eatom); + memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"pair:eatom"); } if (vflag_atom && (int)k_vatom.h_view.extent(0) < maxeatom) { From b9228a854e349fe7cd78d0f293e20b534d35c462 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 4 Apr 2025 17:17:40 -0400 Subject: [PATCH 043/396] no need to call allocate() of the base class --- src/KOKKOS/pair_mliap_kokkos.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/KOKKOS/pair_mliap_kokkos.cpp b/src/KOKKOS/pair_mliap_kokkos.cpp index 3340c100a6..8c06e7983d 100644 --- a/src/KOKKOS/pair_mliap_kokkos.cpp +++ b/src/KOKKOS/pair_mliap_kokkos.cpp @@ -37,7 +37,7 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ template -PairMLIAPKokkos::PairMLIAPKokkos(class LAMMPS* l) : PairMLIAP(l) +PairMLIAPKokkos::PairMLIAPKokkos(class LAMMPS *lmp) : PairMLIAP(lmp) { kokkosable = 1; execution_space = ExecutionSpaceFromDevice::space; @@ -45,7 +45,6 @@ PairMLIAPKokkos::PairMLIAPKokkos(class LAMMPS* l) : PairMLIAP(l) is_child=true; reverse_comm_device = 1; comm_type=COMM_TYPE::UNSET; - } /* ---------------------------------------------------------------------- */ @@ -217,10 +216,7 @@ void PairMLIAPKokkos::settings(int narg, char ** arg) template void PairMLIAPKokkos::coeff(int narg, char **arg) { if (narg < 3) error->all(FLERR,"Incorrect args for pair coefficients" + utils::errorurl(21)); - if (!allocated) { - PairMLIAP::allocate(); - allocate(); - } + if (!allocated) allocate(); char* type1 = arg[0]; char* type2 = arg[1]; From ea76dc99e9f2aceb8d0fdac448a8afabc1b4583b Mon Sep 17 00:00:00 2001 From: jtclemm Date: Fri, 4 Apr 2025 15:20:55 -0600 Subject: [PATCH 044/396] Adding damp coeff back in --- .../granular/log.4Feb25.tableting.200.g++.1 | 874 +++++++------- .../log.4Feb25.triaxial.compaction.12.g++.1 | 1035 +++++++++-------- src/GRANULAR/gran_sub_mod_damping.cpp | 2 + src/GRANULAR/gran_sub_mod_normal.cpp | 6 +- 4 files changed, 959 insertions(+), 958 deletions(-) diff --git a/examples/granular/log.4Feb25.tableting.200.g++.1 b/examples/granular/log.4Feb25.tableting.200.g++.1 index df6428ff1a..818198ccd7 100644 --- a/examples/granular/log.4Feb25.tableting.200.g++.1 +++ b/examples/granular/log.4Feb25.tableting.200.g++.1 @@ -1,4 +1,4 @@ -LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-581-g384d7f446b-modified) +LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-583-g3d4b57d7fd-modified) ##################################### SIMULATION SETTINGS ################################################### atom_style sphere 1 @@ -20,7 +20,7 @@ Reading data file ... 1 by 1 by 1 MPI processor grid reading atoms ... 200 atoms - read_data CPU = 0.004 seconds + read_data CPU = 0.003 seconds #################################### ADD DIE AND ATOM PARAMETERIZATION ###################################### @@ -195,9 +195,9 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes Dt Step Atoms KinEng Volume v_disp_upper 4e-06 0 200 0 2.1e-06 0 -Loop time of 8.51e-07 on 1 procs for 0 steps with 200 atoms +Loop time of 7.84e-07 on 1 procs for 0 steps with 200 atoms -117.5% CPU use with 1 MPI tasks x no OpenMP threads +127.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total @@ -207,7 +207,7 @@ Neigh | 0 | 0 | 0 | 0.0 | 0.00 Comm | 0 | 0 | 0 | 0.0 | 0.00 Output | 0 | 0 | 0 | 0.0 | 0.00 Modify | 0 | 0 | 0 | 0.0 | 0.00 -Other | | 8.51e-07 | | |100.00 +Other | | 7.84e-07 | | |100.00 Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 @@ -263,78 +263,78 @@ Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes Dt Step Atoms KinEng Volume v_disp_upper 4e-06 0 200 0 2.1e-06 0 4e-06 100 200 1.5945503e-09 2.1e-06 0 - 4e-06 200 200 6.3770738e-09 2.1e-06 0 - 4e-06 300 200 1.4245359e-08 2.1e-06 0 - 4e-06 400 200 2.5260505e-08 2.1e-06 0 - 4e-06 500 200 3.9464751e-08 2.1e-06 0 - 4e-06 600 200 5.6858098e-08 2.1e-06 0 - 4e-06 700 200 7.7385952e-08 2.1e-06 0 - 4e-06 800 198 1.0059548e-07 2.1e-06 0 - 4e-06 900 196 1.2599473e-07 2.1e-06 0 - 4e-06 1000 194 1.5428578e-07 2.1e-06 0 - 4e-06 1100 194 1.8644695e-07 2.1e-06 0 - 4e-06 1200 192 2.2088698e-07 2.1e-06 0 - 4e-06 1300 192 2.5897366e-07 2.1e-06 0 - 4e-06 1400 192 3.0013683e-07 2.1e-06 0 - 4e-06 1500 192 3.4277758e-07 2.1e-06 0 - 4e-06 1600 192 3.9077177e-07 2.1e-06 0 - 4e-06 1700 192 4.3898925e-07 2.1e-06 0 - 4e-06 1800 186 4.736674e-07 2.1e-06 0 - 4e-06 1900 184 5.2110858e-07 2.1e-06 0 - 4e-06 2000 184 5.7848899e-07 2.1e-06 0 - 4e-06 2100 184 6.3492469e-07 2.1e-06 0 - 4e-06 2200 184 6.9441989e-07 2.1e-06 0 - 4e-06 2300 182 inf 2.1e-06 0 - 4e-06 2400 176 7.9307687e-07 2.1e-06 0 - 4e-06 2500 176 8.599965e-07 2.1e-06 0 - 4e-06 2600 176 9.2970927e-07 2.1e-06 0 - 4e-06 2700 176 1.0022152e-06 2.1e-06 0 - 4e-06 2800 176 inf 2.1e-06 0 - 4e-06 2900 174 1.1458142e-06 2.1e-06 0 - 4e-06 3000 172 1.2159972e-06 2.1e-06 0 - 4e-06 3100 172 inf 2.1e-06 0 - 4e-06 3200 170 1.3640273e-06 2.1e-06 0 - 4e-06 3300 164 1.4023496e-06 2.1e-06 0 - 4e-06 3400 164 1.4878891e-06 2.1e-06 0 - 4e-06 3500 164 1.5760184e-06 2.1e-06 0 - 4e-06 3600 164 1.6667377e-06 2.1e-06 0 - 4e-06 3700 162 1.7486967e-06 2.1e-06 0 - 4e-06 3800 160 1.8165262e-06 2.1e-06 0 - 4e-06 3900 158 1.8886488e-06 2.1e-06 0 - 4e-06 4000 158 1.9853138e-06 2.1e-06 0 - 4e-06 4100 158 inf 2.1e-06 0 - 4e-06 4200 156 2.1616605e-06 2.1e-06 0 - 4e-06 4300 156 2.2655984e-06 2.1e-06 0 - 4e-06 4400 156 inf 2.1e-06 0 - 4e-06 4500 152 2.4161761e-06 2.1e-06 0 - 4e-06 4600 152 2.497822e-06 2.1e-06 0 - 4e-06 4700 150 2.6001287e-06 2.1e-06 0 - 4e-06 4800 148 inf 2.1e-06 0 - 4e-06 4900 146 inf 2.1e-06 0 - 4e-06 5000 140 2.7812394e-06 2.1e-06 0 -Loop time of 0.432192 on 1 procs for 5000 steps with 140 atoms + 4e-06 200 200 6.3722236e-09 2.1e-06 0 + 4e-06 300 200 1.4211064e-08 2.1e-06 0 + 4e-06 400 200 2.5258679e-08 2.1e-06 0 + 4e-06 500 200 3.9464769e-08 2.1e-06 0 + 4e-06 600 200 5.6825967e-08 2.1e-06 0 + 4e-06 700 200 7.7344469e-08 2.1e-06 0 + 4e-06 800 200 1.0060974e-07 2.1e-06 0 + 4e-06 900 200 1.2653591e-07 2.1e-06 0 + 4e-06 1000 200 1.5569212e-07 2.1e-06 0 + 4e-06 1100 200 1.8742647e-07 2.1e-06 0 + 4e-06 1200 200 2.215525e-07 2.1e-06 0 + 4e-06 1300 200 2.5959327e-07 2.1e-06 0 + 4e-06 1400 200 3.010369e-07 2.1e-06 0 + 4e-06 1500 200 3.4166871e-07 2.1e-06 0 + 4e-06 1600 200 3.8173997e-07 2.1e-06 0 + 4e-06 1700 200 4.2263596e-07 2.1e-06 0 + 4e-06 1800 200 4.6542919e-07 2.1e-06 0 + 4e-06 1900 200 5.1316032e-07 2.1e-06 0 + 4e-06 2000 200 5.6390086e-07 2.1e-06 0 + 4e-06 2100 200 6.1282692e-07 2.1e-06 0 + 4e-06 2200 200 6.6871978e-07 2.1e-06 0 + 4e-06 2300 200 7.2432957e-07 2.1e-06 0 + 4e-06 2400 200 7.7356329e-07 2.1e-06 0 + 4e-06 2500 200 8.3121212e-07 2.1e-06 0 + 4e-06 2600 200 8.9285402e-07 2.1e-06 0 + 4e-06 2700 200 9.5056709e-07 2.1e-06 0 + 4e-06 2800 200 1.0078859e-06 2.1e-06 0 + 4e-06 2900 200 1.0583726e-06 2.1e-06 0 + 4e-06 3000 200 1.1128777e-06 2.1e-06 0 + 4e-06 3100 200 1.149994e-06 2.1e-06 0 + 4e-06 3200 200 1.2038821e-06 2.1e-06 0 + 4e-06 3300 200 1.2266858e-06 2.1e-06 0 + 4e-06 3400 200 1.2785607e-06 2.1e-06 0 + 4e-06 3500 200 1.3382357e-06 2.1e-06 0 + 4e-06 3600 200 1.3864259e-06 2.1e-06 0 + 4e-06 3700 200 1.4382735e-06 2.1e-06 0 + 4e-06 3800 200 1.4261443e-06 2.1e-06 0 + 4e-06 3900 200 1.4409345e-06 2.1e-06 0 + 4e-06 4000 200 1.4794449e-06 2.1e-06 0 + 4e-06 4100 200 1.4696815e-06 2.1e-06 0 + 4e-06 4200 200 1.4980192e-06 2.1e-06 0 + 4e-06 4300 200 1.5093101e-06 2.1e-06 0 + 4e-06 4400 200 1.527165e-06 2.1e-06 0 + 4e-06 4500 200 1.5514338e-06 2.1e-06 0 + 4e-06 4600 200 1.5939536e-06 2.1e-06 0 + 4e-06 4700 200 1.6017087e-06 2.1e-06 0 + 4e-06 4800 200 1.5835827e-06 2.1e-06 0 + 4e-06 4900 200 1.5646707e-06 2.1e-06 0 + 4e-06 5000 200 1.5869167e-06 2.1e-06 0 +Loop time of 0.894952 on 1 procs for 5000 steps with 200 atoms 99.7% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.10597 | 0.10597 | 0.10597 | 0.0 | 24.52 -Neigh | 0.011871 | 0.011871 | 0.011871 | 0.0 | 2.75 -Comm | 0.00034652 | 0.00034652 | 0.00034652 | 0.0 | 0.08 -Output | 0.00027596 | 0.00027596 | 0.00027596 | 0.0 | 0.06 -Modify | 0.31284 | 0.31284 | 0.31284 | 0.0 | 72.39 -Other | | 0.0008893 | | | 0.21 +Pair | 0.33414 | 0.33414 | 0.33414 | 0.0 | 37.34 +Neigh | 0.013978 | 0.013978 | 0.013978 | 0.0 | 1.56 +Comm | 0.00055911 | 0.00055911 | 0.00055911 | 0.0 | 0.06 +Output | 0.00042257 | 0.00042257 | 0.00042257 | 0.0 | 0.05 +Modify | 0.54341 | 0.54341 | 0.54341 | 0.0 | 60.72 +Other | | 0.002439 | | | 0.27 -Nlocal: 140 ave 140 max 140 min +Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 865 ave 865 max 865 min +Neighs: 1663 ave 1663 max 1663 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 865 -Ave neighs/atom = 6.1785714 +Total # of neighbors = 1663 +Ave neighs/atom = 8.315 Neighbor list builds = 83 Dangerous builds not checked @@ -352,170 +352,170 @@ run 14000 Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes Dt Step Atoms KinEng Volume v_disp_upper - 4e-06 5000 140 2.7812394e-06 2.1e-06 0 - 4e-06 5100 140 2.8895541e-06 2.1e-06 -0.00015706645 - 4e-06 5200 136 2.9030642e-06 2.1e-06 -0.00031405381 - 4e-06 5300 134 2.9801402e-06 2.1e-06 -0.00047088304 - 4e-06 5400 134 inf 2.1e-06 -0.00062747516 - 4e-06 5500 130 3.1361708e-06 2.1e-06 -0.00078375133 - 4e-06 5600 130 3.224988e-06 2.1e-06 -0.00093963286 - 4e-06 5700 128 3.2981553e-06 2.1e-06 -0.0010950413 - 4e-06 5800 126 3.3346425e-06 2.1e-06 -0.0012498983 - 4e-06 5900 126 3.4495324e-06 2.1e-06 -0.0014041259 - 4e-06 6000 124 3.4436288e-06 2.1e-06 -0.0015576465 - 4e-06 6100 122 3.5108806e-06 2.1e-06 -0.0017103828 - 4e-06 6200 118 3.4808187e-06 2.1e-06 -0.0018622579 - 4e-06 6300 116 3.5520892e-06 2.1e-06 -0.0020131953 - 4e-06 6400 116 3.6651266e-06 2.1e-06 -0.002163119 - 4e-06 6500 116 3.7768528e-06 2.1e-06 -0.0023119534 - 4e-06 6600 114 3.8296982e-06 2.1e-06 -0.0024596238 - 4e-06 6700 110 3.8220731e-06 2.1e-06 -0.0026060556 - 4e-06 6800 108 3.8409573e-06 2.1e-06 -0.0027511752 - 4e-06 6900 108 inf 2.1e-06 -0.0028949095 - 4e-06 7000 104 3.9206342e-06 2.1e-06 -0.0030371862 - 4e-06 7100 102 3.9647246e-06 2.1e-06 -0.0031779335 - 4e-06 7200 102 inf 2.1e-06 -0.0033170806 - 4e-06 7300 98 3.9766723e-06 2.1e-06 -0.0034545575 - 4e-06 7400 90 3.7821936e-06 2.1e-06 -0.0035902949 - 4e-06 7500 90 inf 2.1e-06 -0.0037242245 - 4e-06 7600 86 3.8144737e-06 2.1e-06 -0.0038562789 - 4e-06 7700 84 3.7897749e-06 2.1e-06 -0.0039863915 - 4e-06 7800 82 3.8008682e-06 2.1e-06 -0.0041144968 - 4e-06 7900 80 3.791409e-06 2.1e-06 -0.0042405303 - 4e-06 8000 76 3.7336309e-06 2.1e-06 -0.0043644286 - 4e-06 8100 76 inf 2.1e-06 -0.0044861293 - 4e-06 8200 72 3.7708462e-06 2.1e-06 -0.0046055711 - 4e-06 8300 72 3.8690393e-06 2.1e-06 -0.0047226938 - 4e-06 8400 68 inf 2.1e-06 -0.0048374385 - 4e-06 8500 64 3.6623177e-06 2.1e-06 -0.0049497475 - 4e-06 8600 62 3.6134274e-06 2.1e-06 -0.005059564 - 4e-06 8700 62 3.6965363e-06 2.1e-06 -0.005166833 - 4e-06 8800 60 3.5674683e-06 2.1e-06 -0.0052715003 - 4e-06 8900 54 3.3423076e-06 2.1e-06 -0.0053735132 - 4e-06 9000 50 3.1486697e-06 2.1e-06 -0.0054728204 - 4e-06 9100 48 3.0716142e-06 2.1e-06 -0.0055693718 - 4e-06 9200 46 2.9984533e-06 2.1e-06 -0.005663119 - 4e-06 9300 46 inf 2.1e-06 -0.0057540145 - 4e-06 9400 34 inf 2.1e-06 -0.0058420128 - 4e-06 9500 32 2.4147256e-06 2.1e-06 -0.0059270694 - 4e-06 9600 32 inf 2.1e-06 -0.0060091416 - 4e-06 9700 26 inf 2.1e-06 -0.0060881879 - 4e-06 9800 20 1.5991947e-06 2.1e-06 -0.0061641687 - 4e-06 9900 20 inf 2.1e-06 -0.0062370457 - 4e-06 10000 16 1.3327917e-06 2.1e-06 -0.0063067821 - 4e-06 10100 10 8.8157027e-07 2.1e-06 -0.0063733428 - 4e-06 10200 10 8.9614642e-07 2.1e-06 -0.0064366944 - 4e-06 10300 10 8.9775988e-07 2.1e-06 -0.0064968049 - 4e-06 10400 10 9.0812889e-07 2.1e-06 -0.0065536441 - 4e-06 10500 10 9.003094e-07 2.1e-06 -0.0066071833 - 4e-06 10600 10 8.8275797e-07 2.1e-06 -0.0066573956 - 4e-06 10700 10 8.6537937e-07 2.1e-06 -0.0067042557 - 4e-06 10800 10 8.4817361e-07 2.1e-06 -0.00674774 - 4e-06 10900 10 8.311407e-07 2.1e-06 -0.0067878266 - 4e-06 11000 10 8.1428062e-07 2.1e-06 -0.0068244954 - 4e-06 11100 10 7.9759338e-07 2.1e-06 -0.0068577278 - 4e-06 11200 10 7.8107899e-07 2.1e-06 -0.0068875071 - 4e-06 11300 10 7.6473743e-07 2.1e-06 -0.0069138184 - 4e-06 11400 10 7.4856871e-07 2.1e-06 -0.0069366483 - 4e-06 11500 10 6.5214996e-07 2.1e-06 -0.0069559855 - 4e-06 11600 10 8.9415748e-07 2.1e-06 -0.0069718201 - 4e-06 11700 10 8.718476e-07 2.1e-06 -0.0069841441 - 4e-06 11800 10 1.0390866e-06 2.1e-06 -0.0069929515 - 4e-06 11900 10 1.058099e-06 2.1e-06 -0.0069982376 - 4e-06 12000 10 1.0772841e-06 2.1e-06 -0.007 - 4e-06 12100 10 1.0966421e-06 2.1e-06 -0.0069982376 - 4e-06 12200 10 1.116173e-06 2.1e-06 -0.0069929515 - 4e-06 12300 10 1.1358767e-06 2.1e-06 -0.0069841441 - 4e-06 12400 10 1.1557532e-06 2.1e-06 -0.0069718201 - 4e-06 12500 10 1.1709163e-06 2.1e-06 -0.0069559855 - 4e-06 12600 10 1.1781568e-06 2.1e-06 -0.0069366483 - 4e-06 12700 10 1.1814023e-06 2.1e-06 -0.0069138184 - 4e-06 12800 10 1.182238e-06 2.1e-06 -0.0068875071 - 4e-06 12900 10 1.1321834e-06 2.1e-06 -0.0068577278 - 4e-06 13000 10 1.1602658e-06 2.1e-06 -0.0068244954 - 4e-06 13100 10 1.1403281e-06 2.1e-06 -0.0067878266 - 4e-06 13200 10 1.1205632e-06 2.1e-06 -0.00674774 - 4e-06 13300 10 1.1009712e-06 2.1e-06 -0.0067042557 - 4e-06 13400 10 1.081552e-06 2.1e-06 -0.0066573956 - 4e-06 13500 10 1.0623057e-06 2.1e-06 -0.0066071833 - 4e-06 13600 10 9.7690472e-07 2.1e-06 -0.0065536441 - 4e-06 13700 10 8.7554649e-07 2.1e-06 -0.0064968049 - 4e-06 13800 10 8.6114161e-07 2.1e-06 -0.0064366944 - 4e-06 13900 10 7.2229969e-07 2.1e-06 -0.0063733428 - 4e-06 14000 10 6.0299298e-07 2.1e-06 -0.0063067821 - 4e-06 14100 10 5.9691906e-07 2.1e-06 -0.0062370457 - 4e-06 14200 10 5.8877052e-07 2.1e-06 -0.0061641687 - 4e-06 14300 10 5.8079481e-07 2.1e-06 -0.0060881879 - 4e-06 14400 10 5.0821182e-07 2.1e-06 -0.0060091416 - 4e-06 14500 10 4.5974587e-07 2.1e-06 -0.0059270694 - 4e-06 14600 10 4.5438391e-07 2.1e-06 -0.0058420128 - 4e-06 14700 10 4.4919479e-07 2.1e-06 -0.0057540145 - 4e-06 14800 10 3.6176002e-07 2.1e-06 -0.005663119 - 4e-06 14900 10 3.5835307e-07 2.1e-06 -0.0055693718 - 4e-06 15000 10 3.5511897e-07 2.1e-06 -0.0054728204 - 4e-06 15100 10 3.5205771e-07 2.1e-06 -0.0053735132 - 4e-06 15200 10 2.4180157e-07 2.1e-06 -0.0052715003 - 4e-06 15300 10 1.9792566e-07 2.1e-06 -0.005166833 - 4e-06 15400 10 1.9768384e-07 2.1e-06 -0.005059564 - 4e-06 15500 10 1.6550345e-07 2.1e-06 -0.0049497475 - 4e-06 15600 10 1.6608824e-07 2.1e-06 -0.0048374385 - 4e-06 15700 10 1.4780766e-07 2.1e-06 -0.0047226938 - 4e-06 15800 10 1.4899916e-07 2.1e-06 -0.0046055711 - 4e-06 15900 10 1.503635e-07 2.1e-06 -0.0044861293 - 4e-06 16000 10 1.5190069e-07 2.1e-06 -0.0043644286 - 4e-06 16100 10 1.5361071e-07 2.1e-06 -0.0042405303 - 4e-06 16200 10 1.5373505e-07 2.1e-06 -0.0041144968 - 4e-06 16300 10 1.5202036e-07 2.1e-06 -0.0039863915 - 4e-06 16400 10 1.5047851e-07 2.1e-06 -0.0038562789 - 4e-06 16500 10 1.491095e-07 2.1e-06 -0.0037242245 - 4e-06 16600 10 1.4791333e-07 2.1e-06 -0.0035902949 - 4e-06 16700 10 1.4689e-07 2.1e-06 -0.0034545575 - 4e-06 16800 10 1.460395e-07 2.1e-06 -0.0033170806 - 4e-06 16900 10 1.4536185e-07 2.1e-06 -0.0031779335 - 4e-06 17000 10 1.4485704e-07 2.1e-06 -0.0030371862 - 4e-06 17100 10 1.4452507e-07 2.1e-06 -0.0028949095 - 4e-06 17200 10 1.4436594e-07 2.1e-06 -0.0027511752 - 4e-06 17300 10 1.4297672e-07 2.1e-06 -0.0026060556 - 4e-06 17400 10 1.4034469e-07 2.1e-06 -0.0024596238 - 4e-06 17500 10 1.378855e-07 2.1e-06 -0.0023119534 - 4e-06 17600 10 1.3559914e-07 2.1e-06 -0.002163119 - 4e-06 17700 10 1.3348563e-07 2.1e-06 -0.0020131953 - 4e-06 17800 10 1.3154496e-07 2.1e-06 -0.0018622579 - 4e-06 17900 10 1.2977712e-07 2.1e-06 -0.0017103828 - 4e-06 18000 10 1.2659132e-07 2.1e-06 -0.0015576465 - 4e-06 18100 10 1.241758e-07 2.1e-06 -0.0014041259 - 4e-06 18200 10 1.2060433e-07 2.1e-06 -0.0012498983 - 4e-06 18300 10 1.172057e-07 2.1e-06 -0.0010950413 - 4e-06 18400 10 1.1397991e-07 2.1e-06 -0.00093963286 - 4e-06 18500 10 1.1092695e-07 2.1e-06 -0.00078375133 - 4e-06 18600 10 1.0804684e-07 2.1e-06 -0.00062747516 - 4e-06 18700 10 1.0533957e-07 2.1e-06 -0.00047088304 - 4e-06 18800 10 1.0280514e-07 2.1e-06 -0.00031405381 - 4e-06 18900 10 1.0044354e-07 2.1e-06 -0.00015706645 - 4e-06 19000 10 9.8254791e-08 2.1e-06 2.0903119e-17 -Loop time of 0.287179 on 1 procs for 14000 steps with 10 atoms + 4e-06 5000 200 1.5869167e-06 2.1e-06 0 + 4e-06 5100 200 1.533415e-06 2.1e-06 -0.00015706645 + 4e-06 5200 200 1.5210118e-06 2.1e-06 -0.00031405381 + 4e-06 5300 200 1.4717654e-06 2.1e-06 -0.00047088304 + 4e-06 5400 200 1.3867583e-06 2.1e-06 -0.00062747516 + 4e-06 5500 200 1.3210172e-06 2.1e-06 -0.00078375133 + 4e-06 5600 200 1.2694854e-06 2.1e-06 -0.00093963286 + 4e-06 5700 200 1.210939e-06 2.1e-06 -0.0010950413 + 4e-06 5800 200 1.1030246e-06 2.1e-06 -0.0012498983 + 4e-06 5900 200 1.0576145e-06 2.1e-06 -0.0014041259 + 4e-06 6000 200 9.6819458e-07 2.1e-06 -0.0015576465 + 4e-06 6100 200 8.4390663e-07 2.1e-06 -0.0017103828 + 4e-06 6200 200 7.1811878e-07 2.1e-06 -0.0018622579 + 4e-06 6300 200 5.9188275e-07 2.1e-06 -0.0020131953 + 4e-06 6400 200 4.8593994e-07 2.1e-06 -0.002163119 + 4e-06 6500 200 3.7604444e-07 2.1e-06 -0.0023119534 + 4e-06 6600 200 2.9315224e-07 2.1e-06 -0.0024596238 + 4e-06 6700 200 2.4346404e-07 2.1e-06 -0.0026060556 + 4e-06 6800 200 2.1035347e-07 2.1e-06 -0.0027511752 + 4e-06 6900 200 1.7982462e-07 2.1e-06 -0.0028949095 + 4e-06 7000 200 3.3817811e-07 2.1e-06 -0.0030371862 + 4e-06 7100 200 5.4229142e-07 2.1e-06 -0.0031779335 + 4e-06 7200 200 9.8011974e-07 2.1e-06 -0.0033170806 + 4e-06 7300 200 1.4073827e-06 2.1e-06 -0.0034545575 + 4e-06 7400 200 1.8007974e-06 2.1e-06 -0.0035902949 + 4e-06 7500 200 2.5690983e-06 2.1e-06 -0.0037242245 + 4e-06 7600 200 3.3504605e-06 2.1e-06 -0.0038562789 + 4e-06 7700 200 3.3047732e-06 2.1e-06 -0.0039863915 + 4e-06 7800 200 2.7409232e-06 2.1e-06 -0.0041144968 + 4e-06 7900 200 2.7731736e-06 2.1e-06 -0.0042405303 + 4e-06 8000 200 2.7721382e-06 2.1e-06 -0.0043644286 + 4e-06 8100 200 2.5449128e-06 2.1e-06 -0.0044861293 + 4e-06 8200 200 2.4113011e-06 2.1e-06 -0.0046055711 + 4e-06 8300 200 2.5104553e-06 2.1e-06 -0.0047226938 + 4e-06 8400 200 2.7969453e-06 2.1e-06 -0.0048374385 + 4e-06 8500 200 2.4549778e-06 2.1e-06 -0.0049497475 + 4e-06 8600 200 2.6065634e-06 2.1e-06 -0.005059564 + 4e-06 8700 200 1.94773e-06 2.1e-06 -0.005166833 + 4e-06 8800 200 1.8669003e-06 2.1e-06 -0.0052715003 + 4e-06 8900 200 1.7712516e-06 2.1e-06 -0.0053735132 + 4e-06 9000 200 1.5868574e-06 2.1e-06 -0.0054728204 + 4e-06 9100 200 1.2586882e-06 2.1e-06 -0.0055693718 + 4e-06 9200 200 1.7392355e-06 2.1e-06 -0.005663119 + 4e-06 9300 200 1.4103062e-06 2.1e-06 -0.0057540145 + 4e-06 9400 200 1.6133909e-06 2.1e-06 -0.0058420128 + 4e-06 9500 200 1.5715429e-06 2.1e-06 -0.0059270694 + 4e-06 9600 200 1.3060432e-06 2.1e-06 -0.0060091416 + 4e-06 9700 200 1.3016643e-06 2.1e-06 -0.0060881879 + 4e-06 9800 200 1.3827359e-06 2.1e-06 -0.0061641687 + 4e-06 9900 200 1.166866e-06 2.1e-06 -0.0062370457 + 4e-06 10000 200 1.1328931e-06 2.1e-06 -0.0063067821 + 4e-06 10100 200 1.0811811e-06 2.1e-06 -0.0063733428 + 4e-06 10200 200 1.0540805e-06 2.1e-06 -0.0064366944 + 4e-06 10300 200 9.3224876e-07 2.1e-06 -0.0064968049 + 4e-06 10400 200 8.8422228e-07 2.1e-06 -0.0065536441 + 4e-06 10500 200 9.6574449e-07 2.1e-06 -0.0066071833 + 4e-06 10600 200 6.5673924e-07 2.1e-06 -0.0066573956 + 4e-06 10700 200 5.7629287e-07 2.1e-06 -0.0067042557 + 4e-06 10800 200 5.1184648e-07 2.1e-06 -0.00674774 + 4e-06 10900 200 4.2140431e-07 2.1e-06 -0.0067878266 + 4e-06 11000 200 3.679501e-07 2.1e-06 -0.0068244954 + 4e-06 11100 200 2.7198635e-07 2.1e-06 -0.0068577278 + 4e-06 11200 200 3.9270049e-07 2.1e-06 -0.0068875071 + 4e-06 11300 200 2.5364345e-07 2.1e-06 -0.0069138184 + 4e-06 11400 200 2.311875e-07 2.1e-06 -0.0069366483 + 4e-06 11500 200 9.1194666e-08 2.1e-06 -0.0069559855 + 4e-06 11600 200 5.9128951e-08 2.1e-06 -0.0069718201 + 4e-06 11700 200 3.8675445e-08 2.1e-06 -0.0069841441 + 4e-06 11800 200 1.5261639e-08 2.1e-06 -0.0069929515 + 4e-06 11900 200 4.1435674e-09 2.1e-06 -0.0069982376 + 4e-06 12000 200 3.6182887e-10 2.1e-06 -0.007 + 4e-06 12100 200 3.4148153e-09 2.1e-06 -0.0069982376 + 4e-06 12200 200 1.201855e-08 2.1e-06 -0.0069929515 + 4e-06 12300 200 2.7088001e-08 2.1e-06 -0.0069841441 + 4e-06 12400 200 4.7261349e-08 2.1e-06 -0.0069718201 + 4e-06 12500 200 7.585591e-08 2.1e-06 -0.0069559855 + 4e-06 12600 200 1.0717843e-07 2.1e-06 -0.0069366483 + 4e-06 12700 200 1.4357347e-07 2.1e-06 -0.0069138184 + 4e-06 12800 200 2.3364223e-07 2.1e-06 -0.0068875071 + 4e-06 12900 200 2.6460705e-07 2.1e-06 -0.0068577278 + 4e-06 13000 200 3.0878617e-07 2.1e-06 -0.0068244954 + 4e-06 13100 200 4.0950412e-07 2.1e-06 -0.0067878266 + 4e-06 13200 200 5.4382238e-07 2.1e-06 -0.00674774 + 4e-06 13300 200 5.9323976e-07 2.1e-06 -0.0067042557 + 4e-06 13400 200 6.0024632e-07 2.1e-06 -0.0066573956 + 4e-06 13500 200 8.9144808e-07 2.1e-06 -0.0066071833 + 4e-06 13600 200 7.4298898e-07 2.1e-06 -0.0065536441 + 4e-06 13700 200 7.5476346e-07 2.1e-06 -0.0064968049 + 4e-06 13800 200 9.4480881e-07 2.1e-06 -0.0064366944 + 4e-06 13900 200 6.9480641e-07 2.1e-06 -0.0063733428 + 4e-06 14000 200 3.6996473e-07 2.1e-06 -0.0063067821 + 4e-06 14100 200 3.7522265e-07 2.1e-06 -0.0062370457 + 4e-06 14200 200 9.5971189e-07 2.1e-06 -0.0061641687 + 4e-06 14300 200 6.3482043e-07 2.1e-06 -0.0060881879 + 4e-06 14400 200 4.4208165e-08 2.1e-06 -0.0060091416 + 4e-06 14500 200 2.5451697e-09 2.1e-06 -0.0059270694 + 4e-06 14600 200 2.3358938e-10 2.1e-06 -0.0058420128 + 4e-06 14700 200 6.5542266e-10 2.1e-06 -0.0057540145 + 4e-06 14800 200 5.7442167e-10 2.1e-06 -0.005663119 + 4e-06 14900 200 1.8498409e-10 2.1e-06 -0.0055693718 + 4e-06 15000 200 8.9754087e-12 2.1e-06 -0.0054728204 + 4e-06 15100 200 1.5735217e-10 2.1e-06 -0.0053735132 + 4e-06 15200 200 2.0644095e-11 2.1e-06 -0.0052715003 + 4e-06 15300 200 3.1810324e-12 2.1e-06 -0.005166833 + 4e-06 15400 200 9.2248411e-13 2.1e-06 -0.005059564 + 4e-06 15500 200 1.049892e-12 2.1e-06 -0.0049497475 + 4e-06 15600 200 5.1537473e-13 2.1e-06 -0.0048374385 + 4e-06 15700 200 8.0874962e-14 2.1e-06 -0.0047226938 + 4e-06 15800 200 1.9259517e-14 2.1e-06 -0.0046055711 + 4e-06 15900 200 6.1677187e-14 2.1e-06 -0.0044861293 + 4e-06 16000 200 4.0175545e-14 2.1e-06 -0.0043644286 + 4e-06 16100 200 2.8906156e-14 2.1e-06 -0.0042405303 + 4e-06 16200 200 1.4689406e-14 2.1e-06 -0.0041144968 + 4e-06 16300 200 1.4816055e-14 2.1e-06 -0.0039863915 + 4e-06 16400 200 1.8585236e-14 2.1e-06 -0.0038562789 + 4e-06 16500 200 1.485896e-14 2.1e-06 -0.0037242245 + 4e-06 16600 200 1.5799533e-14 2.1e-06 -0.0035902949 + 4e-06 16700 200 1.5241276e-14 2.1e-06 -0.0034545575 + 4e-06 16800 200 1.1272606e-14 2.1e-06 -0.0033170806 + 4e-06 16900 200 1.2135244e-14 2.1e-06 -0.0031779335 + 4e-06 17000 200 1.143872e-14 2.1e-06 -0.0030371862 + 4e-06 17100 200 1.1915182e-14 2.1e-06 -0.0028949095 + 4e-06 17200 200 1.2037492e-14 2.1e-06 -0.0027511752 + 4e-06 17300 200 1.2142546e-14 2.1e-06 -0.0026060556 + 4e-06 17400 200 1.2259988e-14 2.1e-06 -0.0024596238 + 4e-06 17500 200 1.2151413e-14 2.1e-06 -0.0023119534 + 4e-06 17600 200 1.2016981e-14 2.1e-06 -0.002163119 + 4e-06 17700 200 1.1899607e-14 2.1e-06 -0.0020131953 + 4e-06 17800 200 1.1847233e-14 2.1e-06 -0.0018622579 + 4e-06 17900 200 1.2597274e-14 2.1e-06 -0.0017103828 + 4e-06 18000 200 1.2571584e-14 2.1e-06 -0.0015576465 + 4e-06 18100 200 1.2548167e-14 2.1e-06 -0.0014041259 + 4e-06 18200 200 1.2600584e-14 2.1e-06 -0.0012498983 + 4e-06 18300 200 1.2060676e-14 2.1e-06 -0.0010950413 + 4e-06 18400 200 1.2159889e-14 2.1e-06 -0.00093963286 + 4e-06 18500 200 1.2213635e-14 2.1e-06 -0.00078375133 + 4e-06 18600 200 1.2323751e-14 2.1e-06 -0.00062747516 + 4e-06 18700 200 1.2137887e-14 2.1e-06 -0.00047088304 + 4e-06 18800 200 1.2201084e-14 2.1e-06 -0.00031405381 + 4e-06 18900 200 1.2210617e-14 2.1e-06 -0.00015706645 + 4e-06 19000 200 1.2385845e-14 2.1e-06 2.0903119e-17 +Loop time of 9.48207 on 1 procs for 14000 steps with 200 atoms -99.8% CPU use with 1 MPI tasks x no OpenMP threads +99.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.049189 | 0.049189 | 0.049189 | 0.0 | 17.13 -Neigh | 0.0057064 | 0.0057064 | 0.0057064 | 0.0 | 1.99 -Comm | 0.00064863 | 0.00064863 | 0.00064863 | 0.0 | 0.23 -Output | 0.00089611 | 0.00089611 | 0.00089611 | 0.0 | 0.31 -Modify | 0.22899 | 0.22899 | 0.22899 | 0.0 | 79.74 -Other | | 0.001749 | | | 0.61 +Pair | 5.3814 | 5.3814 | 5.3814 | 0.0 | 56.75 +Neigh | 0.04326 | 0.04326 | 0.04326 | 0.0 | 0.46 +Comm | 0.0018574 | 0.0018574 | 0.0018574 | 0.0 | 0.02 +Output | 0.0018533 | 0.0018533 | 0.0018533 | 0.0 | 0.02 +Modify | 4.047 | 4.047 | 4.047 | 0.0 | 42.68 +Other | | 0.006661 | | | 0.07 -Nlocal: 10 ave 10 max 10 min +Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 2 ave 2 max 2 min +Neighs: 3146 ave 3146 max 3146 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 2 -Ave neighs/atom = 0.2 +Total # of neighbors = 3146 +Ave neighs/atom = 15.73 Neighbor list builds = 233 Dangerous builds not checked @@ -530,172 +530,172 @@ variable disp_upper equal 0.9*v_disp_lower run ${ejection_steps} run 14000 Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule -Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes +Per MPI rank memory allocation (min/avg/max) = 72.31 | 72.31 | 72.31 Mbytes Dt Step Atoms KinEng Volume v_disp_upper - 4e-06 19000 10 9.8254791e-08 2.1e-06 0 - 4e-06 19100 10 9.6238878e-08 2.1e-06 0.00010097765 - 4e-06 19200 10 9.4395806e-08 2.1e-06 0.00020194258 - 4e-06 19300 10 9.2725573e-08 2.1e-06 0.00030288209 - 4e-06 19400 10 9.1228181e-08 2.1e-06 0.00040378347 - 4e-06 19500 10 8.9903628e-08 2.1e-06 0.00050463403 - 4e-06 19600 10 8.8751915e-08 2.1e-06 0.00060542105 - 4e-06 19700 10 6.9553679e-08 2.1e-06 0.00070613186 - 4e-06 19800 10 3.855161e-07 2.1e-06 0.00080675378 - 4e-06 19900 10 3.8006492e-07 2.1e-06 0.00090727414 - 4e-06 20000 10 3.7478659e-07 2.1e-06 0.0010076803 - 4e-06 20100 10 3.6968109e-07 2.1e-06 0.0011079596 - 4e-06 20200 10 3.6474843e-07 2.1e-06 0.0012080994 - 4e-06 20300 10 3.5998861e-07 2.1e-06 0.0013080871 - 4e-06 20400 10 3.5540163e-07 2.1e-06 0.0014079102 - 4e-06 20500 10 3.509875e-07 2.1e-06 0.001507556 - 4e-06 20600 10 3.467462e-07 2.1e-06 0.0016070121 - 4e-06 20700 10 3.4267774e-07 2.1e-06 0.0017062658 - 4e-06 20800 10 3.3878212e-07 2.1e-06 0.0018053047 - 4e-06 20900 10 6.2902098e-07 2.1e-06 0.0019041164 - 4e-06 21000 10 7.1567323e-07 2.1e-06 0.0020026884 - 4e-06 21100 10 7.0670404e-07 2.1e-06 0.0021010083 - 4e-06 21200 10 6.9790769e-07 2.1e-06 0.0021990637 - 4e-06 21300 10 6.8928417e-07 2.1e-06 0.0022968422 - 4e-06 21400 10 6.808335e-07 2.1e-06 0.0023943316 - 4e-06 21500 10 8.228831e-07 2.1e-06 0.0024915196 - 4e-06 21600 10 8.1258059e-07 2.1e-06 0.0025883939 - 4e-06 21700 10 8.0245093e-07 2.1e-06 0.0026849424 - 4e-06 21800 10 7.924941e-07 2.1e-06 0.0027811529 - 4e-06 21900 10 7.8271011e-07 2.1e-06 0.0028770133 - 4e-06 22000 10 7.7309896e-07 2.1e-06 0.0029725116 - 4e-06 22100 10 7.6366066e-07 2.1e-06 0.0030676356 - 4e-06 22200 10 7.5439519e-07 2.1e-06 0.0031623734 - 4e-06 22300 10 9.6736756e-07 2.1e-06 0.0032567132 - 4e-06 22400 10 9.5508751e-07 2.1e-06 0.0033506429 - 4e-06 22500 10 1.146027e-06 2.1e-06 0.0034441509 - 4e-06 22600 10 1.3340747e-06 2.1e-06 0.0035372253 - 4e-06 22700 10 1.3161012e-06 2.1e-06 0.0036298544 - 4e-06 22800 10 1.3780346e-06 2.1e-06 0.0037220265 - 4e-06 22900 10 1.4437449e-06 2.1e-06 0.0038137301 - 4e-06 23000 10 1.4237439e-06 2.1e-06 0.0039049537 - 4e-06 23100 10 1.4039157e-06 2.1e-06 0.0039956856 - 4e-06 23200 10 1.3842603e-06 2.1e-06 0.0040859145 - 4e-06 23300 10 1.3647778e-06 2.1e-06 0.0041756291 - 4e-06 23400 10 1.3454681e-06 2.1e-06 0.004264818 - 4e-06 23500 10 1.3263312e-06 2.1e-06 0.00435347 - 4e-06 23600 10 1.3073672e-06 2.1e-06 0.004441574 - 4e-06 23700 10 1.4224882e-06 2.1e-06 0.0045291188 - 4e-06 23800 10 1.4016962e-06 2.1e-06 0.0046160935 - 4e-06 23900 10 1.381077e-06 2.1e-06 0.0047024871 - 4e-06 24000 10 1.3606307e-06 2.1e-06 0.0047882887 - 4e-06 24100 10 1.3403572e-06 2.1e-06 0.0048734875 - 4e-06 24200 10 1.3202566e-06 2.1e-06 0.0049580728 - 4e-06 24300 10 1.3003288e-06 2.1e-06 0.005042034 - 4e-06 24400 10 1.2805739e-06 2.1e-06 0.0051253604 - 4e-06 24500 10 1.2609917e-06 2.1e-06 0.0052080417 - 4e-06 24600 10 1.2415825e-06 2.1e-06 0.0052900673 - 4e-06 24700 10 1.222346e-06 2.1e-06 0.0053714269 - 4e-06 24800 10 1.2032824e-06 2.1e-06 0.0054521104 - 4e-06 24900 10 1.1843917e-06 2.1e-06 0.0055321075 - 4e-06 25000 10 1.2550315e-06 2.1e-06 0.0056114082 - 4e-06 25100 10 1.2348763e-06 2.1e-06 0.0056900025 - 4e-06 25200 10 1.2148941e-06 2.1e-06 0.0057678805 - 4e-06 25300 10 1.1950846e-06 2.1e-06 0.0058450324 - 4e-06 25400 10 1.175448e-06 2.1e-06 0.0059214485 - 4e-06 25500 10 1.1559842e-06 2.1e-06 0.0059971192 - 4e-06 25600 10 1.1366933e-06 2.1e-06 0.0060720349 - 4e-06 25700 10 1.1175752e-06 2.1e-06 0.0061461862 - 4e-06 25800 10 1.0986299e-06 2.1e-06 0.0062195638 - 4e-06 25900 10 1.0798575e-06 2.1e-06 0.0062921585 - 4e-06 26000 10 1.061258e-06 2.1e-06 0.006363961 - 4e-06 26100 10 9.1373064e-07 2.1e-06 0.0064349624 - 4e-06 26200 10 8.9836765e-07 2.1e-06 0.0065051538 - 4e-06 26300 10 8.8317749e-07 2.1e-06 0.0065745262 - 4e-06 26400 10 8.6816018e-07 2.1e-06 0.006643071 - 4e-06 26500 10 7.2232503e-07 2.1e-06 0.0067107795 - 4e-06 26600 10 7.1072319e-07 2.1e-06 0.0067776432 - 4e-06 26700 10 6.9929419e-07 2.1e-06 0.0068436537 - 4e-06 26800 10 6.8803803e-07 2.1e-06 0.0069088027 - 4e-06 26900 10 6.7695471e-07 2.1e-06 0.0069730819 - 4e-06 27000 10 6.6604423e-07 2.1e-06 0.0070364833 - 4e-06 27100 10 6.5530659e-07 2.1e-06 0.007098999 - 4e-06 27200 10 6.4474179e-07 2.1e-06 0.0071606209 - 4e-06 27300 10 6.3434984e-07 2.1e-06 0.0072213415 - 4e-06 27400 10 6.2413072e-07 2.1e-06 0.0072811529 - 4e-06 27500 10 6.1408444e-07 2.1e-06 0.0073400478 - 4e-06 27600 10 6.04211e-07 2.1e-06 0.0073980187 - 4e-06 27700 10 5.945104e-07 2.1e-06 0.0074550582 - 4e-06 27800 10 5.8498264e-07 2.1e-06 0.0075111593 - 4e-06 27900 10 5.7562772e-07 2.1e-06 0.0075663148 - 4e-06 28000 10 5.6644564e-07 2.1e-06 0.0076205178 - 4e-06 28100 10 5.574364e-07 2.1e-06 0.0076737615 - 4e-06 28200 10 5.486e-07 2.1e-06 0.0077260391 - 4e-06 28300 10 5.3993644e-07 2.1e-06 0.0077773442 - 4e-06 28400 10 5.3144572e-07 2.1e-06 0.0078276702 - 4e-06 28500 10 5.1027539e-07 2.1e-06 0.0078770108 - 4e-06 28600 10 3.5840723e-07 2.1e-06 0.0079253598 - 4e-06 28700 10 3.7060273e-07 2.1e-06 0.0079727111 - 4e-06 28800 10 3.6745652e-07 2.1e-06 0.0080190587 - 4e-06 28900 10 3.6448315e-07 2.1e-06 0.0080643969 - 4e-06 29000 10 3.0843931e-07 2.1e-06 0.0081087198 - 4e-06 29100 10 3.0772799e-07 2.1e-06 0.008152022 - 4e-06 29200 10 3.0718951e-07 2.1e-06 0.0081942979 - 4e-06 29300 10 3.0682387e-07 2.1e-06 0.0082355423 - 4e-06 29400 10 3.0663107e-07 2.1e-06 0.00827575 - 4e-06 29500 10 3.0661111e-07 2.1e-06 0.0083149158 - 4e-06 29600 10 3.0676399e-07 2.1e-06 0.0083530349 - 4e-06 29700 10 3.0708971e-07 2.1e-06 0.0083901025 - 4e-06 29800 10 3.0758827e-07 2.1e-06 0.0084261138 - 4e-06 29900 10 3.0825967e-07 2.1e-06 0.0084610645 - 4e-06 30000 10 3.0910391e-07 2.1e-06 0.00849495 - 4e-06 30100 10 2.7633224e-07 2.1e-06 0.0085277661 - 4e-06 30200 10 2.7917696e-07 2.1e-06 0.0085595086 - 4e-06 30300 10 2.8219452e-07 2.1e-06 0.0085901737 - 4e-06 30400 10 2.8538492e-07 2.1e-06 0.0086197574 - 4e-06 30500 10 2.8874816e-07 2.1e-06 0.0086482559 - 4e-06 30600 10 2.9228424e-07 2.1e-06 0.0086756657 - 4e-06 30700 10 2.9599316e-07 2.1e-06 0.0087019834 - 4e-06 30800 10 2.9987493e-07 2.1e-06 0.0087272057 - 4e-06 30900 10 3.0392953e-07 2.1e-06 0.0087513293 - 4e-06 31000 10 3.0815697e-07 2.1e-06 0.0087743512 - 4e-06 31100 10 3.1255725e-07 2.1e-06 0.0087962686 - 4e-06 31200 10 3.1713037e-07 2.1e-06 0.0088170786 - 4e-06 31300 10 3.2187633e-07 2.1e-06 0.0088367787 - 4e-06 31400 10 3.2679513e-07 2.1e-06 0.0088553663 - 4e-06 31500 10 3.3188677e-07 2.1e-06 0.0088728392 - 4e-06 31600 10 3.3522008e-07 2.1e-06 0.0088891951 - 4e-06 31700 10 3.3129412e-07 2.1e-06 0.0089044319 - 4e-06 31800 10 3.3814673e-07 2.1e-06 0.0089185479 - 4e-06 31900 10 3.7840167e-07 2.1e-06 0.0089315411 - 4e-06 32000 10 3.8178891e-07 2.1e-06 0.0089434099 - 4e-06 32100 10 3.8534899e-07 2.1e-06 0.0089541529 - 4e-06 32200 10 3.8908191e-07 2.1e-06 0.0089637686 - 4e-06 32300 10 4.1410686e-07 2.1e-06 0.008972256 - 4e-06 32400 10 4.1433199e-07 2.1e-06 0.0089796139 - 4e-06 32500 10 4.1472995e-07 2.1e-06 0.0089858413 - 4e-06 32600 10 4.1530076e-07 2.1e-06 0.0089909376 - 4e-06 32700 10 4.1604441e-07 2.1e-06 0.008994902 - 4e-06 32800 10 4.169609e-07 2.1e-06 0.0089977341 - 4e-06 32900 10 4.1805022e-07 2.1e-06 0.0089994335 - 4e-06 33000 10 4.1931239e-07 2.1e-06 0.009 -Loop time of 0.177773 on 1 procs for 14000 steps with 10 atoms + 4e-06 19000 200 1.2385845e-14 2.1e-06 0 + 4e-06 19100 200 1.2261513e-05 2.1e-06 0.00010097765 + 4e-06 19200 200 1.668842e-05 2.1e-06 0.00020194258 + 4e-06 19300 200 8.188349e-06 2.1e-06 0.00030288209 + 4e-06 19400 200 3.786144e-06 2.1e-06 0.00040378347 + 4e-06 19500 200 9.574368e-06 2.1e-06 0.00050463403 + 4e-06 19600 200 1.1344815e-05 2.1e-06 0.00060542105 + 4e-06 19700 200 5.9381813e-06 2.1e-06 0.00070613186 + 4e-06 19800 200 6.6666301e-06 2.1e-06 0.00080675378 + 4e-06 19900 200 1.090387e-05 2.1e-06 0.00090727414 + 4e-06 20000 200 7.740567e-06 2.1e-06 0.0010076803 + 4e-06 20100 200 6.2375154e-06 2.1e-06 0.0011079596 + 4e-06 20200 200 9.3040254e-06 2.1e-06 0.0012080994 + 4e-06 20300 200 8.9696433e-06 2.1e-06 0.0013080871 + 4e-06 20400 200 6.5727278e-06 2.1e-06 0.0014079102 + 4e-06 20500 200 7.762698e-06 2.1e-06 0.001507556 + 4e-06 20600 200 9.2433982e-06 2.1e-06 0.0016070121 + 4e-06 20700 200 7.3505514e-06 2.1e-06 0.0017062658 + 4e-06 20800 200 6.9601084e-06 2.1e-06 0.0018053047 + 4e-06 20900 200 8.6605025e-06 2.1e-06 0.0019041164 + 4e-06 21000 200 8.0661649e-06 2.1e-06 0.0020026884 + 4e-06 21100 200 6.9330037e-06 2.1e-06 0.0021010083 + 4e-06 21200 200 7.8802994e-06 2.1e-06 0.0021990637 + 4e-06 21300 200 8.12707e-06 2.1e-06 0.0022968422 + 4e-06 21400 200 7.1184483e-06 2.1e-06 0.0023943316 + 4e-06 21500 200 7.3747722e-06 2.1e-06 0.0024915196 + 4e-06 21600 200 7.941038e-06 2.1e-06 0.0025883939 + 4e-06 21700 200 7.2906871e-06 2.1e-06 0.0026849424 + 4e-06 21800 200 7.0584615e-06 2.1e-06 0.0027811529 + 4e-06 21900 200 7.6303484e-06 2.1e-06 0.0028770133 + 4e-06 22000 200 7.3276603e-06 2.1e-06 0.0029725116 + 4e-06 22100 200 7.0392936e-06 2.1e-06 0.0030676356 + 4e-06 22200 200 7.1860378e-06 2.1e-06 0.0031623734 + 4e-06 22300 200 7.1628093e-06 2.1e-06 0.0032567132 + 4e-06 22400 200 6.9556524e-06 2.1e-06 0.0033506429 + 4e-06 22500 200 6.9109402e-06 2.1e-06 0.0034441509 + 4e-06 22600 200 6.981937e-06 2.1e-06 0.0035372253 + 4e-06 22700 200 6.8009271e-06 2.1e-06 0.0036298544 + 4e-06 22800 200 6.6923037e-06 2.1e-06 0.0037220265 + 4e-06 22900 200 6.7438993e-06 2.1e-06 0.0038137301 + 4e-06 23000 200 6.6280705e-06 2.1e-06 0.0039049537 + 4e-06 23100 200 6.4659616e-06 2.1e-06 0.0039956856 + 4e-06 23200 200 6.486839e-06 2.1e-06 0.0040859145 + 4e-06 23300 200 6.4478859e-06 2.1e-06 0.0041756291 + 4e-06 23400 200 6.2666043e-06 2.1e-06 0.004264818 + 4e-06 23500 200 6.2352434e-06 2.1e-06 0.00435347 + 4e-06 23600 200 6.2074024e-06 2.1e-06 0.004441574 + 4e-06 23700 200 6.068366e-06 2.1e-06 0.0045291188 + 4e-06 23800 200 5.9784229e-06 2.1e-06 0.0046160935 + 4e-06 23900 200 5.9536629e-06 2.1e-06 0.0047024871 + 4e-06 24000 200 5.8480609e-06 2.1e-06 0.0047882887 + 4e-06 24100 200 5.707216e-06 2.1e-06 0.0048734875 + 4e-06 24200 200 5.6922834e-06 2.1e-06 0.0049580728 + 4e-06 24300 200 5.6187319e-06 2.1e-06 0.005042034 + 4e-06 24400 200 5.4774741e-06 2.1e-06 0.0051253604 + 4e-06 24500 200 5.4144843e-06 2.1e-06 0.0052080417 + 4e-06 24600 200 5.3595768e-06 2.1e-06 0.0052900673 + 4e-06 24700 200 5.2374057e-06 2.1e-06 0.0053714269 + 4e-06 24800 200 5.1410204e-06 2.1e-06 0.0054521104 + 4e-06 24900 200 5.0888231e-06 2.1e-06 0.0055321075 + 4e-06 25000 200 4.984139e-06 2.1e-06 0.0056114082 + 4e-06 25100 200 4.9836569e-06 2.1e-06 0.0056900025 + 4e-06 25200 200 4.7331289e-06 2.1e-06 0.0057678805 + 4e-06 25300 200 4.6728119e-06 2.1e-06 0.0058450324 + 4e-06 25400 200 4.7016583e-06 2.1e-06 0.0059214485 + 4e-06 25500 200 4.5200193e-06 2.1e-06 0.0059971192 + 4e-06 25600 200 4.378095e-06 2.1e-06 0.0060720349 + 4e-06 25700 200 4.3949017e-06 2.1e-06 0.0061461862 + 4e-06 25800 200 4.2795904e-06 2.1e-06 0.0062195638 + 4e-06 25900 200 4.116551e-06 2.1e-06 0.0062921585 + 4e-06 26000 200 4.0844003e-06 2.1e-06 0.006363961 + 4e-06 26100 200 4.0601132e-06 2.1e-06 0.0064349624 + 4e-06 26200 200 3.8632558e-06 2.1e-06 0.0065051538 + 4e-06 26300 200 3.7501901e-06 2.1e-06 0.0065745262 + 4e-06 26400 200 3.7665658e-06 2.1e-06 0.006643071 + 4e-06 26500 200 3.6221171e-06 2.1e-06 0.0067107795 + 4e-06 26600 200 3.483452e-06 2.1e-06 0.0067776432 + 4e-06 26700 200 3.4573133e-06 2.1e-06 0.0068436537 + 4e-06 26800 200 3.3725298e-06 2.1e-06 0.0069088027 + 4e-06 26900 200 3.2275695e-06 2.1e-06 0.0069730819 + 4e-06 27000 200 3.1636462e-06 2.1e-06 0.0070364833 + 4e-06 27100 200 3.1002791e-06 2.1e-06 0.007098999 + 4e-06 27200 200 2.9719515e-06 2.1e-06 0.0071606209 + 4e-06 27300 200 2.8999181e-06 2.1e-06 0.0072213415 + 4e-06 27400 200 2.8296722e-06 2.1e-06 0.0072811529 + 4e-06 27500 200 2.7244185e-06 2.1e-06 0.0073400478 + 4e-06 27600 200 2.6342108e-06 2.1e-06 0.0073980187 + 4e-06 27700 200 2.5655873e-06 2.1e-06 0.0074550582 + 4e-06 27800 200 2.4771843e-06 2.1e-06 0.0075111593 + 4e-06 27900 200 2.3805529e-06 2.1e-06 0.0075663148 + 4e-06 28000 200 2.3094253e-06 2.1e-06 0.0076205178 + 4e-06 28100 200 2.2443631e-06 2.1e-06 0.0076737615 + 4e-06 28200 200 2.1339799e-06 2.1e-06 0.0077260391 + 4e-06 28300 200 2.0525827e-06 2.1e-06 0.0077773442 + 4e-06 28400 200 2.0012311e-06 2.1e-06 0.0078276702 + 4e-06 28500 200 1.9064828e-06 2.1e-06 0.0078770108 + 4e-06 28600 200 1.8186848e-06 2.1e-06 0.0079253598 + 4e-06 28700 200 1.7614909e-06 2.1e-06 0.0079727111 + 4e-06 28800 200 1.6854916e-06 2.1e-06 0.0080190587 + 4e-06 28900 200 1.5987487e-06 2.1e-06 0.0080643969 + 4e-06 29000 200 1.5345142e-06 2.1e-06 0.0081087198 + 4e-06 29100 200 1.4807046e-06 2.1e-06 0.008152022 + 4e-06 29200 200 1.3891852e-06 2.1e-06 0.0081942979 + 4e-06 29300 200 1.3152808e-06 2.1e-06 0.0082355423 + 4e-06 29400 200 1.2682955e-06 2.1e-06 0.00827575 + 4e-06 29500 200 1.1980726e-06 2.1e-06 0.0083149158 + 4e-06 29600 200 1.1206391e-06 2.1e-06 0.0083530349 + 4e-06 29700 200 1.069315e-06 2.1e-06 0.0083901025 + 4e-06 29800 200 1.0128853e-06 2.1e-06 0.0084261138 + 4e-06 29900 200 9.4294228e-07 2.1e-06 0.0084610645 + 4e-06 30000 200 8.8682322e-07 2.1e-06 0.00849495 + 4e-06 30100 200 8.3143727e-07 2.1e-06 0.0085277661 + 4e-06 30200 200 7.7886925e-07 2.1e-06 0.0085595086 + 4e-06 30300 200 7.2644265e-07 2.1e-06 0.0085901737 + 4e-06 30400 200 6.7416382e-07 2.1e-06 0.0086197574 + 4e-06 30500 200 6.2520867e-07 2.1e-06 0.0086482559 + 4e-06 30600 200 5.7710448e-07 2.1e-06 0.0086756657 + 4e-06 30700 200 5.3156928e-07 2.1e-06 0.0087019834 + 4e-06 30800 200 4.8684727e-07 2.1e-06 0.0087272057 + 4e-06 30900 200 4.4454752e-07 2.1e-06 0.0087513293 + 4e-06 31000 200 4.0418128e-07 2.1e-06 0.0087743512 + 4e-06 31100 200 3.677997e-07 2.1e-06 0.0087962686 + 4e-06 31200 200 3.2762411e-07 2.1e-06 0.0088170786 + 4e-06 31300 200 2.9156601e-07 2.1e-06 0.0088367787 + 4e-06 31400 200 2.6235825e-07 2.1e-06 0.0088553663 + 4e-06 31500 200 2.2926207e-07 2.1e-06 0.0088728392 + 4e-06 31600 200 1.9870435e-07 2.1e-06 0.0088891951 + 4e-06 31700 200 1.7318685e-07 2.1e-06 0.0089044319 + 4e-06 31800 200 1.4793716e-07 2.1e-06 0.0089185479 + 4e-06 31900 200 1.2335756e-07 2.1e-06 0.0089315411 + 4e-06 32000 200 1.024269e-07 2.1e-06 0.0089434099 + 4e-06 32100 200 8.4811971e-08 2.1e-06 0.0089541529 + 4e-06 32200 200 6.5610079e-08 2.1e-06 0.0089637686 + 4e-06 32300 200 4.9804549e-08 2.1e-06 0.008972256 + 4e-06 32400 200 3.7696394e-08 2.1e-06 0.0089796139 + 4e-06 32500 200 2.6121364e-08 2.1e-06 0.0089858413 + 4e-06 32600 200 1.6302764e-08 2.1e-06 0.0089909376 + 4e-06 32700 200 9.4496486e-09 2.1e-06 0.008994902 + 4e-06 32800 200 4.3514823e-09 2.1e-06 0.0089977341 + 4e-06 32900 200 1.0546756e-09 2.1e-06 0.0089994335 + 4e-06 33000 200 7.3695568e-13 2.1e-06 0.009 +Loop time of 11.7961 on 1 procs for 14000 steps with 200 atoms -99.8% CPU use with 1 MPI tasks x no OpenMP threads +99.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.0020062 | 0.0020062 | 0.0020062 | 0.0 | 1.13 -Neigh | 0.00084671 | 0.00084671 | 0.00084671 | 0.0 | 0.48 -Comm | 0.00056289 | 0.00056289 | 0.00056289 | 0.0 | 0.32 -Output | 0.0010356 | 0.0010356 | 0.0010356 | 0.0 | 0.58 -Modify | 0.17178 | 0.17178 | 0.17178 | 0.0 | 96.63 -Other | | 0.001546 | | | 0.87 +Pair | 7.033 | 7.033 | 7.033 | 0.0 | 59.62 +Neigh | 0.047308 | 0.047308 | 0.047308 | 0.0 | 0.40 +Comm | 0.0020382 | 0.0020382 | 0.0020382 | 0.0 | 0.02 +Output | 0.0022072 | 0.0022072 | 0.0022072 | 0.0 | 0.02 +Modify | 4.7043 | 4.7043 | 4.7043 | 0.0 | 39.88 +Other | | 0.00727 | | | 0.06 -Nlocal: 10 ave 10 max 10 min +Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 3 ave 3 max 3 min +Neighs: 3145 ave 3145 max 3145 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 3 -Ave neighs/atom = 0.3 +Total # of neighbors = 3145 +Ave neighs/atom = 15.725 Neighbor list builds = 233 Dangerous builds not checked @@ -710,82 +710,82 @@ variable max_disp equal 0.004*0.75 run ${free_float_steps} run 5000 Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule -Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes +Per MPI rank memory allocation (min/avg/max) = 72.31 | 72.31 | 72.31 Mbytes Dt Step Atoms KinEng Volume v_disp_upper - 4e-06 33000 10 4.1931239e-07 2.1e-06 0.009 - 4e-06 33100 10 4.207474e-07 2.1e-06 0.009 - 4e-06 33200 10 4.2235525e-07 2.1e-06 0.009 - 4e-06 33300 10 4.2413593e-07 2.1e-06 0.009 - 4e-06 33400 10 4.2608946e-07 2.1e-06 0.009 - 4e-06 33500 10 4.2821583e-07 2.1e-06 0.009 - 4e-06 33600 10 4.3051504e-07 2.1e-06 0.009 - 4e-06 33700 10 4.3298709e-07 2.1e-06 0.009 - 4e-06 33800 10 4.3563197e-07 2.1e-06 0.009 - 4e-06 33900 10 4.384497e-07 2.1e-06 0.009 - 4e-06 34000 10 4.4144027e-07 2.1e-06 0.009 - 4e-06 34100 10 4.4460367e-07 2.1e-06 0.009 - 4e-06 34200 10 4.4793992e-07 2.1e-06 0.009 - 4e-06 34300 10 4.5144901e-07 2.1e-06 0.009 - 4e-06 34400 10 4.5465956e-07 2.1e-06 0.009 - 4e-06 34500 10 4.5470653e-07 2.1e-06 0.009 - 4e-06 34600 10 4.5236426e-07 2.1e-06 0.009 - 4e-06 34700 10 4.5019483e-07 2.1e-06 0.009 - 4e-06 34800 10 4.4819824e-07 2.1e-06 0.009 - 4e-06 34900 10 4.4590448e-07 2.1e-06 0.009 - 4e-06 35000 10 4.4154693e-07 2.1e-06 0.009 - 4e-06 35100 10 4.3736222e-07 2.1e-06 0.009 - 4e-06 35200 10 4.3335035e-07 2.1e-06 0.009 - 4e-06 35300 10 4.2951132e-07 2.1e-06 0.009 - 4e-06 35400 10 4.2584514e-07 2.1e-06 0.009 - 4e-06 35500 10 4.2235179e-07 2.1e-06 0.009 - 4e-06 35600 10 4.1903128e-07 2.1e-06 0.009 - 4e-06 35700 10 4.1034829e-07 2.1e-06 0.009 - 4e-06 35800 10 4.1153836e-07 2.1e-06 0.009 - 4e-06 35900 10 4.0720986e-07 2.1e-06 0.009 - 4e-06 36000 10 4.0259092e-07 2.1e-06 0.009 - 4e-06 36100 10 3.9607992e-07 2.1e-06 0.009 - 4e-06 36200 10 3.8974177e-07 2.1e-06 0.009 - 4e-06 36300 10 3.8357646e-07 2.1e-06 0.009 - 4e-06 36400 10 3.7758398e-07 2.1e-06 0.009 - 4e-06 36500 10 3.7176435e-07 2.1e-06 0.009 - 4e-06 36600 10 3.6611755e-07 2.1e-06 0.009 - 4e-06 36700 10 3.606436e-07 2.1e-06 0.009 - 4e-06 36800 10 3.5534248e-07 2.1e-06 0.009 - 4e-06 36900 10 3.5021421e-07 2.1e-06 0.009 - 4e-06 37000 10 3.4525877e-07 2.1e-06 0.009 - 4e-06 37100 10 3.4047618e-07 2.1e-06 0.009 - 4e-06 37200 10 3.3586643e-07 2.1e-06 0.009 - 4e-06 37300 10 3.3142951e-07 2.1e-06 0.009 - 4e-06 37400 10 3.0307307e-07 2.1e-06 0.009 - 4e-06 37500 10 3.208203e-07 2.1e-06 0.009 - 4e-06 37600 10 3.1480548e-07 2.1e-06 0.009 - 4e-06 37700 10 3.0896349e-07 2.1e-06 0.009 - 4e-06 37800 10 3.0329434e-07 2.1e-06 0.009 - 4e-06 37900 10 2.9779804e-07 2.1e-06 0.009 - 4e-06 38000 10 2.9247457e-07 2.1e-06 0.009 -Loop time of 0.0201013 on 1 procs for 5000 steps with 10 atoms + 4e-06 33000 200 7.3695568e-13 2.1e-06 0.009 + 4e-06 33100 200 1.0383246e-10 2.1e-06 0.009 + 4e-06 33200 200 5.9976193e-12 2.1e-06 0.009 + 4e-06 33300 200 6.2729949e-12 2.1e-06 0.009 + 4e-06 33400 200 9.0819715e-12 2.1e-06 0.009 + 4e-06 33500 200 4.1741245e-12 2.1e-06 0.009 + 4e-06 33600 200 4.2796157e-13 2.1e-06 0.009 + 4e-06 33700 200 1.2198973e-13 2.1e-06 0.009 + 4e-06 33800 200 5.0253099e-13 2.1e-06 0.009 + 4e-06 33900 200 3.2987112e-13 2.1e-06 0.009 + 4e-06 34000 200 9.8474325e-14 2.1e-06 0.009 + 4e-06 34100 200 2.0804908e-14 2.1e-06 0.009 + 4e-06 34200 200 3.5479858e-14 2.1e-06 0.009 + 4e-06 34300 200 4.6823841e-14 2.1e-06 0.009 + 4e-06 34400 200 2.8845396e-14 2.1e-06 0.009 + 4e-06 34500 200 2.4894095e-14 2.1e-06 0.009 + 4e-06 34600 200 2.4407576e-14 2.1e-06 0.009 + 4e-06 34700 200 2.4241607e-14 2.1e-06 0.009 + 4e-06 34800 200 2.5678797e-14 2.1e-06 0.009 + 4e-06 34900 200 3.0880003e-14 2.1e-06 0.009 + 4e-06 35000 200 3.3341003e-14 2.1e-06 0.009 + 4e-06 35100 200 1.5611246e-11 2.1e-06 0.009 + 4e-06 35200 200 8.7304571e-13 2.1e-06 0.009 + 4e-06 35300 200 1.28235e-13 2.1e-06 0.009 + 4e-06 35400 200 4.7975116e-13 2.1e-06 0.009 + 4e-06 35500 200 4.0667584e-13 2.1e-06 0.009 + 4e-06 35600 200 1.1230838e-13 2.1e-06 0.009 + 4e-06 35700 200 3.0578739e-14 2.1e-06 0.009 + 4e-06 35800 200 5.2724197e-14 2.1e-06 0.009 + 4e-06 35900 200 5.4930313e-14 2.1e-06 0.009 + 4e-06 36000 200 5.0413822e-14 2.1e-06 0.009 + 4e-06 36100 200 4.2936129e-14 2.1e-06 0.009 + 4e-06 36200 200 4.2946116e-14 2.1e-06 0.009 + 4e-06 36300 200 4.5163485e-14 2.1e-06 0.009 + 4e-06 36400 200 4.6640704e-14 2.1e-06 0.009 + 4e-06 36500 200 4.6581622e-14 2.1e-06 0.009 + 4e-06 36600 200 4.6319151e-14 2.1e-06 0.009 + 4e-06 36700 200 4.5444461e-14 2.1e-06 0.009 + 4e-06 36800 200 4.6152933e-14 2.1e-06 0.009 + 4e-06 36900 200 4.5660145e-14 2.1e-06 0.009 + 4e-06 37000 200 4.479585e-14 2.1e-06 0.009 + 4e-06 37100 200 4.454612e-14 2.1e-06 0.009 + 4e-06 37200 200 4.3595031e-14 2.1e-06 0.009 + 4e-06 37300 200 4.2650848e-14 2.1e-06 0.009 + 4e-06 37400 200 4.3124042e-14 2.1e-06 0.009 + 4e-06 37500 200 4.1053224e-14 2.1e-06 0.009 + 4e-06 37600 200 4.2786157e-14 2.1e-06 0.009 + 4e-06 37700 200 4.3961233e-14 2.1e-06 0.009 + 4e-06 37800 200 4.359215e-14 2.1e-06 0.009 + 4e-06 37900 200 4.3410766e-14 2.1e-06 0.009 + 4e-06 38000 200 3.9866697e-14 2.1e-06 0.009 +Loop time of 4.29106 on 1 procs for 5000 steps with 200 atoms -99.8% CPU use with 1 MPI tasks x no OpenMP threads +99.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.00055406 | 0.00055406 | 0.00055406 | 0.0 | 2.76 -Neigh | 0.00029074 | 0.00029074 | 0.00029074 | 0.0 | 1.45 -Comm | 0.00017063 | 0.00017063 | 0.00017063 | 0.0 | 0.85 -Output | 0.00023192 | 0.00023192 | 0.00023192 | 0.0 | 1.15 -Modify | 0.018306 | 0.018306 | 0.018306 | 0.0 | 91.07 -Other | | 0.000548 | | | 2.73 +Pair | 2.6156 | 2.6156 | 2.6156 | 0.0 | 60.95 +Neigh | 0.017028 | 0.017028 | 0.017028 | 0.0 | 0.40 +Comm | 0.00059632 | 0.00059632 | 0.00059632 | 0.0 | 0.01 +Output | 0.00055782 | 0.00055782 | 0.00055782 | 0.0 | 0.01 +Modify | 1.6547 | 1.6547 | 1.6547 | 0.0 | 38.56 +Other | | 0.002613 | | | 0.06 -Nlocal: 10 ave 10 max 10 min +Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 2 ave 2 max 2 min +Neighs: 3145 ave 3145 max 3145 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 2 -Ave neighs/atom = 0.2 +Total # of neighbors = 3145 +Ave neighs/atom = 15.725 Neighbor list builds = 83 Dangerous builds not checked -Total wall time: 0:00:00 +Total wall time: 0:00:26 diff --git a/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 index 8b9562d59f..eb49f732e8 100644 --- a/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 +++ b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 @@ -1,4 +1,4 @@ -LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-581-g384d7f446b-modified) +LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-583-g3d4b57d7fd-modified) ############################### SIMULATION SETTINGS ################################################### atom_style sphere 1 @@ -19,7 +19,7 @@ Reading data file ... 1 by 1 by 1 MPI processor grid reading atoms ... 12 atoms - read_data CPU = 0.002 seconds + read_data CPU = 0.003 seconds fix integr all nve/sphere # create pair group for contact area outputs @@ -193,9 +193,9 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 74.54 | 74.54 | 74.54 Mbytes Dt Step Atoms KinEng c_1 Volume 1e-06 0 12 0 0 8000 -Loop time of 1.135e-06 on 1 procs for 0 steps with 12 atoms +Loop time of 8.47e-07 on 1 procs for 0 steps with 12 atoms -88.1% CPU use with 1 MPI tasks x no OpenMP threads +0.0% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total @@ -205,7 +205,7 @@ Neigh | 0 | 0 | 0 | 0.0 | 0.00 Comm | 0 | 0 | 0 | 0.0 | 0.00 Output | 0 | 0 | 0 | 0.0 | 0.00 Modify | 0 | 0 | 0 | 0.0 | 0.00 -Other | | 1.135e-06 | | |100.00 +Other | | 8.47e-07 | | |100.00 Nlocal: 12 ave 12 max 12 min Histogram: 1 0 0 0 0 0 0 0 0 0 @@ -253,527 +253,528 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 75.17 | 75.17 | 75.17 Mbytes Dt Step Atoms KinEng c_1 Volume 1e-06 0 12 0 0 8000 - 1e-06 100 12 0.00013054111 0 8000 - 1e-06 200 12 0.013855547 0 8000 - 1e-06 300 12 0.14822185 0 8000 - 1e-06 400 12 0.73507149 0 8000 - 1e-06 500 12 2.4874475 0 8000 - 1e-06 600 12 6.7258963 0 8000 - 1e-06 700 12 15.636026 0 8000 - 1e-06 800 12 32.517811 0 8000 - 1e-06 900 12 62.020123 0 8000 - 1e-06 1000 12 110.35576 0 8000 - 1e-06 1100 12 185.492 0 8000 - 1e-06 1200 12 297.31164 0 8000 - 1e-06 1300 12 457.73953 0 8000 - 1e-06 1400 12 680.82988 0 8000 - 1e-06 1500 12 982.80999 0 8000 - 1e-06 1600 12 1382.0767 0 8000 - 1e-06 1700 12 1899.1422 0 8000 - 1e-06 1800 12 2556.5278 0 8000 - 1e-06 1900 12 3378.6026 0 8000 - 1e-06 2000 12 4391.3694 0 8000 - 1e-06 2100 12 5622.1967 0 8000 - 1e-06 2200 12 7099.4998 0 8000 - 1e-06 2300 12 8852.3743 0 8000 - 1e-06 2400 10 6989.9205 0 8000 - 1e-06 2500 10 8429.3452 0 8000 - 1e-06 2600 10 10069.898 0 8000 - 1e-06 2700 10 11924.3 0 8000 - 1e-06 2800 10 14004.078 0 8000 - 1e-06 2900 10 16319.307 0 8000 - 1e-06 3000 10 18878.365 0 8000 - 1e-06 3100 10 21687.702 0 8000 - 1e-06 3200 10 24751.634 0 8000 - 1e-06 3300 10 28072.177 0 8000 - 1e-06 3400 10 31649.069 0 8000 - 1e-06 3500 10 35479.937 0 8000 - 1e-06 3600 10 39560.508 0 8000 - 1e-06 3700 10 43884.837 0 8000 - 1e-06 3800 10 48445.544 0 8000 - 1e-06 3900 10 53234.048 0 8000 - 1e-06 4000 10 58240.786 0 8000 - 1e-06 4100 10 63455.398 0 8000 - 1e-06 4200 10 68866.878 0 8000 - 1e-06 4300 10 74463.666 0 8000 - 1e-06 4400 10 80233.692 0 8000 - 1e-06 4500 10 86164.354 0 8000 - 1e-06 4600 10 92242.435 0 8000 - 1e-06 4700 10 98453.963 0 8000 - 1e-06 4800 10 104784.03 0 8000 - 1e-06 4900 10 111216.58 0 8000 - 1e-06 5000 10 117734.15 0 8000 - 1e-06 5100 10 124317.68 0 8000 - 1e-06 5200 10 130946.27 0 8000 - 1e-06 5300 10 137597 0 8000 - 1e-06 5400 10 144244.91 0 8000 - 1e-06 5500 10 150862.88 0 8000 - 1e-06 5600 10 157421.78 0 8000 - 1e-06 5700 10 163890.67 0 8000 - 1e-06 5800 10 170237.02 0 8000 - 1e-06 5900 10 176427.24 0 8000 - 1e-06 6000 10 182427.1 0 8000 - 1e-06 6100 10 188202.4 0 8000 - 1e-06 6200 10 193719.65 0 8000 - 1e-06 6300 10 198946.82 0 8000 - 1e-06 6400 10 203854.11 0 8000 - 1e-06 6500 10 208414.76 0 8000 - 1e-06 6600 10 212605.82 0 8000 - 1e-06 6700 10 216408.93 0 8000 - 1e-06 6800 10 219811.02 0 8000 - 1e-06 6900 10 222804.99 0 8000 - 1e-06 7000 10 225390.45 0 8000 - 1e-06 7100 10 227574.39 0 8000 - 1e-06 7200 10 229372.23 0 8000 - 1e-06 7300 10 230809.43 0 8000 - 1e-06 7400 10 231925.78 0 8000 - 1e-06 7500 10 232793.77 0 8000 - 1e-06 7600 10 233468.99 0 8000 - 1e-06 7700 10 233964.52 1.1292815e-08 8000 - 1e-06 7800 10 234297.53 3.2638536e-06 8000 - 1e-06 7900 10 234490.97 4.5245711e-05 8000 - 1e-06 8000 10 234575.58 0.00027361033 8000 - 1e-06 8100 10 234598.71 0.001096929 8000 - 1e-06 8200 10 234623.44 0.0034192164 8000 - 1e-06 8300 10 234664.37 0.0089703149 8000 - 1e-06 8400 10 234728.48 0.020734818 8000 - 1e-06 8500 10 234824.44 0.043473962 8000 - 1e-06 8600 10 234962.62 0.084326224 8000 - 1e-06 8700 10 235155.17 0.15346362 8000 - 1e-06 8800 10 235415.94 0.26477255 8000 - 1e-06 8900 10 235760.43 0.43652067 8000 - 1e-06 9000 10 236205.62 0.69196571 8000 - 1e-06 9100 10 236769.75 1.0598579 8000 - 1e-06 9200 10 237472.3 1.5747862 8000 - 1e-06 9300 10 238334.06 2.2773199 8000 - 1e-06 9400 10 239377.46 3.2138993 8000 - 1e-06 9500 10 240626.63 4.4364369 8000 - 1e-06 9600 10 242107.53 6.0015993 8000 - 1e-06 9700 10 243847.86 7.9697503 8000 - 1e-06 9800 10 245876.93 10.403551 8000 - 1e-06 9900 10 248225.31 13.366224 8000 - 1e-06 10000 10 250924.44 16.919517 8000 - 1e-06 10100 8 234934.58 0 8000 - 1e-06 10200 8 235124.58 0 8000 - 1e-06 10300 8 235382.91 0 8000 - 1e-06 10400 8 235723.84 0 8000 - 1e-06 10500 8 236162.16 0 8000 - 1e-06 10600 8 236712.7 0 8000 - 1e-06 10700 8 237389.77 0 8000 - 1e-06 10800 8 238206.63 0 8000 - 1e-06 10900 8 239174.87 0 8000 - 1e-06 11000 8 240303.83 0 8000 - 1e-06 11100 8 241600.1 0 8000 - 1e-06 11200 8 243067 0 8000 - 1e-06 11300 8 244704.22 0 8000 - 1e-06 11400 8 246507.57 0 8000 - 1e-06 11500 8 248468.78 0 8000 - 1e-06 11600 8 250575.55 0 8000 - 1e-06 11700 8 252811.67 0 8000 - 1e-06 11800 6 201540.76 0 8000 - 1e-06 11900 6 203972.8 0 8000 - 1e-06 12000 6 206465.55 0 8000 - 1e-06 12100 6 208991.23 0 8000 - 1e-06 12200 6 211520.76 0 8000 - 1e-06 12300 6 214024.53 0 8000 - 1e-06 12400 6 216473.14 0 8000 - 1e-06 12500 6 218838.23 0 8000 - 1e-06 12600 6 221093.18 0 8000 - 1e-06 12700 6 223213.84 0 8000 - 1e-06 12800 6 225179.08 0 8000 - 1e-06 12900 6 226971.32 0 8000 - 1e-06 13000 6 228576.94 0 8000 - 1e-06 13100 6 229986.52 0 8000 - 1e-06 13200 6 231195.09 0 8000 - 1e-06 13300 6 232202.15 0 8000 - 1e-06 13400 6 233011.77 0 8000 - 1e-06 13500 6 233632.53 0 8000 - 1e-06 13600 6 234077.63 0 8000 - 1e-06 13700 6 234365.12 0 8000 - 1e-06 13800 6 234518.64 0 8000 - 1e-06 13900 6 234569.99 0 8000 - 1e-06 14000 6 234572.25 0 8000 - 1e-06 14100 6 234572.25 0 8000 - 1e-06 14200 6 234572.25 0 8000 - 1e-06 14300 6 234572.25 0 8000 - 1e-06 14400 6 234572.25 0 8000 - 1e-06 14500 6 234572.25 0 8000 - 1e-06 14600 6 234572.25 0 8000 - 1e-06 14700 6 234572.25 0 8000 - 1e-06 14800 6 234572.29 0 8000 - 1e-06 14900 6 234572.53 0 8000 - 1e-06 15000 6 234573.43 0 8000 - 1e-06 15100 6 234575.83 0 8000 - 1e-06 15200 6 234581.15 0 8000 - 1e-06 15300 6 234591.61 0 8000 - 1e-06 15400 6 234610.69 0 8000 - 1e-06 15500 6 234643.46 0 8000 - 1e-06 15600 6 234697 0 8000 - 1e-06 15700 6 234780.66 0 8000 - 1e-06 15800 6 234906.33 0 8000 - 1e-06 15900 6 235088.62 0 8000 - 1e-06 16000 6 235344.92 0 8000 - 1e-06 16100 6 235695.54 0 8000 - 1e-06 16200 6 236163.79 0 8000 - 1e-06 16300 6 236775.81 0 8000 - 1e-06 16400 6 237560.44 0 8000 - 1e-06 16500 6 238548.84 0 8000 - 1e-06 16600 6 239774.02 0 8000 - 1e-06 16700 6 241270.31 0 8000 - 1e-06 16800 6 243072.61 0 8000 - 1e-06 16900 6 245211.28 6.7509561e-05 8000 - 1e-06 17000 6 247685.18 0.0080448801 8000 - 1e-06 17100 6 250497.91 0.088500606 8000 - 1e-06 17200 6 253660.58 0.44413361 8000 - 1e-06 17300 6 257184.97 1.4994335 8000 - 1e-06 17400 6 261081.58 3.9820483 8000 - 1e-06 17500 6 265358.51 9.0005574 8000 - 1e-06 17600 6 270020.73 18.117195 8000 - 1e-06 17700 6 275069.6 33.413964 8000 - 1e-06 17800 6 280502.61 57.550525 8000 - 1e-06 17900 6 286303.62 93.814333 8000 - 1e-06 18000 6 292426.19 146.2099 8000 - 1e-06 18100 6 298823.02 219.66922 8000 - 1e-06 18200 6 305448.57 320.29091 8000 - 1e-06 18300 6 312257.06 455.50977 8000 - 1e-06 18400 6 319203.29 634.16436 8000 - 1e-06 18500 6 326243.62 866.44452 8000 - 1e-06 18600 6 333337.05 1163.7119 8000 - 1e-06 18700 6 340446.07 1538.1992 8000 - 1e-06 18800 6 347537.26 2002.6065 8000 - 1e-06 18900 6 354581.63 2569.6256 8000 - 1e-06 19000 6 361554.66 3251.4317 8000 - 1e-06 19100 6 368436.16 4059.1895 8000 - 1e-06 19200 6 375209.78 5002.6224 8000 - 1e-06 19300 6 381882.2 6109.6539 8000 - 1e-06 19400 6 388474.8 7416.2947 8000 - 1e-06 19500 6 395001.33 8944.9067 8000 - 1e-06 19600 6 401479.91 10717.67 8000 - 1e-06 19700 6 407931.4 12755.438 8000 - 1e-06 19800 6 414377.59 15076.566 8000 - 1e-06 19900 6 420839.43 17695.777 8000 - 1e-06 20000 6 427335.35 20623.111 8000 - 1e-06 20100 6 433879.62 23863.014 8000 - 1e-06 20200 6 440481.15 27413.577 8000 - 1e-06 20300 6 447142.48 31265.951 8000 - 1e-06 20400 6 453859.41 35403.784 8000 - 1e-06 20500 6 460622.17 39801.729 8000 - 1e-06 20600 6 467431.36 44452.106 8000 - 1e-06 20700 6 474330.29 49397.748 8000 - 1e-06 20800 6 481309.26 54624.638 8000 - 1e-06 20900 6 488358.84 60103.827 8000 - 1e-06 21000 6 495475.98 65790.173 8000 - 1e-06 21100 6 502655.34 71632.552 8000 - 1e-06 21200 6 509889.38 77576.424 8000 - 1e-06 21300 6 517172.66 83561.469 8000 - 1e-06 21400 6 524502.62 89522.951 8000 - 1e-06 21500 6 531876.86 95398.198 8000 - 1e-06 21600 6 539294.19 101129.04 8000 - 1e-06 21700 6 546755.8 106663.72 8000 - 1e-06 21800 6 554266.99 111958.45 8000 - 1e-06 21900 6 561839.98 116978.4 8000 - 1e-06 22000 6 569504.77 121698.15 8000 - 1e-06 22100 6 577194.68 126299.67 8000 - 1e-06 22200 6 584793.35 130939.81 8000 - 1e-06 22300 6 592287.59 135570.38 8000 - 1e-06 22400 6 599668.12 140143.02 8000 - 1e-06 22500 6 606930.15 144609.51 8000 - 1e-06 22600 6 614053.56 148921.72 8000 - 1e-06 22700 6 621008.46 153030.89 8000 - 1e-06 22800 6 627801.12 156883.57 8000 - 1e-06 22900 6 634468.16 160420.58 8000 - 1e-06 23000 6 640978.09 163613.12 8000 - 1e-06 23100 6 647287.63 166442.2 8000 - 1e-06 23200 6 653357.63 168893.16 8000 - 1e-06 23300 6 659133.28 170996.37 8000 - 1e-06 23400 6 664395.28 173122 8000 - 1e-06 23500 6 669082.71 175330.06 8000 - 1e-06 23600 6 673190.8 177582.02 8000 - 1e-06 23700 6 676722.56 179839.98 8000 - 1e-06 23800 6 679689.62 182067.03 8000 - 1e-06 23900 6 682113 184227.49 8000 - 1e-06 24000 6 684024.19 186286.94 8000 - 1e-06 24100 6 685466.31 188212.09 8000 - 1e-06 24200 6 686496.31 189970.05 8000 - 1e-06 24300 6 687194.14 191524.49 8000 - 1e-06 24400 6 687664.3 192834.65 8000 - 1e-06 24500 6 687952.12 193892.14 8000 - 1e-06 24600 6 688095.09 194698.81 8000 - 1e-06 24700 6 688136.6 195260.51 8000 - 1e-06 24800 6 688125.44 195586.96 8000 - 1e-06 24900 6 688096.3 195728.68 8000 - 1e-06 25000 6 687921.9 196064.13 8000 - 1e-06 25100 6 687620.45 196683.53 8000 - 1e-06 25200 6 687262.22 197578.87 8000 - 1e-06 25300 6 686921.27 198739.39 8000 - 1e-06 25400 6 686676.56 200150.16 8000 - 1e-06 25500 6 686616.59 201789.73 8000 - 1e-06 25600 6 686864.53 203620.41 8000 - 1e-06 25700 6 687515.07 205612.65 8000 - 1e-06 25800 6 688581.75 207765.95 8000 - 1e-06 25900 6 690068.86 210079.27 8000 - 1e-06 26000 6 691973.66 212549.89 8000 - 1e-06 26100 6 694286.34 215173.38 8000 - 1e-06 26200 6 696990.21 217943.63 8000 - 1e-06 26300 6 700062.02 220852.8 8000 - 1e-06 26400 6 703472.51 223891.43 8000 - 1e-06 26500 6 707187.07 227048.44 8000 - 1e-06 26600 6 711166.57 230311.27 8000 - 1e-06 26700 6 715368.28 233666 8000 - 1e-06 26800 6 719746.83 237097.44 8000 - 1e-06 26900 4 611074.01 219866.64 8000 - 1e-06 27000 4 613405.75 223401.9 8000 - 1e-06 27100 4 615906.25 226962.69 8000 - 1e-06 27200 4 618550.98 230530.7 8000 - 1e-06 27300 4 621314.15 234087.34 8000 - 1e-06 27400 4 624169.04 237613.98 8000 - 1e-06 27500 4 627088.41 241092.16 8000 - 1e-06 27600 4 630045.27 244503.29 8000 - 1e-06 27700 4 633017.68 247822.39 8000 - 1e-06 27800 4 635987.37 251019.87 8000 - 1e-06 27900 4 638936.67 254066.27 8000 - 1e-06 28000 4 641848.81 256932.77 8000 - 1e-06 28100 4 644708.19 259591.65 8000 - 1e-06 28200 4 647500.76 262016.69 8000 - 1e-06 28300 4 650214.19 264183.55 8000 - 1e-06 28400 4 652838.21 266070.17 8000 - 1e-06 28500 4 655364.7 267657.12 8000 - 1e-06 28600 4 657787.94 268927.87 8000 - 1e-06 28700 4 660104.66 269869.08 8000 - 1e-06 28800 4 662314.19 270470.82 8000 - 1e-06 28900 4 664418.47 270726.71 8000 - 1e-06 29000 4 666422.08 270634.03 8000 - 1e-06 29100 4 668332.27 270193.77 8000 - 1e-06 29200 4 670133.21 269455.46 8000 - 1e-06 29300 4 671623.88 268795.91 8000 - 1e-06 29400 4 672777.96 268288.08 8000 - 1e-06 29500 4 673622.53 267917.97 8000 - 1e-06 29600 4 674189.83 267670.08 8000 - 1e-06 29700 4 674518.57 267526.71 8000 - 1e-06 29800 4 674657.04 267466.37 8000 - 1e-06 29900 4 674676.17 267458.04 8000 - 1e-06 30000 4 674676.17 267458.04 8000 - 1e-06 30100 4 674676.17 267458.04 8000 - 1e-06 30200 2 304425.26 84084.197 8000 - 1e-06 30300 2 304425.26 84084.197 8000 - 1e-06 30400 2 304425.26 84084.197 8000 - 1e-06 30500 2 304425.26 84084.197 8000 - 1e-06 30600 2 304425.26 84084.197 8000 - 1e-06 30700 2 304425.26 84084.197 8000 - 1e-06 30800 2 304425.26 84084.197 8000 - 1e-06 30900 2 304425.26 84084.197 8000 - 1e-06 31000 2 304425.26 84084.197 8000 - 1e-06 31100 2 304425.26 84084.197 8000 - 1e-06 31200 2 304425.26 84084.197 8000 - 1e-06 31300 2 304425.26 84084.197 8000 - 1e-06 31400 2 304425.26 84084.197 8000 - 1e-06 31500 2 304425.26 84084.197 8000 - 1e-06 31600 2 304425.26 84084.197 8000 - 1e-06 31700 2 304425.26 84084.197 8000 - 1e-06 31800 2 304425.26 84084.197 8000 - 1e-06 31900 2 304425.26 84084.197 8000 - 1e-06 32000 2 304425.26 84084.197 8000 - 1e-06 32100 2 304425.26 84084.197 8000 - 1e-06 32200 2 304425.26 84084.197 8000 - 1e-06 32300 2 304425.26 84084.197 8000 - 1e-06 32400 2 304425.26 84084.197 8000 - 1e-06 32500 2 304425.26 84084.197 8000 - 1e-06 32600 2 304425.26 84084.197 8000 - 1e-06 32700 2 304425.26 84084.197 8000 - 1e-06 32800 2 304425.26 84084.197 8000 - 1e-06 32900 2 304425.26 84084.197 8000 - 1e-06 33000 2 304425.26 84084.197 8000 - 1e-06 33100 2 304425.26 84084.197 8000 - 1e-06 33200 2 304425.26 84084.197 8000 - 1e-06 33300 2 304425.26 84084.197 8000 - 1e-06 33400 2 304425.26 84084.197 8000 - 1e-06 33500 2 304425.26 84084.197 8000 - 1e-06 33600 2 304425.26 84084.197 8000 - 1e-06 33700 2 304425.26 84084.197 8000 - 1e-06 33800 2 304425.26 84084.197 8000 - 1e-06 33900 2 304425.26 84084.197 8000 - 1e-06 34000 2 304419.46 84084.197 8000 - 1e-06 34100 2 304377.55 84084.224 8000 - 1e-06 34200 2 304278.4 84084.45 8000 - 1e-06 34300 2 304108.46 84085.385 8000 - 1e-06 34400 2 303858.22 84088.048 8000 - 1e-06 34500 2 303521.62 84094.139 8000 - 1e-06 34600 2 303095.91 84106.182 8000 - 1e-06 34700 2 302581.78 84127.634 8000 - 1e-06 34800 2 301983.37 84162.962 8000 - 1e-06 34900 2 301308.35 84217.674 8000 - 1e-06 35000 2 300567.85 84298.29 8000 - 1e-06 35100 2 299776.31 84412.267 8000 - 1e-06 35200 2 298951.17 84567.862 8000 - 1e-06 35300 2 298112.52 84773.935 8000 - 1e-06 35400 2 297282.57 85039.703 8000 - 1e-06 35500 2 296485.02 85374.448 8000 - 1e-06 35600 2 295744.34 85787.18 8000 - 1e-06 35700 2 295085 86286.286 8000 - 1e-06 35800 2 294530.68 86879.159 8000 - 1e-06 35900 0 0 0 8000 - 1e-06 36000 0 0 0 8000 - 1e-06 36100 0 0 0 8000 - 1e-06 36200 0 0 0 8000 - 1e-06 36300 0 0 0 8000 - 1e-06 36400 0 0 0 8000 - 1e-06 36500 0 0 0 8000 - 1e-06 36600 0 0 0 8000 - 1e-06 36700 0 0 0 8000 - 1e-06 36800 0 0 0 8000 - 1e-06 36900 0 0 0 8000 - 1e-06 37000 0 0 0 8000 - 1e-06 37100 0 0 0 8000 - 1e-06 37200 0 0 0 8000 - 1e-06 37300 0 0 0 8000 - 1e-06 37400 0 0 0 8000 - 1e-06 37500 0 0 0 8000 - 1e-06 37600 0 0 0 8000 - 1e-06 37700 0 0 0 8000 - 1e-06 37800 0 0 0 8000 - 1e-06 37900 0 0 0 8000 - 1e-06 38000 0 0 0 8000 - 1e-06 38100 0 0 0 8000 - 1e-06 38200 0 0 0 8000 - 1e-06 38300 0 0 0 8000 - 1e-06 38400 0 0 0 8000 - 1e-06 38500 0 0 0 8000 - 1e-06 38600 0 0 0 8000 - 1e-06 38700 0 0 0 8000 - 1e-06 38800 0 0 0 8000 - 1e-06 38900 0 0 0 8000 - 1e-06 39000 0 0 0 8000 - 1e-06 39100 0 0 0 8000 - 1e-06 39200 0 0 0 8000 - 1e-06 39300 0 0 0 8000 - 1e-06 39400 0 0 0 8000 - 1e-06 39500 0 0 0 8000 - 1e-06 39600 0 0 0 8000 - 1e-06 39700 0 0 0 8000 - 1e-06 39800 0 0 0 8000 - 1e-06 39900 0 0 0 8000 - 1e-06 40000 0 0 0 8000 - 1e-06 40100 0 0 0 8000 - 1e-06 40200 0 0 0 8000 - 1e-06 40300 0 0 0 8000 - 1e-06 40400 0 0 0 8000 - 1e-06 40500 0 0 0 8000 - 1e-06 40600 0 0 0 8000 - 1e-06 40700 0 0 0 8000 - 1e-06 40800 0 0 0 8000 - 1e-06 40900 0 0 0 8000 - 1e-06 41000 0 0 0 8000 - 1e-06 41100 0 0 0 8000 - 1e-06 41200 0 0 0 8000 - 1e-06 41300 0 0 0 8000 - 1e-06 41400 0 0 0 8000 - 1e-06 41500 0 0 0 8000 - 1e-06 41600 0 0 0 8000 - 1e-06 41700 0 0 0 8000 - 1e-06 41800 0 0 0 8000 - 1e-06 41900 0 0 0 8000 - 1e-06 42000 0 0 0 8000 - 1e-06 42100 0 0 0 8000 - 1e-06 42200 0 0 0 8000 - 1e-06 42300 0 0 0 8000 - 1e-06 42400 0 0 0 8000 - 1e-06 42500 0 0 0 8000 - 1e-06 42600 0 0 0 8000 - 1e-06 42700 0 0 0 8000 - 1e-06 42800 0 0 0 8000 - 1e-06 42900 0 0 0 8000 - 1e-06 43000 0 0 0 8000 - 1e-06 43100 0 0 0 8000 - 1e-06 43200 0 0 0 8000 - 1e-06 43300 0 0 0 8000 - 1e-06 43400 0 0 0 8000 - 1e-06 43500 0 0 0 8000 - 1e-06 43600 0 0 0 8000 - 1e-06 43700 0 0 0 8000 - 1e-06 43800 0 0 0 8000 - 1e-06 43900 0 0 0 8000 - 1e-06 44000 0 0 0 8000 - 1e-06 44100 0 0 0 8000 - 1e-06 44200 0 0 0 8000 - 1e-06 44300 0 0 0 8000 - 1e-06 44400 0 0 0 8000 - 1e-06 44500 0 0 0 8000 - 1e-06 44600 0 0 0 8000 - 1e-06 44700 0 0 0 8000 - 1e-06 44800 0 0 0 8000 - 1e-06 44900 0 0 0 8000 - 1e-06 45000 0 0 0 8000 - 1e-06 45100 0 0 0 8000 - 1e-06 45200 0 0 0 8000 - 1e-06 45300 0 0 0 8000 - 1e-06 45400 0 0 0 8000 - 1e-06 45500 0 0 0 8000 - 1e-06 45600 0 0 0 8000 - 1e-06 45700 0 0 0 8000 - 1e-06 45800 0 0 0 8000 - 1e-06 45900 0 0 0 8000 - 1e-06 46000 0 0 0 8000 - 1e-06 46100 0 0 0 8000 - 1e-06 46200 0 0 0 8000 - 1e-06 46300 0 0 0 8000 - 1e-06 46400 0 0 0 8000 - 1e-06 46500 0 0 0 8000 - 1e-06 46600 0 0 0 8000 - 1e-06 46700 0 0 0 8000 - 1e-06 46800 0 0 0 8000 - 1e-06 46900 0 0 0 8000 - 1e-06 47000 0 0 0 8000 - 1e-06 47100 0 0 0 8000 - 1e-06 47200 0 0 0 8000 - 1e-06 47300 0 0 0 8000 - 1e-06 47400 0 0 0 8000 - 1e-06 47500 0 0 0 8000 - 1e-06 47600 0 0 0 8000 - 1e-06 47700 0 0 0 8000 - 1e-06 47800 0 0 0 8000 - 1e-06 47900 0 0 0 8000 - 1e-06 48000 0 0 0 8000 - 1e-06 48100 0 0 0 8000 - 1e-06 48200 0 0 0 8000 - 1e-06 48300 0 0 0 8000 - 1e-06 48400 0 0 0 8000 - 1e-06 48500 0 0 0 8000 - 1e-06 48600 0 0 0 8000 - 1e-06 48700 0 0 0 8000 - 1e-06 48800 0 0 0 8000 - 1e-06 48900 0 0 0 8000 - 1e-06 49000 0 0 0 8000 - 1e-06 49100 0 0 0 8000 - 1e-06 49200 0 0 0 8000 - 1e-06 49300 0 0 0 8000 - 1e-06 49400 0 0 0 8000 - 1e-06 49500 0 0 0 8000 - 1e-06 49600 0 0 0 8000 - 1e-06 49700 0 0 0 8000 - 1e-06 49800 0 0 0 8000 - 1e-06 49900 0 0 0 8000 -Loop time of 0.419125 on 1 procs for 49900 steps with 0 atoms + 1e-06 100 12 0.37627896 0 8000 + 1e-06 200 12 4.1791248 0 8000 + 1e-06 300 12 14.842751 0 8000 + 1e-06 400 12 36.772259 0 8000 + 1e-06 500 12 77.630616 0 8000 + 1e-06 600 12 145.73848 0 8000 + 1e-06 700 12 250.50491 0 8000 + 1e-06 800 12 402.70153 0 8000 + 1e-06 900 12 614.51551 0 8000 + 1e-06 1000 12 899.53232 0 8000 + 1e-06 1100 12 1272.6697 0 8000 + 1e-06 1200 12 1750.0701 0 8000 + 1e-06 1300 12 2348.9536 0 8000 + 1e-06 1400 12 3087.4362 0 8000 + 1e-06 1500 12 3984.3134 0 8000 + 1e-06 1600 12 5058.8155 0 8000 + 1e-06 1700 12 6330.3362 0 8000 + 1e-06 1800 12 7818.1411 0 8000 + 1e-06 1900 12 9541.0592 0 8000 + 1e-06 2000 12 11498.791 0.0047810266 8000 + 1e-06 2100 12 13704.573 0.10811492 8000 + 1e-06 2200 12 16174.974 0.63000368 8000 + 1e-06 2300 12 18921.112 2.1626376 8000 + 1e-06 2400 12 21953.925 5.2698517 8000 + 1e-06 2500 12 25281.497 10.484444 8000 + 1e-06 2600 12 28908.645 18.482248 8000 + 1e-06 2700 12 32837.664 30.036339 8000 + 1e-06 2800 12 37068.237 46.017479 8000 + 1e-06 2900 12 41597.382 67.391786 8000 + 1e-06 3000 12 46419.434 95.215596 8000 + 1e-06 3100 12 51526.06 130.62752 8000 + 1e-06 3200 12 56906.565 174.8377 8000 + 1e-06 3300 12 62550.059 229.11444 8000 + 1e-06 3400 12 68444.395 294.66357 8000 + 1e-06 3500 12 74576.632 372.08886 8000 + 1e-06 3600 12 80933.178 461.43595 8000 + 1e-06 3700 12 87499.829 562.23674 8000 + 1e-06 3800 12 94261.901 673.47838 8000 + 1e-06 3900 12 101204.31 793.60705 8000 + 1e-06 4000 12 108311.58 920.56829 8000 + 1e-06 4100 12 115567.86 1051.8828 8000 + 1e-06 4200 12 122956.81 1184.754 8000 + 1e-06 4300 12 130461.5 1316.2004 8000 + 1e-06 4400 12 138064.33 1443.2052 8000 + 1e-06 4500 12 145746.82 1562.8719 8000 + 1e-06 4600 12 153422.95 1670.3394 8000 + 1e-06 4700 12 161051.84 1763.0999 8000 + 1e-06 4800 12 168667.52 1842.4996 8000 + 1e-06 4900 12 176255.36 1908.409 8000 + 1e-06 5000 12 183795.82 1961.1714 8000 + 1e-06 5100 12 191266.94 2001.7002 8000 + 1e-06 5200 12 198645 2031.4642 8000 + 1e-06 5300 12 205905.03 2052.4189 8000 + 1e-06 5400 12 213021.06 2066.906 8000 + 1e-06 5500 12 219828.33 2076.3201 8000 + 1e-06 5600 12 226088.26 2080.385 8000 + 1e-06 5700 12 231986.18 2088.93 8000 + 1e-06 5800 12 237570.94 2108.0119 8000 + 1e-06 5900 12 242837.17 2141.5471 8000 + 1e-06 6000 12 247775.44 2192.6781 8000 + 1e-06 6100 12 252375.51 2263.7885 8000 + 1e-06 6200 12 256627.89 2356.5013 8000 + 1e-06 6300 12 260524.71 2471.6922 8000 + 1e-06 6400 12 264060.29 2609.528 8000 + 1e-06 6500 12 267231.53 2769.5274 8000 + 1e-06 6600 12 270038.2 2950.6395 8000 + 1e-06 6700 12 272483.11 3151.335 8000 + 1e-06 6800 12 274572.24 3369.7006 8000 + 1e-06 6900 12 276314.75 3603.531 8000 + 1e-06 7000 12 277722.99 3850.4128 8000 + 1e-06 7100 12 278812.52 4107.7948 8000 + 1e-06 7200 12 279602.05 4373.0439 8000 + 1e-06 7300 12 280113.55 4643.4856 8000 + 1e-06 7400 12 280372.7 4916.43 8000 + 1e-06 7500 12 280411.71 5189.1887 8000 + 1e-06 7600 12 280270.18 5459.0844 8000 + 1e-06 7700 12 279999.69 5723.4596 8000 + 1e-06 7800 12 279696.94 5979.6896 8000 + 1e-06 7900 12 279705.93 6225.2029 8000 + 1e-06 8000 12 279677 6457.5689 8000 + 1e-06 8100 12 279607.39 6683.3974 8000 + 1e-06 8200 12 279535.86 6906.911 8000 + 1e-06 8300 12 279515.96 7125.9155 8000 + 1e-06 8400 12 279726.3 7338.4626 8000 + 1e-06 8500 12 279905.61 7528.2253 8000 + 1e-06 8600 12 279994.55 7695.3391 8000 + 1e-06 8700 12 280109.97 7846.4954 8000 + 1e-06 8800 12 280280.9 7992.1243 8000 + 1e-06 8900 12 280526.73 8146.1487 8000 + 1e-06 9000 12 280875.16 8309.0778 8000 + 1e-06 9100 12 281361.17 8473.1301 8000 + 1e-06 9200 12 282015.74 8638.5101 8000 + 1e-06 9300 12 282868.61 8807.2007 8000 + 1e-06 9400 12 283949.43 8980.8606 8000 + 1e-06 9500 12 285287.01 9160.6973 8000 + 1e-06 9600 12 286908.48 9347.3851 8000 + 1e-06 9700 12 288808.95 9540.3891 8000 + 1e-06 9800 12 291008.88 9739.3515 8000 + 1e-06 9900 12 293533.31 9944.1548 8000 + 1e-06 10000 12 296392.46 10153.993 8000 + 1e-06 10100 12 299589.23 10366.149 8000 + 1e-06 10200 12 303120.5 10580.26 8000 + 1e-06 10300 12 306976.5 10797.104 8000 + 1e-06 10400 12 311140.59 11018.1 8000 + 1e-06 10500 12 315589.46 11245.316 8000 + 1e-06 10600 12 320293.56 11481.375 8000 + 1e-06 10700 12 325217.67 11729.284 8000 + 1e-06 10800 12 330321.65 11992.189 8000 + 1e-06 10900 12 335561.34 12273.086 8000 + 1e-06 11000 12 340889.49 12574.505 8000 + 1e-06 11100 12 346256.88 12898.214 8000 + 1e-06 11200 12 351613.36 13244.969 8000 + 1e-06 11300 12 356921.74 13613.584 8000 + 1e-06 11400 12 362263.57 14000.802 8000 + 1e-06 11500 12 367685.46 14407.905 8000 + 1e-06 11600 12 373173.46 14833.769 8000 + 1e-06 11700 12 378713.19 15276.703 8000 + 1e-06 11800 12 384258.42 15728.278 8000 + 1e-06 11900 12 389798.27 16183.88 8000 + 1e-06 12000 12 395067.85 16636.846 8000 + 1e-06 12100 12 400198.63 17088.171 8000 + 1e-06 12200 12 405211.55 17537.364 8000 + 1e-06 12300 12 410112.47 17984.343 8000 + 1e-06 12400 12 414906.33 18429.831 8000 + 1e-06 12500 12 419598.71 18875.613 8000 + 1e-06 12600 12 424192.44 19324.904 8000 + 1e-06 12700 12 428565.91 19783.784 8000 + 1e-06 12800 12 432825.92 20255.392 8000 + 1e-06 12900 12 437005.65 20738.975 8000 + 1e-06 13000 12 441133.84 21226.416 8000 + 1e-06 13100 12 445218.44 21720.281 8000 + 1e-06 13200 12 449263.02 22225.116 8000 + 1e-06 13300 12 453268.59 22746.27 8000 + 1e-06 13400 12 457229.62 23288.917 8000 + 1e-06 13500 12 461141.35 23859.236 8000 + 1e-06 13600 12 464999.54 24464.127 8000 + 1e-06 13700 12 468798.7 25110.47 8000 + 1e-06 13800 12 472500.62 25806.135 8000 + 1e-06 13900 12 476074.74 26564.004 8000 + 1e-06 14000 12 479545.35 27389.059 8000 + 1e-06 14100 12 482914.85 28284.54 8000 + 1e-06 14200 12 486185.47 29252.687 8000 + 1e-06 14300 12 489361.15 30294.757 8000 + 1e-06 14400 12 492273.69 31409.091 8000 + 1e-06 14500 12 494514.18 32573.659 8000 + 1e-06 14600 12 496511.76 33785.467 8000 + 1e-06 14700 12 498362.32 35051.794 8000 + 1e-06 14800 12 500126.95 36382.324 8000 + 1e-06 14900 12 501872.73 37788.434 8000 + 1e-06 15000 12 503658.95 39269.921 8000 + 1e-06 15100 12 505524.32 40815.737 8000 + 1e-06 15200 12 507507.74 42410.397 8000 + 1e-06 15300 12 509052.44 44020.642 8000 + 1e-06 15400 12 510424.85 45607.21 8000 + 1e-06 15500 12 511477.14 47150.907 8000 + 1e-06 15600 12 511930.85 48638.383 8000 + 1e-06 15700 12 512124.38 50030.203 8000 + 1e-06 15800 12 512194.05 51293.423 8000 + 1e-06 15900 12 512175.22 52402.955 8000 + 1e-06 16000 12 512095.42 53340.637 8000 + 1e-06 16100 12 511970.22 54097.278 8000 + 1e-06 16200 12 511797.58 54671.217 8000 + 1e-06 16300 12 511596.19 55067.665 8000 + 1e-06 16400 12 511390.31 55298.281 8000 + 1e-06 16500 12 511203.2 55383.204 8000 + 1e-06 16600 12 511056.43 55352.575 8000 + 1e-06 16700 12 510973.55 55240.989 8000 + 1e-06 16800 12 510979.82 55085.771 8000 + 1e-06 16900 12 511018.94 54944.912 8000 + 1e-06 17000 12 510839.23 54871.084 8000 + 1e-06 17100 12 510670.95 54882.14 8000 + 1e-06 17200 12 510592.26 55012.23 8000 + 1e-06 17300 12 510473.65 55293.657 8000 + 1e-06 17400 12 509821.33 55718.974 8000 + 1e-06 17500 12 508425.2 56251.107 8000 + 1e-06 17600 12 506922.69 56913.254 8000 + 1e-06 17700 12 505432.36 57751.093 8000 + 1e-06 17800 12 504007.07 58820.863 8000 + 1e-06 17900 12 502565.91 60215.42 8000 + 1e-06 18000 12 501138.89 61987.521 8000 + 1e-06 18100 12 499028.8 64137.707 8000 + 1e-06 18200 12 493241.81 66656.007 8000 + 1e-06 18300 12 486709.22 69522.002 8000 + 1e-06 18400 12 480004.21 72703.075 8000 + 1e-06 18500 12 473373.17 76162.035 8000 + 1e-06 18600 12 466967.02 79858.627 8000 + 1e-06 18700 12 460896.76 83749.858 8000 + 1e-06 18800 12 455246.73 87789.78 8000 + 1e-06 18900 12 450058.54 91935.918 8000 + 1e-06 19000 12 445381.99 96175.252 8000 + 1e-06 19100 12 441278.15 100523.08 8000 + 1e-06 19200 12 437763.14 104946.19 8000 + 1e-06 19300 12 434836.79 109405.67 8000 + 1e-06 19400 12 432488.77 113863.34 8000 + 1e-06 19500 12 430699.83 118281.43 8000 + 1e-06 19600 12 429442.98 122622.26 8000 + 1e-06 19700 12 428684.66 126847.95 8000 + 1e-06 19800 12 428328.48 130917.63 8000 + 1e-06 19900 12 428196.55 134775.59 8000 + 1e-06 20000 12 427597.88 138354.14 8000 + 1e-06 20100 12 425748.44 141440.79 8000 + 1e-06 20200 12 423827.82 143975.56 8000 + 1e-06 20300 12 422029.53 145951.68 8000 + 1e-06 20400 12 420416.81 147364.79 8000 + 1e-06 20500 12 419027.95 148273.8 8000 + 1e-06 20600 12 417858.85 148716.68 8000 + 1e-06 20700 12 416878.1 148666.56 8000 + 1e-06 20800 12 416057.47 148096.03 8000 + 1e-06 20900 12 415366.73 146981.92 8000 + 1e-06 21000 12 414775.28 145311.94 8000 + 1e-06 21100 12 414254.77 143086.56 8000 + 1e-06 21200 12 413734.06 140320.07 8000 + 1e-06 21300 12 412373.7 137040.42 8000 + 1e-06 21400 12 410695.21 133289.46 8000 + 1e-06 21500 12 408430.75 129131.69 8000 + 1e-06 21600 12 405927.7 124609.43 8000 + 1e-06 21700 12 403251.27 119786.82 8000 + 1e-06 21800 12 400435.71 114740.64 8000 + 1e-06 21900 12 397484.88 109586.68 8000 + 1e-06 22000 12 394308.48 104582.2 8000 + 1e-06 22100 12 390933.42 99878.117 8000 + 1e-06 22200 12 387369.16 95602.908 8000 + 1e-06 22300 12 383599.37 91871.749 8000 + 1e-06 22400 12 379598.34 88800.942 8000 + 1e-06 22500 12 375344.08 86475.879 8000 + 1e-06 22600 12 370860.89 84903.263 8000 + 1e-06 22700 12 366151.23 84105.325 8000 + 1e-06 22800 12 361209.31 84104.321 8000 + 1e-06 22900 12 356040.22 84897.625 8000 + 1e-06 23000 12 350662.58 86460.188 8000 + 1e-06 23100 12 345116.82 88752.422 8000 + 1e-06 23200 12 339495.95 91790.621 8000 + 1e-06 23300 12 333687.3 95431.883 8000 + 1e-06 23400 12 327700.18 99552.952 8000 + 1e-06 23500 12 321587.6 104041.28 8000 + 1e-06 23600 12 315413.29 108778.56 8000 + 1e-06 23700 12 309232.19 113641.68 8000 + 1e-06 23800 12 303140 118515.28 8000 + 1e-06 23900 12 297243.14 123286.42 8000 + 1e-06 24000 12 291647.45 127852.5 8000 + 1e-06 24100 12 286443.56 132128.25 8000 + 1e-06 24200 12 281738.47 136042.29 8000 + 1e-06 24300 12 277598.16 139537.18 8000 + 1e-06 24400 12 274126.59 142570.51 8000 + 1e-06 24500 12 271212.37 145112.95 8000 + 1e-06 24600 12 268528.37 147123.47 8000 + 1e-06 24700 12 266518.1 148576.54 8000 + 1e-06 24800 12 265271.22 149482.64 8000 + 1e-06 24900 12 264825.89 149868.7 8000 + 1e-06 25000 12 265195.27 149778.11 8000 + 1e-06 25100 12 266383.27 149277.13 8000 + 1e-06 25200 12 268349.03 148416.99 8000 + 1e-06 25300 12 270306.65 147210.83 8000 + 1e-06 25400 12 272540.67 145679.8 8000 + 1e-06 25500 12 275074.7 143905.2 8000 + 1e-06 25600 12 277868.98 141980.52 8000 + 1e-06 25700 12 280861.82 139998.04 8000 + 1e-06 25800 12 283988.43 138050.21 8000 + 1e-06 25900 12 287187.75 136227 8000 + 1e-06 26000 12 290378.71 134578.07 8000 + 1e-06 26100 12 293523.52 133120.1 8000 + 1e-06 26200 12 296607.69 131949.25 8000 + 1e-06 26300 12 299624.93 131155.87 8000 + 1e-06 26400 12 302615.41 130771.8 8000 + 1e-06 26500 12 305572.83 130791.04 8000 + 1e-06 26600 12 308487.65 131181.94 8000 + 1e-06 26700 12 311349.47 131876.78 8000 + 1e-06 26800 12 314152.42 132778.86 8000 + 1e-06 26900 12 316889.29 133767.68 8000 + 1e-06 27000 12 319555.95 134708.52 8000 + 1e-06 27100 12 322120.91 135461.05 8000 + 1e-06 27200 12 324555.84 135890.05 8000 + 1e-06 27300 12 326829.66 135875.78 8000 + 1e-06 27400 12 328889.23 135312.91 8000 + 1e-06 27500 12 330281.69 133716.24 8000 + 1e-06 27600 12 329638.28 131054.91 8000 + 1e-06 27700 12 328037.36 127321.07 8000 + 1e-06 27800 12 325917.33 122660.17 8000 + 1e-06 27900 12 323405.93 117289.76 8000 + 1e-06 28000 12 320546.78 111541.78 8000 + 1e-06 28100 12 317368.1 105721.12 8000 + 1e-06 28200 12 313916.1 100042.75 8000 + 1e-06 28300 12 310233.7 94704.867 8000 + 1e-06 28400 12 306354.19 89876.573 8000 + 1e-06 28500 12 302311.92 85693.914 8000 + 1e-06 28600 12 298136.83 82229.878 8000 + 1e-06 28700 12 293861.39 79475.257 8000 + 1e-06 28800 12 289522.82 77321.299 8000 + 1e-06 28900 12 285166.39 75606.038 8000 + 1e-06 29000 12 280832.9 74150.094 8000 + 1e-06 29100 12 276597.93 72751.053 8000 + 1e-06 29200 12 272488.85 71238.957 8000 + 1e-06 29300 12 268566.35 69513.495 8000 + 1e-06 29400 12 264945.51 67531.391 8000 + 1e-06 29500 12 261654.36 65280.325 8000 + 1e-06 29600 12 258609.63 62770.995 8000 + 1e-06 29700 12 255839.5 60094.223 8000 + 1e-06 29800 12 253400.35 57359.541 8000 + 1e-06 29900 12 251293.26 54686.718 8000 + 1e-06 30000 12 249489.3 52206.293 8000 + 1e-06 30100 12 247933.05 50046.862 8000 + 1e-06 30200 12 246671.31 48361.721 8000 + 1e-06 30300 12 245727.43 47234.492 8000 + 1e-06 30400 12 245089.53 46668.443 8000 + 1e-06 30500 12 244732.88 46634.46 8000 + 1e-06 30600 12 244634.04 47078.65 8000 + 1e-06 30700 12 244776.41 47932.487 8000 + 1e-06 30800 12 245144.95 49123.892 8000 + 1e-06 30900 12 245702.52 50587.15 8000 + 1e-06 31000 12 246438.58 52268.799 8000 + 1e-06 31100 12 247320.85 54174.572 8000 + 1e-06 31200 12 248299.92 56314.047 8000 + 1e-06 31300 12 249329.77 58655.775 8000 + 1e-06 31400 12 250368.76 61154.112 8000 + 1e-06 31500 12 251379.78 63756.764 8000 + 1e-06 31600 12 252311.71 66409.538 8000 + 1e-06 31700 12 252527.59 69055.013 8000 + 1e-06 31800 12 252438.03 71645.91 8000 + 1e-06 31900 12 252149.26 74149.007 8000 + 1e-06 32000 12 251697.31 76539.619 8000 + 1e-06 32100 12 251102.37 78801.8 8000 + 1e-06 32200 12 250377.5 80923.81 8000 + 1e-06 32300 12 249388.7 82875.3 8000 + 1e-06 32400 12 248054.75 84570.827 8000 + 1e-06 32500 12 246510.48 85977.951 8000 + 1e-06 32600 12 244788.85 87069.778 8000 + 1e-06 32700 12 242926.09 87820.435 8000 + 1e-06 32800 12 240951.82 88208.457 8000 + 1e-06 32900 12 238923.34 88216.633 8000 + 1e-06 33000 12 236972.84 87811.784 8000 + 1e-06 33100 12 235176.94 86991.249 8000 + 1e-06 33200 12 233594.14 85783.149 8000 + 1e-06 33300 12 232256.48 84231.2 8000 + 1e-06 33400 12 231063.68 82397.369 8000 + 1e-06 33500 12 229814.73 80366.279 8000 + 1e-06 33600 12 228715.08 78221.16 8000 + 1e-06 33700 12 227846.27 76046.828 8000 + 1e-06 33800 12 227241.85 73932.693 8000 + 1e-06 33900 12 226942.55 71944.948 8000 + 1e-06 34000 12 226979.34 70148.331 8000 + 1e-06 34100 12 227374.73 68624.913 8000 + 1e-06 34200 12 228140.68 67389 8000 + 1e-06 34300 12 229286.23 66436.221 8000 + 1e-06 34400 12 230818.8 65748.265 8000 + 1e-06 34500 12 232718.67 65274.126 8000 + 1e-06 34600 12 234956.45 64949.901 8000 + 1e-06 34700 12 237495.47 64705.586 8000 + 1e-06 34800 12 240298.79 64471.768 8000 + 1e-06 34900 12 243327.46 64186.278 8000 + 1e-06 35000 12 246540.11 63799.369 8000 + 1e-06 35100 12 249891.89 63272.741 8000 + 1e-06 35200 12 253331.8 62590.115 8000 + 1e-06 35300 12 256810.15 61755.192 8000 + 1e-06 35400 12 260282.81 60790.037 8000 + 1e-06 35500 12 263711.24 59733.295 8000 + 1e-06 35600 12 267063.76 58636.285 8000 + 1e-06 35700 12 270321.08 57558.359 8000 + 1e-06 35800 12 273471.7 56562.046 8000 + 1e-06 35900 12 276025.36 55655.191 8000 + 1e-06 36000 12 277671.27 54780.068 8000 + 1e-06 36100 12 278702.08 54044.977 8000 + 1e-06 36200 12 279135.29 53482.141 8000 + 1e-06 36300 12 278950.85 53096.328 8000 + 1e-06 36400 12 278091.84 52852.785 8000 + 1e-06 36500 12 276595.93 52726.318 8000 + 1e-06 36600 12 274484.66 52702.496 8000 + 1e-06 36700 12 271787.05 52743.065 8000 + 1e-06 36800 12 268570.57 52802.129 8000 + 1e-06 36900 12 264883.91 52837.56 8000 + 1e-06 37000 12 260770.78 52813.294 8000 + 1e-06 37100 12 256294.93 52703.248 8000 + 1e-06 37200 12 251520.81 52496.031 8000 + 1e-06 37300 12 246514.92 52198.643 8000 + 1e-06 37400 12 241336.35 51838.499 8000 + 1e-06 37500 12 236051.19 51466.475 8000 + 1e-06 37600 12 230530.99 51158.037 8000 + 1e-06 37700 12 224831.9 51005.878 8000 + 1e-06 37800 12 219195 51087.112 8000 + 1e-06 37900 12 213774.51 51464.55 8000 + 1e-06 38000 12 208719.8 52178.179 8000 + 1e-06 38100 12 204173.16 53238.452 8000 + 1e-06 38200 12 200268.52 54621.477 8000 + 1e-06 38300 12 197150.81 56266.704 8000 + 1e-06 38400 12 194900.92 58092.885 8000 + 1e-06 38500 12 193569.8 59999.47 8000 + 1e-06 38600 12 193173.44 61875.452 8000 + 1e-06 38700 12 193689.15 63611.808 8000 + 1e-06 38800 12 195056.93 65114.049 8000 + 1e-06 38900 12 197179.13 66310.945 8000 + 1e-06 39000 12 199964.06 67173.129 8000 + 1e-06 39100 12 203313.78 67704.561 8000 + 1e-06 39200 12 206537.34 67923.159 8000 + 1e-06 39300 12 209698.91 67870.023 8000 + 1e-06 39400 12 212990.74 67598.734 8000 + 1e-06 39500 12 216350.18 67172.426 8000 + 1e-06 39600 12 219678.83 66655.657 8000 + 1e-06 39700 12 222844.21 66084.261 8000 + 1e-06 39800 12 225879.54 65489.967 8000 + 1e-06 39900 12 228750 64901.658 8000 + 1e-06 40000 12 231432.52 64333.74 8000 + 1e-06 40100 12 233916.24 63787.895 8000 + 1e-06 40200 12 236200.24 63256.3 8000 + 1e-06 40300 12 238290.68 62725.161 8000 + 1e-06 40400 12 240198.17 62177.851 8000 + 1e-06 40500 12 241937.05 61597.51 8000 + 1e-06 40600 12 243521.73 60967.618 8000 + 1e-06 40700 12 244888.47 60271.31 8000 + 1e-06 40800 12 245447.64 59435.777 8000 + 1e-06 40900 12 245685.9 58426.609 8000 + 1e-06 41000 12 245713.15 57255.612 8000 + 1e-06 41100 12 245574.53 55939.057 8000 + 1e-06 41200 12 245295.74 54497.409 8000 + 1e-06 41300 12 244893.38 52955.91 8000 + 1e-06 41400 12 244382.52 51349.735 8000 + 1e-06 41500 12 243831.69 49814.42 8000 + 1e-06 41600 12 243254.37 48400.984 8000 + 1e-06 41700 12 242477.85 47069.283 8000 + 1e-06 41800 12 241513.72 45827.072 8000 + 1e-06 41900 12 239756.07 44524.57 8000 + 1e-06 42000 12 237373.8 43055.987 8000 + 1e-06 42100 12 234744.81 41643.015 8000 + 1e-06 42200 12 231931.52 40312.339 8000 + 1e-06 42300 12 228935.92 39072.939 8000 + 1e-06 42400 12 225746.23 37930.778 8000 + 1e-06 42500 12 222348.89 36895.022 8000 + 1e-06 42600 12 218698.5 35981.801 8000 + 1e-06 42700 12 214647.12 35216.043 8000 + 1e-06 42800 12 210245.47 34620.785 8000 + 1e-06 42900 12 205531.71 34205.699 8000 + 1e-06 43000 12 200578.63 33994.95 8000 + 1e-06 43100 12 195456.13 33986.177 8000 + 1e-06 43200 12 190228.82 34157.583 8000 + 1e-06 43300 12 184952.07 34469.117 8000 + 1e-06 43400 12 179670.45 34866.761 8000 + 1e-06 43500 12 174418.49 35289.81 8000 + 1e-06 43600 12 169223.1 35679.916 8000 + 1e-06 43700 12 164106.46 35990.914 8000 + 1e-06 43800 12 159087.52 36198.071 8000 + 1e-06 43900 12 154186.33 36296.826 8000 + 1e-06 44000 12 149426.96 36300.354 8000 + 1e-06 44100 12 144835.14 36235.093 8000 + 1e-06 44200 12 140411 36133.354 8000 + 1e-06 44300 12 136182.81 36025.46 8000 + 1e-06 44400 12 132191.02 35932.385 8000 + 1e-06 44500 12 128477.69 35860.362 8000 + 1e-06 44600 12 125084.47 35799.083 8000 + 1e-06 44700 12 122052.38 35722.674 8000 + 1e-06 44800 12 119423.36 35591.653 8000 + 1e-06 44900 12 117231.38 35361.568 8000 + 1e-06 45000 12 115498.71 34993.601 8000 + 1e-06 45100 12 114234.68 34464.293 8000 + 1e-06 45200 12 113435.12 33772.471 8000 + 1e-06 45300 12 113082.91 32941.872 8000 + 1e-06 45400 12 113268.89 32017.499 8000 + 1e-06 45500 12 114094.16 31061.868 8000 + 1e-06 45600 12 115590.36 30141.335 8000 + 1e-06 45700 12 117815.57 29316.931 8000 + 1e-06 45800 12 120811.47 28631.895 8000 + 1e-06 45900 12 124575.14 28113.464 8000 + 1e-06 46000 12 129078.74 27763.791 8000 + 1e-06 46100 12 134338.42 27558.943 8000 + 1e-06 46200 12 140371.84 27456.007 8000 + 1e-06 46300 12 147179.46 27401.261 8000 + 1e-06 46400 12 154720.12 27350.633 8000 + 1e-06 46500 12 162903.78 27280.725 8000 + 1e-06 46600 12 171569.61 27160.074 8000 + 1e-06 46700 12 180503.28 26959.29 8000 + 1e-06 46800 12 189437.05 26679.422 8000 + 1e-06 46900 12 198196.23 26336.443 8000 + 1e-06 47000 12 206520.98 25964.312 8000 + 1e-06 47100 12 214102.44 25606.132 8000 + 1e-06 47200 12 220554.38 25312.112 8000 + 1e-06 47300 12 225530.25 25128.211 8000 + 1e-06 47400 12 228814.64 25087.25 8000 + 1e-06 47500 12 230374.48 25204.456 8000 + 1e-06 47600 12 230169.61 25476.535 8000 + 1e-06 47700 12 228279.91 25884.284 8000 + 1e-06 47800 12 224903.35 26398.057 8000 + 1e-06 47900 12 220331.08 26984.898 8000 + 1e-06 48000 12 214896.98 27615.915 8000 + 1e-06 48100 12 208954.59 28272.416 8000 + 1e-06 48200 12 202876.52 28949.711 8000 + 1e-06 48300 12 197002.89 29657.821 8000 + 1e-06 48400 12 191715.64 30417.951 8000 + 1e-06 48500 12 187427.74 31259.165 8000 + 1e-06 48600 12 184340.37 32206.982 8000 + 1e-06 48700 12 182293.26 33278.236 8000 + 1e-06 48800 12 181185.81 34481.276 8000 + 1e-06 48900 12 181101.89 35801.056 8000 + 1e-06 49000 12 182147.18 37201.316 8000 + 1e-06 49100 12 184365.23 38617.38 8000 + 1e-06 49200 12 187357.35 39915.206 8000 + 1e-06 49300 12 190910.82 40926.844 8000 + 1e-06 49400 12 195007.02 41662.043 8000 + 1e-06 49500 12 199572.66 42126.903 8000 + 1e-06 49600 12 204382.72 42280.987 8000 + 1e-06 49700 12 209699.49 42088.752 8000 + 1e-06 49800 12 215597.68 41583.342 8000 + 1e-06 49900 12 222033.85 40867.693 8000 +Loop time of 1.45978 on 1 procs for 49900 steps with 12 atoms -99.7% CPU use with 1 MPI tasks x no OpenMP threads +99.5% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.015815 | 0.015815 | 0.015815 | 0.0 | 3.77 -Neigh | 1.795e-05 | 1.795e-05 | 1.795e-05 | 0.0 | 0.00 -Comm | 0.0015216 | 0.0015216 | 0.0015216 | 0.0 | 0.36 -Output | 0.0024194 | 0.0024194 | 0.0024194 | 0.0 | 0.58 -Modify | 0.3932 | 0.3932 | 0.3932 | 0.0 | 93.81 -Other | | 0.006155 | | | 1.47 +Pair | 0.34189 | 0.34189 | 0.34189 | 0.0 | 23.42 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0.0023579 | 0.0023579 | 0.0023579 | 0.0 | 0.16 +Output | 0.0038476 | 0.0038476 | 0.0038476 | 0.0 | 0.26 +Modify | 1.1002 | 1.1002 | 1.1002 | 0.0 | 75.37 +Other | | 0.01145 | | | 0.78 -Nlocal: 0 ave 0 max 0 min +Nlocal: 12 ave 12 max 12 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 0 ave 0 max 0 min +Neighs: 66 ave 66 max 66 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 0 -Neighbor list builds = 6 +Total # of neighbors = 66 +Ave neighs/atom = 5.5 +Neighbor list builds = 0 Dangerous builds = 0 -Total wall time: 0:00:00 +Total wall time: 0:00:01 diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 1c62c92c76..a171f70654 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -190,6 +190,8 @@ void GranSubModDampingMDR::init() { if (gm->normal_model->name != "mdr") error->all(FLERR, "Damping mdr can only be used with mdr normal model"); + + damp = gm->normal_model->get_damp(); } /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 5683f54fc2..9eb30e2a0e 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -807,10 +807,8 @@ double GranSubModNormalMDR::calculate_forces() F_MDR = calculate_nonadhesive_mdr_force(deltae1D, Ainv, Eeff, A, B); } - if (std::isnan(F_MDR)) { - printf("itag = %d, jtag = %d \n", itag_true, jtag_true); - error->one(FLERR, "F_MDR is NaN, case 1: no tensile springs"); - } + if (std::isnan(F_MDR)) + error->one(FLERR, "F_MDR is NaN, case 1: no tensile springs for atoms {} and {}", itag_true, jtag_true); if (history_update) *aAdh_offset = a_fac * a_na; } else { From e0847f2195c2a96efc66b01c26732595645ce140 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 00:26:20 -0400 Subject: [PATCH 045/396] fix memory leak in test --- unittest/force-styles/test_fix_timestep.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittest/force-styles/test_fix_timestep.cpp b/unittest/force-styles/test_fix_timestep.cpp index b952a3c045..d1bdee3535 100644 --- a/unittest/force-styles/test_fix_timestep.cpp +++ b/unittest/force-styles/test_fix_timestep.cpp @@ -446,10 +446,10 @@ TEST(FixTimestep, plain) !utils::strmatch(ifix->style, "^nve/limit") && !utils::strmatch(ifix->style, "^recenter")) { if (!verbose) ::testing::internal::CaptureStdout(); cleanup_lammps(lmp, test_config); + delete lmp; if (!verbose) ::testing::internal::GetCapturedStdout(); ::testing::internal::CaptureStdout(); - LAMMPS *lmp = nullptr; try { lmp = init_lammps(args, test_config, true); } catch (std::exception &e) { @@ -758,6 +758,7 @@ TEST(FixTimestep, omp) if (!verbose) ::testing::internal::CaptureStdout(); cleanup_lammps(lmp, test_config); + delete lmp; if (!verbose) ::testing::internal::GetCapturedStdout(); ::testing::internal::CaptureStdout(); From c60bff2b971b2499dfa2aaa2d49f73ce45b53911 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 00:53:28 -0400 Subject: [PATCH 046/396] reformat source --- src/lammps.cpp | 7 +++---- src/universe.cpp | 18 +++++++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/lammps.cpp b/src/lammps.cpp index 72a1b67fb2..d1b05aa279 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -528,8 +528,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : if (helpflag == 0) { universe->ulogfile = fopen("log.lammps","w"); if (universe->ulogfile == nullptr) - error->universe_warn(FLERR,"Cannot open log.lammps for writing: " - + utils::getsyserror()); + error->universe_warn(FLERR,"Cannot open log.lammps for writing: " + utils::getsyserror()); } } else if (strcmp(arg[logflag],"none") == 0) universe->ulogfile = nullptr; @@ -661,8 +660,8 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : } if ((me == 0) && (!helpflag)) - utils::logmesg(this,"LAMMPS ({}{})\nProcessor partition = {}\n", version, - update_string, universe->iworld); + utils::logmesg(this,"LAMMPS ({}{})\nProcessor partition = {}\n", version, update_string, + universe->iworld); } // check consistency of datatype settings in lmptype.h diff --git a/src/universe.cpp b/src/universe.cpp index fb07e26759..4daa83ef80 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -27,21 +27,18 @@ static constexpr int MAXLINE = 256; create & initialize the universe of processors in communicator ------------------------------------------------------------------------- */ -Universe::Universe(LAMMPS *lmp, MPI_Comm communicator) : Pointers(lmp) +Universe::Universe(LAMMPS *lmp, MPI_Comm communicator) : + Pointers(lmp), uscreen(stdout), ulogfile(nullptr), procs_per_world(nullptr), root_proc(nullptr), + uni2orig(nullptr) { uworld = uorig = communicator; - MPI_Comm_rank(uworld,&me); - MPI_Comm_size(uworld,&nprocs); - - uscreen = stdout; - ulogfile = nullptr; + MPI_Comm_rank(uworld, &me); + MPI_Comm_size(uworld, &nprocs); existflag = 0; nworlds = 0; - procs_per_world = nullptr; - root_proc = nullptr; - memory->create(uni2orig,nprocs,"universe:uni2orig"); + memory->create(uni2orig, nprocs, "universe:uni2orig"); for (int i = 0; i < nprocs; i++) uni2orig[i] = i; } @@ -89,8 +86,7 @@ void Universe::reorder(char *style, char *arg) if (me == 0) { FILE *fp = fopen(arg,"r"); if (fp == nullptr) - error->universe_one(FLERR,fmt::format("Cannot open -reorder " - "file {}: {}",arg, + error->universe_one(FLERR,fmt::format("Cannot open -reorder file {}: {}", arg, utils::getsyserror())); // skip header = blank and comment lines From 7c2ca8c8e523a1de63cd701c7f60fbb704537527 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 01:42:18 -0400 Subject: [PATCH 047/396] must not call plain ev_init() from KOKKOS without setting alloc to 0 to avoid memory leak --- src/KOKKOS/dynamical_matrix_kokkos.cpp | 2 +- src/KOKKOS/min_kokkos.cpp | 8 ++++---- src/KOKKOS/third_order_kokkos.cpp | 2 +- src/KOKKOS/verlet_kokkos.cpp | 10 ++++------ src/kspace.cpp | 4 ++-- src/kspace.h | 2 +- src/pair.cpp | 4 ++-- src/pair.h | 2 +- 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/KOKKOS/dynamical_matrix_kokkos.cpp b/src/KOKKOS/dynamical_matrix_kokkos.cpp index e4c454c7f2..d59bdc233d 100644 --- a/src/KOKKOS/dynamical_matrix_kokkos.cpp +++ b/src/KOKKOS/dynamical_matrix_kokkos.cpp @@ -118,7 +118,7 @@ void DynamicalMatrixKokkos::setup() force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); update->setupflag = 0; lmp->kokkos->auto_sync = 0; diff --git a/src/KOKKOS/min_kokkos.cpp b/src/KOKKOS/min_kokkos.cpp index fca7a16e62..4bd983221b 100644 --- a/src/KOKKOS/min_kokkos.cpp +++ b/src/KOKKOS/min_kokkos.cpp @@ -172,7 +172,7 @@ void MinKokkos::setup(int flag) force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -203,7 +203,7 @@ void MinKokkos::setup(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); @@ -281,7 +281,7 @@ void MinKokkos::setup_minimal(int flag) force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -312,7 +312,7 @@ void MinKokkos::setup_minimal(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); diff --git a/src/KOKKOS/third_order_kokkos.cpp b/src/KOKKOS/third_order_kokkos.cpp index 569a94a773..761165d99a 100644 --- a/src/KOKKOS/third_order_kokkos.cpp +++ b/src/KOKKOS/third_order_kokkos.cpp @@ -118,7 +118,7 @@ void ThirdOrderKokkos::setup() force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); update->setupflag = 0; lmp->kokkos->auto_sync = 0; diff --git a/src/KOKKOS/verlet_kokkos.cpp b/src/KOKKOS/verlet_kokkos.cpp index a492b5a9c9..b711d8108f 100644 --- a/src/KOKKOS/verlet_kokkos.cpp +++ b/src/KOKKOS/verlet_kokkos.cpp @@ -122,8 +122,7 @@ void VerletKokkos::setup(int flag) atomKK->sync(force->pair->execution_space,force->pair->datamask_read); force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); - } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + } else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -154,7 +153,7 @@ void VerletKokkos::setup(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); @@ -213,8 +212,7 @@ void VerletKokkos::setup_minimal(int flag) atomKK->sync(force->pair->execution_space,force->pair->datamask_read); force->pair->compute(eflag,vflag); atomKK->modified(force->pair->execution_space,force->pair->datamask_modify); - } - else if (force->pair) force->pair->compute_dummy(eflag,vflag); + } else if (force->pair) force->pair->compute_dummy(eflag,vflag,0); if (atom->molecular != Atom::ATOMIC) { if (force->bond) { @@ -245,7 +243,7 @@ void VerletKokkos::setup_minimal(int flag) atomKK->sync(force->kspace->execution_space,force->kspace->datamask_read); force->kspace->compute(eflag,vflag); atomKK->modified(force->kspace->execution_space,force->kspace->datamask_modify); - } else force->kspace->compute_dummy(eflag,vflag); + } else force->kspace->compute_dummy(eflag,vflag,0); } modify->setup_pre_reverse(eflag,vflag); diff --git a/src/kspace.cpp b/src/kspace.cpp index 2de25d6e86..8ab7a11eda 100644 --- a/src/kspace.cpp +++ b/src/kspace.cpp @@ -181,9 +181,9 @@ void KSpace::triclinic_check() /* ---------------------------------------------------------------------- */ -void KSpace::compute_dummy(int eflag, int vflag) +void KSpace::compute_dummy(int eflag, int vflag, int alloc) { - ev_init(eflag,vflag); + ev_init(eflag,vflag,alloc); } /* ---------------------------------------------------------------------- diff --git a/src/kspace.h b/src/kspace.h index 86e9a29bd2..0a3db05ee7 100644 --- a/src/kspace.h +++ b/src/kspace.h @@ -141,7 +141,7 @@ class KSpace : protected Pointers { void triclinic_check(); void modify_params(int, char **); void *extract(const char *); - void compute_dummy(int, int); + void compute_dummy(int eflag, int vflag, int alloc = 1); // triclinic diff --git a/src/pair.cpp b/src/pair.cpp index 52fea894df..896957c087 100644 --- a/src/pair.cpp +++ b/src/pair.cpp @@ -741,9 +741,9 @@ double Pair::mix_distance(double sig1, double sig2) /* ---------------------------------------------------------------------- */ -void Pair::compute_dummy(int eflag, int vflag) +void Pair::compute_dummy(int eflag, int vflag, int alloc) { - ev_init(eflag,vflag); + ev_init(eflag,vflag,alloc); } /* ---------------------------------------------------------------------- */ diff --git a/src/pair.h b/src/pair.h index ce9e189aa5..461d0c121b 100644 --- a/src/pair.h +++ b/src/pair.h @@ -140,7 +140,7 @@ class Pair : protected Pointers { void write_file(int, char **); void init_bitmap(double, double, int, int &, int &, int &, int &); virtual void modify_params(int, char **); - void compute_dummy(int, int); + void compute_dummy(int eflag, int vflag, int alloc = 1); // need to be public, so can be called by pair_style reaxc From 25f1dac9b6837200f03b2a31b581488597292260 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 01:42:44 -0400 Subject: [PATCH 048/396] more suppressions for MPICH and Kokkos --- tools/valgrind/Kokkos.supp | 14 +++++++++++- tools/valgrind/MPICH.supp | 47 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/tools/valgrind/Kokkos.supp b/tools/valgrind/Kokkos.supp index 720b7a3718..a9d62ce2e2 100644 --- a/tools/valgrind/Kokkos.supp +++ b/tools/valgrind/Kokkos.supp @@ -14,4 +14,16 @@ fun:_ZN9LAMMPS_NS9KokkosLMPC1EPNS_6LAMMPSEiPPc ... } - +{ + Kokkos_OpenMP_string1 + Memcheck:Leak + match-leak-kinds: reachable + fun:_ZnwmSt11align_val_tRKSt9nothrow_t + fun:_ZNK6Kokkos9HostSpace13impl_allocateEPKcmm28Kokkos_Profiling_SpaceHandle + fun:_ZNK6Kokkos9HostSpace8allocateEPKcmm + fun:_ZN6Kokkos4Impl14OpenMPInternal18resize_thread_dataEmmmm + fun:execute + ... + fun:operator() + ... +} diff --git a/tools/valgrind/MPICH.supp b/tools/valgrind/MPICH.supp index 80c6b66624..09a52472d9 100644 --- a/tools/valgrind/MPICH.supp +++ b/tools/valgrind/MPICH.supp @@ -138,6 +138,53 @@ fun:Run ... } +{ + MPICH_library2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:MPIDI_OFI_init_local + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... +} +{ + MPICH_library3 + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + ... + fun:MPID_Comm_commit_pre_hook + fun:MPID_Comm_commit_internal + fun:MPID_Comm_commit + fun:MPIR_init_comm_world + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... +} +{ + MPICH_library4 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:udev_new + ... + fun:hwloc_topology_load + ... + fun:PMPI_Init + fun:lammps_mpi_init + fun:lammps_mpi_init + fun:lammps_open + ... +} { MPICH_json1 Memcheck:Leak From 0bfa5b210bb1e31e51150e8e3d8dbc43ea568a11 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 15:42:04 -0400 Subject: [PATCH 049/396] plug memory leak --- src/compute_rdf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compute_rdf.cpp b/src/compute_rdf.cpp index c1e7dda2bb..9d7f4306d6 100644 --- a/src/compute_rdf.cpp +++ b/src/compute_rdf.cpp @@ -159,6 +159,7 @@ ComputeRDF::~ComputeRDF() delete[] ihi; delete[] jlo; delete[] jhi; + delete[] rev; memory->destroy(hist); memory->destroy(histall); memory->destroy(array); From 3fc0868db96336bf39c2598a377feed8da5e57b5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 15:48:10 -0400 Subject: [PATCH 050/396] enable and apply clang-format --- src/memory.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/memory.cpp b/src/memory.cpp index 84f052e447..c30b9933d4 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,4 +1,3 @@ -// clang-format off /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -62,7 +61,7 @@ void *Memory::smalloc(bigint nbytes, const char *name) void *ptr = malloc(nbytes); #endif if (ptr == nullptr) - error->one(FLERR,"Failed to allocate {} bytes for array {}", nbytes,name); + error->one(FLERR, Error::NOLASTLINE, "Failed to allocate {} bytes for array {}", nbytes, name); return ptr; } @@ -80,28 +79,28 @@ void *Memory::srealloc(void *ptr, bigint nbytes, const char *name) #if defined(LMP_USE_TBB_ALLOCATOR) ptr = scalable_aligned_realloc(ptr, nbytes, LAMMPS_MEMALIGN); #elif defined(LMP_INTEL_NO_TBB) && defined(LAMMPS_MEMALIGN) && \ - (defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER)) + (defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER)) ptr = realloc(ptr, nbytes); - uintptr_t offset = ((uintptr_t)(const void *)(ptr)) % LAMMPS_MEMALIGN; + uintptr_t offset = ((uintptr_t) (const void *) (ptr)) % LAMMPS_MEMALIGN; if (offset) { void *optr = ptr; ptr = smalloc(nbytes, name); #if defined(__APPLE__) - memcpy(ptr, optr, MIN(nbytes,malloc_size(optr))); + memcpy(ptr, optr, MIN(nbytes, malloc_size(optr))); #elif defined(_WIN32) || defined(__MINGW32__) - memcpy(ptr, optr, MIN(nbytes,_msize(optr))); + memcpy(ptr, optr, MIN(nbytes, _msize(optr))); #else - memcpy(ptr, optr, MIN(nbytes,malloc_usable_size(optr))); + memcpy(ptr, optr, MIN(nbytes, malloc_usable_size(optr))); #endif free(optr); } #else - ptr = realloc(ptr,nbytes); + ptr = realloc(ptr, nbytes); #endif if (ptr == nullptr) - error->one(FLERR,"Failed to reallocate {} bytes for array {}", - nbytes,name); + error->one(FLERR, Error::NOLASTLINE, "Failed to reallocate {} bytes for array {}", nbytes, + name); return ptr; } @@ -112,11 +111,11 @@ void *Memory::srealloc(void *ptr, bigint nbytes, const char *name) void Memory::sfree(void *ptr) { if (ptr == nullptr) return; - #if defined(LMP_USE_TBB_ALLOCATOR) +#if defined(LMP_USE_TBB_ALLOCATOR) scalable_aligned_free(ptr); - #else +#else free(ptr); - #endif +#endif } /* ---------------------------------------------------------------------- @@ -125,5 +124,6 @@ void Memory::sfree(void *ptr) void Memory::fail(const char *name) { - error->one(FLERR,"Cannot create/grow a vector/array of pointers for {}",name); + error->one(FLERR, Error::NOLASTLINE, "Cannot create/grow a vector/array of pointers for {}", + name); } From 0cc6fb8e18706ddd5c9303c65d6661e09eda95af Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 5 Apr 2025 16:33:40 -0400 Subject: [PATCH 051/396] fix acks2/reaxff/kk should use post_constructor() like base class for order of operations --- src/KOKKOS/fix_acks2_reaxff_kokkos.cpp | 19 +++++++++++++------ src/KOKKOS/fix_acks2_reaxff_kokkos.h | 3 ++- src/REAXFF/fix_acks2_reaxff.cpp | 15 ++++++++------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp b/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp index 5f82b778c1..2720b74578 100644 --- a/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp +++ b/src/KOKKOS/fix_acks2_reaxff_kokkos.cpp @@ -58,12 +58,6 @@ FixACKS2ReaxFFKokkos(LAMMPS *lmp, int narg, char **arg) : allocated_flag = 0; nprev = 4; - memory->destroy(s_hist); - memory->destroy(s_hist_X); - memory->destroy(s_hist_last); - grow_arrays(atom->nmax); - memoryKK->create_kokkos(k_s_hist_last,s_hist_last,2,nprev,"acks2/reax:s_hist_last"); - d_s_hist_last = k_s_hist_last.template view(); buf = new double[2*nprev]; prev_last_rows_rank = 0; @@ -87,6 +81,19 @@ FixACKS2ReaxFFKokkos::~FixACKS2ReaxFFKokkos() /* ---------------------------------------------------------------------- */ +template +void FixACKS2ReaxFFKokkos::post_constructor() +{ + memory->destroy(s_hist); + grow_arrays(atom->nmax); + memoryKK->create_kokkos(k_s_hist_last,s_hist_last,2,nprev,"acks2/reax:s_hist_last"); + d_s_hist_last = k_s_hist_last.template view(); + + pertype_parameters(pertype_option); +} + +/* ---------------------------------------------------------------------- */ + template void FixACKS2ReaxFFKokkos::init() { diff --git a/src/KOKKOS/fix_acks2_reaxff_kokkos.h b/src/KOKKOS/fix_acks2_reaxff_kokkos.h index d3e4dff53c..afae47816c 100644 --- a/src/KOKKOS/fix_acks2_reaxff_kokkos.h +++ b/src/KOKKOS/fix_acks2_reaxff_kokkos.h @@ -64,8 +64,9 @@ class FixACKS2ReaxFFKokkos : public FixACKS2ReaxFF, public KokkosBase { typedef double value_type; typedef ArrayTypes AT; FixACKS2ReaxFFKokkos(class LAMMPS *, int, char **); - ~FixACKS2ReaxFFKokkos(); + ~FixACKS2ReaxFFKokkos() override; + void post_constructor() override; void init() override; void setup_pre_force(int) override; void pre_force(int) override; diff --git a/src/REAXFF/fix_acks2_reaxff.cpp b/src/REAXFF/fix_acks2_reaxff.cpp index 4fd86605fa..2692d7eeca 100644 --- a/src/REAXFF/fix_acks2_reaxff.cpp +++ b/src/REAXFF/fix_acks2_reaxff.cpp @@ -80,6 +80,11 @@ FixACKS2ReaxFF::FixACKS2ReaxFF(LAMMPS *lmp, int narg, char **arg) : last_rows_rank = 0; last_rows_flag = (comm->me == last_rows_rank); + + if (lmp->citeme) lmp->citeme->add(cite_fix_acks2_reax); + + if (dual_enabled) + error->all(FLERR, Error::NOLASTLINE, "Dual keyword only supported with fix qeq/reax/omp"); } /* ---------------------------------------------------------------------- */ @@ -104,8 +109,6 @@ FixACKS2ReaxFF::~FixACKS2ReaxFF() void FixACKS2ReaxFF::post_constructor() { - if (lmp->citeme) lmp->citeme->add(cite_fix_acks2_reax); - memory->create(s_hist_last,2,nprev,"acks2/reax:s_hist_last"); for (int i = 0; i < 2; i++) for (int j = 0; j < nprev; ++j) @@ -117,8 +120,6 @@ void FixACKS2ReaxFF::post_constructor() s_hist[i][j] = s_hist_X[i][j] = 0.0; pertype_parameters(pertype_option); - if (dual_enabled) - error->all(FLERR,"Dual keyword only supported with fix qeq/reax/omp"); } /* ---------------------------------------------------------------------- */ @@ -128,7 +129,7 @@ void FixACKS2ReaxFF::pertype_parameters(char *arg) if (utils::strmatch(arg,"^reaxff")) { reaxflag = 1; Pair *pair = force->pair_match("^reaxff",0); - if (!pair) error->all(FLERR,"No reaxff pair style for fix acks2/reaxff"); + if (!pair) error->all(FLERR, Error::NOLASTLINE, "No reaxff pair style for fix acks2/reaxff"); int tmp; chi = (double *) pair->extract("chi",tmp); @@ -139,8 +140,8 @@ void FixACKS2ReaxFF::pertype_parameters(char *arg) if (chi == nullptr || eta == nullptr || gamma == nullptr || bcut_acks2 == nullptr || bond_softness_ptr == nullptr) - error->all(FLERR, - "Fix acks2/reaxff could not extract params from pair reaxff"); + error->all(FLERR, Error::NOLASTLINE, "Fix {} could not extract params from pair reaxff", + style); bond_softness = *bond_softness_ptr; return; } From 8d5459393fc72a83f03d70cee07309f3318964ac Mon Sep 17 00:00:00 2001 From: Germain Clavier Date: Sat, 5 Apr 2025 23:32:36 +0200 Subject: [PATCH 052/396] Added the plot_forces file from previous PR --- tools/python/plot_forces.py | 277 ++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 tools/python/plot_forces.py diff --git a/tools/python/plot_forces.py b/tools/python/plot_forces.py new file mode 100644 index 0000000000..583f3ae6ed --- /dev/null +++ b/tools/python/plot_forces.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Author: Germain Clavier (Unicaen), germain.clavier at unicaen.fr + +""" +Plot LAMMPS tabulated forces. +""" + +import argparse +import numpy as np +import os +import logging +import sys +from matplotlib import pyplot as plt + +logger = logging.getLogger(__name__) + + +units = { + "lj": { + "Distance": "Reduced units", + "Energy": "Reduced units", + "Force": "Reduced units", + "kb": 1, + }, + "real": { + "Distance": "[A]", + "Energy": "[kcal/mol]", + "Force": "[kcal/mol/A]", + "kb": 0.001985875, + }, + "metal": { + "Distance": "[A]", + "Energy": "[eV]", + "Force": "[eV/A]", + "kb": 8.6173332e-5, + }, + "si": {"Distance": "[m]", "Energy": "[J]", "Force": "[N]", "kb": 1.380649e-23}, + "cgs": { + "Distance": "[cm]", + "Energy": "[ergs]", + "Force": "[dynes]", + "kb": 1.3806504e-16, + }, + "electron": { + "Distance": "[Bohr]", + "Energy": "[Hartrees]", + "Force": "[Hartree/Bohr]", + "kb": 3.16681534e-6, + }, + "micro": { + "Distance": "[um]", + "Energy": "[pg·um^2/us^2]", + "Force": "[pg·um/us^2]", + "kb": 1.3806504e-8, + }, + "nano": { + "Distance": "[nm]", + "Energy": "[ag·nm^2/ns^2]", + "Force": "[ag·nm/ns^2]", + "kb": 0.013806504, + }, +} + + +def compute_energy(tp): + r = tp[0] + fo = tp[2] + e = np.zeros(r.shape) + for i, (ri, fi) in enumerate(zip(r, fo)): + if i == 0: + continue + dr = ri - r[i - 1] + e[i] = e[i - 1] - dr * fo[i - 1] + e -= e[-1] + return e + + +def main(): + + parser = argparse.ArgumentParser( + description=""" + Plots LAMMPS tabulated forces. This script takes a table + file as an input and plots all the tabulated forces inside with their + corresponding energy. The forces label is the token used to name the + force in the file. It can be used to output all the forces in separate + files and/or recompute the energy from forces through finite difference + (assuming e(rc)=0). This script requires the matplotlib and numpy + Python libraries. Bitmap format is not supported. + """ + ) + parser.add_argument( + "-u", + "--units", + dest="units", + default="real", + help="Units of the file (LAMMPS units system)", + ) + parser.add_argument( + "-f", + "--file", + dest="infile", + default="", + help="File to read", + ) + parser.add_argument( + "-x", + dest="xrange", + default="", + help="xrange separated by : (for negative values use the '=' sign: -x=-3:10)", + ) + parser.add_argument( + "-y", + dest="yrange", + default="", + help="yrange separated by :", + ) + parser.add_argument( + "-t", + dest="temp", + default=None, + type=float, + help="temperature for KbT plot [default none]", + ) + parser.add_argument( + "--recompute-energy", + dest="recompute", + action="store_true", + help="Recompute the energies from forces and distances through finite differences", + ) + parser.add_argument( + "-e", + dest="extract", + action="store_true", + help="Extract the forces in separate files", + ) + args = parser.parse_args() + logging.basicConfig(level=logging.INFO) + + ########## + # Manage arguments + + udistance = units[args.units]["Distance"] + uenergy = units[args.units]["Energy"] + uforce = units[args.units]["Force"] + kb = units[args.units]["kb"] + rlabel = " ".join(["Rij", udistance]) + elabel = " ".join(["E", uenergy]) + flabel = " ".join(["F", uforce]) + etitle = "Energy" + ftitle = "Force" + font = "DejaVu Sans" + fontsize = 30 + + infile = args.infile + if not os.path.isfile(infile): + logger.error("Input file not found") + sys.exit(1) + + toplot = [] + with open(infile, "r") as f: + lines = iter(f.readlines()) + while True: + try: + r = [] + force = [] + ener = [] + tok = [] + while not tok: + tok = next(lines).partition("#")[0].rstrip() + logger.info("Found {} token".format(tok)) + infos = next(lines).split() + npoints = int(infos[1]) + next(lines) + if "bitmap" in infos: + logger.info("Unsupported bitmap format for token {:s}".format(tok)) + for _ in range(npoints): + continue + else: + for i in range(npoints): + line = next(lines).split() + r.append(float(line[1])) + ener.append(float(line[2])) + force.append(float(line[3])) + r = np.array(r) + ener = np.array(ener) + force = np.array(force) + toplot.append([r, ener, force, tok]) + tok = [] + next(lines) + except StopIteration: + break + if args.recompute: + etitle = "Estimated energy" + for tp in toplot: + tp[1] = compute_energy(tp) + + fig, axes = plt.subplots(1, 2) + + for tp in toplot: + axes[0].plot(tp[0], tp[1], label=tp[3], linewidth=3) + axes[1].plot(tp[0], tp[2], label=tp[3], linewidth=3) + hmin, hmax = axes[1].get_xlim() + axes[1].hlines(0, hmin, hmax, color="black", linewidth=3, linestyles="dashdot") + + if args.temp: + if args.temp > 0: + hmin, hmax = axes[0].get_xlim() + axes[0].hlines( + kb * args.temp, + hmin, + hmax, + color="orange", + label=r"$k_BT$", + linewidth=3, + linestyles="dashdot", + ) + axes[0].text(hmax / 2.0, kb * args.temp, "KbT", fontsize=0.7 * fontsize) + logger.info("KbT value= {:e} {:s}".format(kb * args.temp, uenergy)) + else: + logger.info("Invalid temperature value: {:e}".format(args.temp)) + + if args.xrange: + xmin, xmax = list(map(float, args.xrange.split(":"))) + axes[0].set_xlim(xmin, xmax) + axes[1].set_xlim(xmin, xmax) + if args.yrange: + ymin, ymax = list(map(float, args.yrange.split(":"))) + axes[0].set_ylim(ymin, ymax) + axes[1].set_ylim(ymin, ymax) + + # Setting axes 0 + axes[0].set_title(etitle, fontsize=fontsize) + axes[0].set_xlabel( + rlabel, fontname=font, fontsize=fontsize + ) # xlabel name, size 30pts + axes[0].set_ylabel( + elabel, fontname=font, fontsize=fontsize + ) # ylabel name, size 30pts + axes[0].tick_params( + axis="both", which="major", labelsize=fontsize + ) # Biggers ticks, bigger tick labels! + + # Setting axes 1 + axes[1].set_title(ftitle, fontsize=fontsize) + axes[1].legend(frameon=False, fontsize=fontsize) # Fat font, no frame + axes[1].set_xlabel( + rlabel, fontname=font, fontsize=fontsize + ) + axes[1].set_ylabel( + flabel, fontname=font, fontsize=fontsize + ) + axes[1].tick_params( + axis="both", which="major", labelsize=fontsize + ) + + figManager = plt.get_current_fig_manager() + figManager.window.showMaximized() + plt.show() + + if args.extract: + for tp in toplot: + outfile = "".join([tp[3], ".plot"]) + logger.info("Writing file {}".format(outfile)) + with open(outfile, "w") as f: + f.write("# {} force extracted from {}\n".format(tp[3], infile)) + f.write("# {:^20} {:^20} {:^20}\n".format("r", "energy", "force")) + for a, b, c in zip(tp[0], tp[1], tp[2]): + f.write("{:>18.16e} {:>18.16e} {:>18.16e}\n".format(a, b, c)) + return + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + raise SystemExit("User interruption.") From 860a3cbbd308e7f201281abdae0941733fb9ff98 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 03:02:34 -0400 Subject: [PATCH 053/396] add suppressions for dlopen() and friends --- tools/valgrind/README | 26 ++++++++------- tools/valgrind/libc.supp | 69 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 tools/valgrind/libc.supp diff --git a/tools/valgrind/README b/tools/valgrind/README index 277b1dfd1f..77479d52d3 100644 --- a/tools/valgrind/README +++ b/tools/valgrind/README @@ -6,14 +6,15 @@ when running "ctest -T memcheck". To manually add them to do a memory check on running LAMMPS, use a command line like following: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ - --suppressions=/path/to/lammps/tools/valgrind/OpenMP.supp \ - --suppressions=/path/to/lammps/tools/valgrind/OpenMPI.supp \ - --suppressions=/path/to/lammps/tools/valgrind/MPICH.supp \ - --suppressions=/path/to/lammps/tools/valgrind/LLVM.supp \ - --suppressions=/path/to/lammps/tools/valgrind/Python3.supp \ + --suppressions=/path/to/lammps/tools/valgrind/FlexiBLAS.supp \ --suppressions=/path/to/lammps/tools/valgrind/GTest.supp \ --suppressions=/path/to/lammps/tools/valgrind/Kokkos.supp \ - --suppressions=/path/to/lammps/tools/valgrind/FlexiBLAS.supp \ + --suppressions=/path/to/lammps/tools/valgrind/LLVM.supp \ + --suppressions=/path/to/lammps/tools/valgrind/MPICH.supp \ + --suppressions=/path/to/lammps/tools/valgrind/OpenMP.supp \ + --suppressions=/path/to/lammps/tools/valgrind/OpenMPI.supp \ + --suppressions=/path/to/lammps/tools/valgrind/Python3.supp \ + --suppressions=/path/to/lammps/tools/valgrind/libc.supp \ --suppressions=/path/to/lammps/tools/valgrind/readline.supp \ lmp -in in.melt @@ -22,15 +23,16 @@ Or you can create a file $HOME/.valgrindrc with one option per line: --leak-check=full --show-leak-kinds=all --track-origins=yes ---suppressions=/path/to/lammps/tools/valgrind/OpenMP.supp ---suppressions=/path/to/lammps/tools/valgrind/OpenMPI.supp ---suppressions=/path/to/lammps/tools/valgrind/MPICH.supp ---suppressions=/path/to/lammps/tools/valgrind/LLVM.supp +--suppressions=/path/to/lammps/tools/valgrind/FlexiBLAS.supp --suppressions=/path/to/lammps/tools/valgrind/GTest.supp --suppressions=/path/to/lammps/tools/valgrind/Kokkos.supp ---suppressions=/path/to/lammps/tools/valgrind/FlexiBLAS.supp ---suppressions=/path/to/lammps/tools/valgrind/readline.supp +--suppressions=/path/to/lammps/tools/valgrind/LLVM.supp +--suppressions=/path/to/lammps/tools/valgrind/MPICH.supp +--suppressions=/path/to/lammps/tools/valgrind/OpenMP.supp +--suppressions=/path/to/lammps/tools/valgrind/OpenMPI.supp --suppressions=/path/to/lammps/tools/valgrind/Python3.supp +--suppressions=/path/to/lammps/tools/valgrind/libc.supp +--suppressions=/path/to/lammps/tools/valgrind/readline.supp These options will be automatically added to the valgrind command line, so it becomes: valgrind lmp -in in.melt diff --git a/tools/valgrind/libc.supp b/tools/valgrind/libc.supp new file mode 100644 index 0000000000..2b90fd3f1f --- /dev/null +++ b/tools/valgrind/libc.supp @@ -0,0 +1,69 @@ +{ + libc_dlopen1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:malloc + fun:strdup + fun:_dl_load_cache_lookup + fun:_dl_map_object + fun:dl_open_worker_begin + fun:_dl_catch_exception + fun:dl_open_worker + fun:_dl_catch_exception + fun:_dl_open + fun:do_dlopen + fun:_dl_catch_exception + fun:_dl_catch_error +} +{ + libc_dlopen2 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object + fun:dl_open_worker_begin + fun:_dl_catch_exception + fun:dl_open_worker + fun:_dl_catch_exception + fun:_dl_open + fun:do_dlopen + fun:_dl_catch_exception + fun:_dl_catch_error +} +{ + libc_dlopen3 + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + fun:* + fun:_dl_check_map_versions + fun:dl_open_worker_begin + fun:_dl_catch_exception + fun:dl_open_worker + fun:_dl_catch_exception + fun:_dl_open + fun:do_dlopen + ... +} +{ + libc_dlopen4 + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object + fun:dl_open_worker_begin + fun:_dl_catch_exception + fun:dl_open_worker + fun:_dl_catch_exception + fun:_dl_open + fun:do_dlopen + fun:_dl_catch_exception + fun:_dl_catch_error +} From 2eaf1e52f0396c0fde14855161def1dd2973ef26 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 03:49:11 -0400 Subject: [PATCH 054/396] add even more suppressions and generalize some --- tools/valgrind/MPICH.supp | 80 ++++++------------ tools/valgrind/Python3.supp | 162 ++++++++++++++++++++++++++++++++++++ tools/valgrind/libc.supp | 13 +++ 3 files changed, 201 insertions(+), 54 deletions(-) diff --git a/tools/valgrind/MPICH.supp b/tools/valgrind/MPICH.supp index 09a52472d9..01681974ac 100644 --- a/tools/valgrind/MPICH.supp +++ b/tools/valgrind/MPICH.supp @@ -121,6 +121,17 @@ fun:PMPI_Init ... } +{ + MPICH_MPI_init10 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:MPII_Init_thread.isra.0 + ... + fun:PMPI_Init + ... +} { MPICH_library1 Memcheck:Leak @@ -128,14 +139,6 @@ fun:malloc ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open - ... - fun:Run - fun:* - fun:* - fun:Run ... } { @@ -147,9 +150,6 @@ fun:MPIDI_OFI_init_local ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... } { @@ -164,9 +164,6 @@ fun:MPIR_init_comm_world ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... } { @@ -180,9 +177,6 @@ fun:hwloc_topology_load ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... } { @@ -208,13 +202,7 @@ fun:MPIR_init_comm_world ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... - fun:Run - fun:* - fun:* } { MPICH_comm2 @@ -228,13 +216,7 @@ fun:MPIR_init_comm_world ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... - fun:Run - fun:* - fun:* } { MPICH_comm3 @@ -248,13 +230,7 @@ fun:MPIR_init_comm_self ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... - fun:Run - fun:* - fun:* } { MPICH_comm4 @@ -268,13 +244,7 @@ fun:MPIR_init_comm_self ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open ... - fun:Run - fun:* - fun:* } { MPICH_psm3_1 @@ -307,8 +277,7 @@ fun:MPIDI_OFI_init_local ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init + ... } { MPICH_psm3_3 @@ -344,8 +313,7 @@ fun:MPIDI_OFI_init_local ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init + ... } { MPICH_hwloc1 @@ -362,9 +330,7 @@ fun:hwloc_topology_load ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open + ... } { MPICH_hwloc2 @@ -379,10 +345,16 @@ fun:hwloc_topology_load ... fun:PMPI_Init - fun:lammps_mpi_init - fun:lammps_mpi_init - fun:lammps_open - fun:* - fun:* - fun:* + ... +} +{ + MPICH_hwloc3 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:hwloc__topology_init + ... + fun:PMPI_Init + ... } diff --git a/tools/valgrind/Python3.supp b/tools/valgrind/Python3.supp index 2e455c8db4..26350ab9c1 100644 --- a/tools/valgrind/Python3.supp +++ b/tools/valgrind/Python3.supp @@ -143,3 +143,165 @@ fun:PyUnicode_FromKindAndData ... } +{ + Python3_init_1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:PyMem_Malloc + fun:PyModule_ExecDef + ... + fun:pycore_interp_init + ... + fun:Py_InitializeFromConfig + ... +} +{ + Python3_init_2 + Memcheck:Leak + match-leak-kinds: reachable + fun:realloc + fun:_Py_EncodeUTF8Ex + fun:encode_wstr_utf8 + ... + fun:py_interp_main + fun:pyinit_main + fun:Py_InitializeFromConfig + ... +} +{ + Python3_init_3 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:_PyMem_RawStrdup + ... + fun:py_interp_main + fun:pyinit_main + fun:Py_InitializeFromConfig + ... +} +{ + Python3_init_4 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:_extensions_cache_find_unlocked + ... + fun:_PyImport_FixupBuiltin + fun:_PySys_Create + fun:pycore_interp_init + ... + fun:Py_InitializeFromConfig + ... +} +{ + Python3_init_5 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:PyMem_Calloc + fun:PyList_New + fun:_PyWideStringList_AsList + fun:* + fun:interpreter_update_config + fun:init_interp_main + fun:pyinit_main + fun:Py_InitializeFromConfig + ... +} +{ + Python3_init_6 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:PyMem_Calloc + fun:PyList_New + fun:* + fun:_PyEval_EvalFrameDefault + ... + fun:PyObject_CallFunction + fun:PyImport_Import + fun:PyImport_ImportModule + ... + fun:init_interp_main +} +{ + Python3_init_7 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:PyMem_Calloc + fun:PyList_New + fun:* + fun:_PyEval_EvalFrameDefault + fun:PyEval_EvalCode + ... + fun:PyObject_CallFunction + fun:PyImport_Import + fun:PyImport_ImportModule + ... +} +{ + Python3_init_8 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:PyMem_Calloc + fun:PyList_New + fun:* + fun:_PyEval_EvalFrameDefault + fun:* + fun:object_vacall + fun:PyObject_CallMethodObjArgs + ... + fun:_PyEval_EvalFrameDefault + fun:* + fun:object_vacall + fun:PyObject_CallMethodObjArgs + fun:* + fun:PyImport_ImportModuleLevelObject +} +{ + Python3_init_9 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:PyMem_Calloc + fun:PyList_New + fun:* + fun:_PyEval_EvalFrameDefault + fun:* + fun:object_vacall + fun:PyObject_CallMethodObjArgs + ... + fun:_PyEval_EvalFrameDefault + fun:PyEval_EvalCode + ... +} +{ + Python3_init_10 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + ... + fun:PyMem_Calloc + fun:PyList_New + fun:* + fun:_PyEval_EvalFrameDefault + ... + fun:PyObject_Vectorcall + fun:_PyEval_EvalFrameDefault + fun:PyEval_EvalCode + fun:* + fun:builtin_exec + ... + fun:_PyEval_EvalFrameDefault +} diff --git a/tools/valgrind/libc.supp b/tools/valgrind/libc.supp index 2b90fd3f1f..a5942c8ed5 100644 --- a/tools/valgrind/libc.supp +++ b/tools/valgrind/libc.supp @@ -67,3 +67,16 @@ fun:_dl_catch_exception fun:_dl_catch_error } +{ + libc_dlclose1 + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:* + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_exception + fun:_dl_catch_error + fun:_dlerror_run + ... +} From f8757abe928856059f9ac9619317d4028c6cbb02 Mon Sep 17 00:00:00 2001 From: Germain Clavier Date: Sun, 6 Apr 2025 10:31:29 +0200 Subject: [PATCH 055/396] Moved plot_forces to the tools/tabulate/ folder --- tools/{python => tabulate}/plot_forces.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tools/{python => tabulate}/plot_forces.py (100%) diff --git a/tools/python/plot_forces.py b/tools/tabulate/plot_forces.py similarity index 100% rename from tools/python/plot_forces.py rename to tools/tabulate/plot_forces.py From b357540e923b71c62df19e892b9768d05aac94b7 Mon Sep 17 00:00:00 2001 From: Germain Clavier Date: Sun, 6 Apr 2025 10:33:30 +0200 Subject: [PATCH 056/396] Added plot_forces description to README.md --- tools/tabulate/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/tabulate/README.md b/tools/tabulate/README.md index d3b4df0738..995bb8abdd 100644 --- a/tools/tabulate/README.md +++ b/tools/tabulate/README.md @@ -27,6 +27,7 @@ Please see the individual tabulation scripts in this folder for examples: | wall_harmonic_tabulate.py | creates a table for fix wall/table with a simple repulsive harmonic potential | | wall_multi_tabulate.py | creates a table for fix wall/table with multiple tables | | pair_bi_tabulate.py | creates a table from radial distribution file using Boltzmann Inversion | +| plot_forces.py | plots and extracts tabulated forces from table files | Common command line flags: From 94e602221065ef9d1e2dba1419f0551a81ae5948 Mon Sep 17 00:00:00 2001 From: Germain Clavier Date: Sun, 6 Apr 2025 10:34:28 +0200 Subject: [PATCH 057/396] Changed --recompute option of plot_forces to -d for consistency --- tools/tabulate/plot_forces.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/tabulate/plot_forces.py b/tools/tabulate/plot_forces.py index 583f3ae6ed..ee55a93be6 100644 --- a/tools/tabulate/plot_forces.py +++ b/tools/tabulate/plot_forces.py @@ -123,7 +123,8 @@ def main(): help="temperature for KbT plot [default none]", ) parser.add_argument( - "--recompute-energy", + "-d", + "--diff-num", dest="recompute", action="store_true", help="Recompute the energies from forces and distances through finite differences", From ece0df7f7e133fc3defdd5df9cca3a1f272b317c Mon Sep 17 00:00:00 2001 From: Germain Clavier Date: Sun, 6 Apr 2025 10:37:23 +0200 Subject: [PATCH 058/396] Small modification of Tools.rst to include plot_forces + typo --- doc/src/Tools.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/src/Tools.rst b/doc/src/Tools.rst index e502480ce5..488de848bf 100644 --- a/doc/src/Tools.rst +++ b/doc/src/Tools.rst @@ -1250,10 +1250,10 @@ tabulate tool .. versionadded:: 22Dec2022 -The ``tabulate`` folder contains Python scripts scripts to generate tabulated -potential files for LAMMPS. The bulk of the code is in the ``tabulate`` module -in the ``tabulate.py`` file. Some example files demonstrating its use are -included. See the README file for more information. +The ``tabulate`` folder contains Python scripts scripts to generate and +visualize tabulated potential files for LAMMPS. The bulk of the code is in the +``tabulate`` module in the ``tabulate.py`` file. Some example files +demonstrating its use are included. See the README file for more information. ---------- @@ -1276,7 +1276,7 @@ Those scripts were written by Steve Plimpton sjplimp at gmail.com valgrind tool ------------- -The ``valgrind`` folder contains additional suppressions fur LAMMPS when +The ``valgrind`` folder contains additional suppressions for LAMMPS when using `valgrind's `_ ` `memcheck tool `_ to search for memory access violation and memory leaks. These suppressions are automatically From 6ab7d7d818c47b573527f7ae193d1e96e44b6948 Mon Sep 17 00:00:00 2001 From: Germain Clavier Date: Sun, 6 Apr 2025 10:37:54 +0200 Subject: [PATCH 059/396] Made plot_forces executable --- tools/tabulate/plot_forces.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/tabulate/plot_forces.py diff --git a/tools/tabulate/plot_forces.py b/tools/tabulate/plot_forces.py old mode 100644 new mode 100755 From 6272acd9c6fabfccb3e5e9f546c96a5e803be2e5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 06:19:34 -0400 Subject: [PATCH 060/396] match documentation to return 0 when checking for size of columns on 1d arrays --- src/atom.cpp | 146 ++++++++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/src/atom.cpp b/src/atom.cpp index 0e0b1350ac..ae06a9070d 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -3409,107 +3409,111 @@ int Atom::extract_size(const char *name, int type) } } } else { + if (type == LMP_SIZE_COLS) { + return 0; + } else if (type == LMP_SIZE_ROWS) { - if (strcmp(name,"mass") == 0) return ntypes + 1; + if (strcmp(name,"mass") == 0) return ntypes + 1; - if (strcmp(name,"id") == 0) return nall; - if (strcmp(name,"type") == 0) return nall; - if (strcmp(name,"mask") == 0) return nall; - if (strcmp(name,"image") == 0) return nlocal; - if (strcmp(name,"molecule") == 0) return nall; - if (strcmp(name,"q") == 0) return nall; - if (strcmp(name,"radius") == 0) return nall; - if (strcmp(name,"rmass") == 0) return nall; + if (strcmp(name,"id") == 0) return nall; + if (strcmp(name,"type") == 0) return nall; + if (strcmp(name,"mask") == 0) return nall; + if (strcmp(name,"image") == 0) return nlocal; + if (strcmp(name,"molecule") == 0) return nall; + if (strcmp(name,"q") == 0) return nall; + if (strcmp(name,"radius") == 0) return nall; + if (strcmp(name,"rmass") == 0) return nall; - // ASPHERE package + // ASPHERE package - if (strcmp(name,"ellipsoid") == 0) return nlocal; + if (strcmp(name,"ellipsoid") == 0) return nlocal; - // BODY package + // BODY package - if (strcmp(name,"line") == 0) return nlocal; - if (strcmp(name,"tri") == 0) return nlocal; - if (strcmp(name,"body") == 0) return nlocal; + if (strcmp(name,"line") == 0) return nlocal; + if (strcmp(name,"tri") == 0) return nlocal; + if (strcmp(name,"body") == 0) return nlocal; - // PERI package (and in part MACHDYN) + // PERI package (and in part MACHDYN) - if (strcmp(name,"vfrac") == 0) return nall; - if (strcmp(name,"s0") == 0) return nall; + if (strcmp(name,"vfrac") == 0) return nall; + if (strcmp(name,"s0") == 0) return nall; - // AWPMD package (and in part EFF and ELECTRODE) + // AWPMD package (and in part EFF and ELECTRODE) - if (strcmp(name,"espin") == 0) return nall; - if (strcmp(name,"spin") == 0) return nall; // backwards compatibility - if (strcmp(name,"eradius") == 0) return nall; - if (strcmp(name,"ervel") == 0) return nlocal; - if (strcmp(name,"erforce") == 0) return nlocal; - if (strcmp(name,"ervelforce") == 0) return nlocal; - if (strcmp(name,"etag") == 0) return nall; + if (strcmp(name,"espin") == 0) return nall; + if (strcmp(name,"spin") == 0) return nall; // backwards compatibility + if (strcmp(name,"eradius") == 0) return nall; + if (strcmp(name,"ervel") == 0) return nlocal; + if (strcmp(name,"erforce") == 0) return nlocal; + if (strcmp(name,"ervelforce") == 0) return nlocal; + if (strcmp(name,"etag") == 0) return nall; - // CG-DNA package + // CG-DNA package - if (strcmp(name,"id5p") == 0) return nall; + if (strcmp(name,"id5p") == 0) return nall; - // RHEO package + // RHEO package - if (strcmp(name,"temperature") == 0) return nlocal; - if (strcmp(name,"heatflow") == 0) return nlocal; - if (strcmp(name,"rheo_status") == 0) return nall; - if (strcmp(name,"conductivity") == 0) return nlocal; - if (strcmp(name,"pressure") == 0) return nlocal; - if (strcmp(name,"viscosity") == 0) return nlocal; + if (strcmp(name,"temperature") == 0) return nlocal; + if (strcmp(name,"heatflow") == 0) return nlocal; + if (strcmp(name,"rheo_status") == 0) return nall; + if (strcmp(name,"conductivity") == 0) return nlocal; + if (strcmp(name,"pressure") == 0) return nlocal; + if (strcmp(name,"viscosity") == 0) return nlocal; - // SPH package + // SPH package - if (strcmp(name,"rho") == 0) return nall; - if (strcmp(name,"drho") == 0) return nlocal; - if (strcmp(name,"esph") == 0) return nall; - if (strcmp(name,"desph") == 0) return nlocal; - if (strcmp(name,"cv") == 0) return nall; + if (strcmp(name,"rho") == 0) return nall; + if (strcmp(name,"drho") == 0) return nlocal; + if (strcmp(name,"esph") == 0) return nall; + if (strcmp(name,"desph") == 0) return nlocal; + if (strcmp(name,"cv") == 0) return nall; - // MACHDYN package + // MACHDYN package - if (strcmp(name, "contact_radius") == 0) return nall; - if (strcmp(name, "eff_plastic_strain") == 0) return nlocal; - if (strcmp(name, "eff_plastic_strain_rate") == 0) return nlocal; - if (strcmp(name, "damage") == 0) return nlocal; + if (strcmp(name, "contact_radius") == 0) return nall; + if (strcmp(name, "eff_plastic_strain") == 0) return nlocal; + if (strcmp(name, "eff_plastic_strain_rate") == 0) return nlocal; + if (strcmp(name, "damage") == 0) return nlocal; - // DPD-REACT package + // DPD-REACT package - if (strcmp(name,"dpdTheta") == 0) return nall; + if (strcmp(name,"dpdTheta") == 0) return nall; - // DPD-MESO package + // DPD-MESO package - if (strcmp(name,"edpd_temp") == 0) return nall; + if (strcmp(name,"edpd_temp") == 0) return nall; - // DIELECTRIC package + // DIELECTRIC package - if (strcmp(name,"area") == 0) return nall; - if (strcmp(name,"ed") == 0) return nall; - if (strcmp(name,"em") == 0) return nall; - if (strcmp(name,"epsilon") == 0) return nall; - if (strcmp(name,"curvature") == 0) return nall; - if (strcmp(name,"q_unscaled") == 0) return nall; + if (strcmp(name,"area") == 0) return nall; + if (strcmp(name,"ed") == 0) return nall; + if (strcmp(name,"em") == 0) return nall; + if (strcmp(name,"epsilon") == 0) return nall; + if (strcmp(name,"curvature") == 0) return nall; + if (strcmp(name,"q_unscaled") == 0) return nall; - // end of customization section - // -------------------------------------------------------------------- + // end of customization section + // -------------------------------------------------------------------- - // custom vectors + // custom vectors - if (utils::strmatch(name,"^[id]_")) { - int which = 0; - if (name[0] == 'd') which = 1; + if (utils::strmatch(name,"^[id]_")) { + int which = 0; + if (name[0] == 'd') which = 1; - int index,flag,cols,ghost; - index = find_custom_ghost(&name[2],flag,cols,ghost); + int index,flag,cols,ghost; + index = find_custom_ghost(&name[2],flag,cols,ghost); - // consistency checks - if (index < 0) return -1; - if (which != flag) return -1; - if (cols) return -1; + // consistency checks + if (index < 0) return -1; + if (which != flag) return -1; + if (cols) return -1; - if (ghost) return nall; - else return nlocal; + if (ghost) return nall; + else return nlocal; + } } } return -1; From da2bc03ae6d1eb447e3a0e89cff29fa795aa220d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 06:21:39 -0400 Subject: [PATCH 061/396] do explicit loop over nlocal to avoid out-of-bounds access with implicit loop --- unittest/fortran/test_fortran_fixexternal.f90 | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/unittest/fortran/test_fortran_fixexternal.f90 b/unittest/fortran/test_fortran_fixexternal.f90 index d46e1ec673..ec42716507 100644 --- a/unittest/fortran/test_fortran_fixexternal.f90 +++ b/unittest/fortran/test_fortran_fixexternal.f90 @@ -323,44 +323,50 @@ SUBROUTINE f_lammps_find_forces() BIND(C) INTEGER(c_int) :: size_tagint INTEGER(c_int), DIMENSION(:), POINTER :: id INTEGER(c_int64_t), DIMENSION(:), POINTER :: tag + INTEGER :: i, nlocal f3(:,:) = 0.0_c_double f4(:,:) = 0.0_c_double size_tagint = lmp%extract_setting('tagint') + nlocal = lmp%extract_setting('nlocal') IF (size_tagint == 4_c_int) THEN id = lmp%extract_atom('id') - WHERE (id == 1_c_int) - f3(1,:) = 4.0_c_double - f3(2,:) = -4.0_c_double - f3(3,:) = 6.0_c_double - f4(1,:) = 10.0_c_double - f4(2,:) = -10.0_c_double - f4(3,:) = 12.0_c_double - ELSEWHERE - f3(1,:) = 5.0_c_double - f3(2,:) = -5.0_c_double - f3(3,:) = 7.0_c_double - f4(1,:) = 11.0_c_double - f4(2,:) = -11.0_c_double - f4(3,:) = 13.0_c_double - END WHERE + DO i=1,nlocal + IF (id(i) == 1_c_int) THEN + f3(1,i) = 4.0_c_double + f3(2,i) = -4.0_c_double + f3(3,i) = 6.0_c_double + f4(1,i) = 10.0_c_double + f4(2,i) = -10.0_c_double + f4(3,i) = 12.0_c_double + ELSE + f3(1,i) = 5.0_c_double + f3(2,i) = -5.0_c_double + f3(3,i) = 7.0_c_double + f4(1,i) = 11.0_c_double + f4(2,i) = -11.0_c_double + f4(3,i) = 13.0_c_double + END IF + END DO ELSE tag = lmp%extract_atom('id') - WHERE (tag == 1_c_int64_t) - f3(1,:) = 4.0_c_double - f3(2,:) = -4.0_c_double - f3(3,:) = 6.0_c_double - f4(1,:) = 10.0_c_double - f4(2,:) = -10.0_c_double - f4(3,:) = 12.0_c_double - ELSEWHERE - f3(1,:) = 5.0_c_double - f3(2,:) = -5.0_c_double - f3(3,:) = 7.0_c_double - f4(1,:) = 11.0_c_double - f4(2,:) = -11.0_c_double - f4(3,:) = 13.0_c_double - END WHERE + DO i=1,nlocal + IF (tag(i) == 1_c_int64_t) THEN + f3(1,i) = 4.0_c_double + f3(2,i) = -4.0_c_double + f3(3,i) = 6.0_c_double + f4(1,i) = 10.0_c_double + f4(2,i) = -10.0_c_double + f4(3,i) = 12.0_c_double + ELSE + f3(1,i) = 5.0_c_double + f3(2,i) = -5.0_c_double + f3(3,i) = 7.0_c_double + f4(1,i) = 11.0_c_double + f4(2,i) = -11.0_c_double + f4(3,i) = 13.0_c_double + END IF + END DO END IF END SUBROUTINE f_lammps_find_forces From cdea2737c7e1fca38ddb0f4c56d2046d3142b6e7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 07:06:20 -0400 Subject: [PATCH 062/396] remove CMAKE_TUNE_FLAGS --- cmake/CMakeLists.txt | 26 ++++++++---------- cmake/Modules/Packages/COLVARS.cmake | 4 --- cmake/presets/kokkos-hip.cmake | 8 +++++- cmake/presets/kokkos-sycl-intel.cmake | 17 ++++++++---- cmake/presets/kokkos-sycl-nvidia.cmake | 12 ++++++-- cmake/presets/mingw-cross.cmake | 8 +++++- cmake/presets/windows-intel-llvm.cmake | 8 +++++- doc/src/Build_basics.rst | 10 +------ doc/src/Build_settings.rst | 38 -------------------------- doc/src/Howto_cmake.rst | 4 +-- 10 files changed, 56 insertions(+), 79 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index f22fa401a2..6fb2f0c65e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -102,31 +102,31 @@ include(CheckIncludeFileCXX) if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") if(CMAKE_SYSTEM_NAME STREQUAL "Windows") if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Qrestrict") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} /Qrestrict") endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_TUNE_DEFAULT "/QxCOMMON-AVX512") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} /QxCOMMON-AVX512") else() - set(CMAKE_TUNE_DEFAULT "/QxHost") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} /QxHost") endif() else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -restrict") if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_TUNE_DEFAULT "-xCOMMON-AVX512") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -xCOMMON-AVX512") else() - set(CMAKE_TUNE_DEFAULT "-xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196") endif() endif() endif() # silence excessive warnings for new Intel Compilers if(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(CMAKE_TUNE_DEFAULT "-fp-model precise -Wno-tautological-constant-compare -Wno-unused-command-line-argument") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -fp-model precise -Wno-tautological-constant-compare -Wno-unused-command-line-argument") endif() # silence excessive warnings for PGI/NVHPC compilers if((CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC") OR (CMAKE_CXX_COMPILER_ID STREQUAL "PGI")) - set(CMAKE_TUNE_DEFAULT "-Minform=severe") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -Minform=severe") endif() # this hack is required to compile fmt lib with CrayClang version 15.0.2 @@ -134,17 +134,17 @@ endif() if(CMAKE_VERSION VERSION_LESS 3.28) get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) - set(CMAKE_TUNE_DEFAULT "-DFMT_STATIC_THOUSANDS_SEPARATOR") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -DFMT_STATIC_THOUSANDS_SEPARATOR") endif() else() if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") - set(CMAKE_TUNE_DEFAULT "-DFMT_STATIC_THOUSANDS_SEPARATOR") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -DFMT_STATIC_THOUSANDS_SEPARATOR") endif() endif() # silence nvcc warnings if((PKG_KOKKOS) AND (Kokkos_ENABLE_CUDA) AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) - set(CMAKE_TUNE_DEFAULT "${CMAKE_TUNE_DEFAULT}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") + set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") endif() # we *require* C++11 without extensions but prefer C++17. @@ -628,10 +628,6 @@ if(WITH_SWIG) add_subdirectory(${LAMMPS_SWIG_DIR} swig) endif() -set(CMAKE_TUNE_FLAGS "${CMAKE_TUNE_DEFAULT}" CACHE STRING "Compiler and machine specific optimization flags (compilation only)") -separate_arguments(CMAKE_TUNE_FLAGS) -target_compile_options(lammps PRIVATE ${CMAKE_TUNE_FLAGS}) -target_compile_options(lmp PRIVATE ${CMAKE_TUNE_FLAGS}) ######################################################################## # Basic system tests (standard libraries, headers, functions, types) # ######################################################################## diff --git a/cmake/Modules/Packages/COLVARS.cmake b/cmake/Modules/Packages/COLVARS.cmake index b943a0345e..8fa0d84f01 100644 --- a/cmake/Modules/Packages/COLVARS.cmake +++ b/cmake/Modules/Packages/COLVARS.cmake @@ -14,10 +14,6 @@ endif() add_library(colvars STATIC ${COLVARS_SOURCES}) target_compile_definitions(colvars PRIVATE -DCOLVARS_LAMMPS) -separate_arguments(CMAKE_TUNE_FLAGS) -foreach(_FLAG ${CMAKE_TUNE_FLAGS}) - target_compile_options(colvars PRIVATE ${_FLAG}) -endforeach() set_target_properties(colvars PROPERTIES OUTPUT_NAME lammps_colvars${LAMMPS_MACHINE}) target_include_directories(colvars PUBLIC ${LAMMPS_LIB_SOURCE_DIR}/colvars) # The line below is needed to locate math_eigen_impl.h diff --git a/cmake/presets/kokkos-hip.cmake b/cmake/presets/kokkos-hip.cmake index 38bf27092f..ba1eeb1853 100644 --- a/cmake/presets/kokkos-hip.cmake +++ b/cmake/presets/kokkos-hip.cmake @@ -10,7 +10,13 @@ set(Kokkos_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS ON CACHE BOOL "" FORCE) set(BUILD_OMP ON CACHE BOOL "" FORCE) set(CMAKE_CXX_COMPILER hipcc CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-munsafe-fp-atomics" CACHE STRING "" FORCE) +if (CMAKE_CXX_FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -munsafe-fp-atomics" CACHE STRING "" FORCE) +endif() +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -munsafe-fp-atomics" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -munsafe-fp-atomics" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -munsafe-fp-atomics" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -munsafe-fp-atomics" CACHE STRING "" FORCE) # If KSPACE is also enabled, use CUFFT for FFTs set(FFT_KOKKOS "HIPFFT" CACHE STRING "" FORCE) diff --git a/cmake/presets/kokkos-sycl-intel.cmake b/cmake/presets/kokkos-sycl-intel.cmake index eba386564d..163d35e031 100644 --- a/cmake/presets/kokkos-sycl-intel.cmake +++ b/cmake/presets/kokkos-sycl-intel.cmake @@ -21,9 +21,16 @@ set(CMAKE_C_COMPILER icx CACHE STRING "" FORCE) set(CMAKE_Fortran_COMPILER "" CACHE STRING "" FORCE) set(MPI_CXX_COMPILER "mpicxx" CACHE STRING "" FORCE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) -# Silence everything -set(CMAKE_CXX_FLAGS "-w" CACHE STRING "" FORCE) + +# set(_intel_sycl_flags " -w -fsycl -flink-huge-device-code -fsycl-targets=spir64_gen " +set(_intel_sycl_flags " -w -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen " +if (CMAKE_CXX_FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +endif() +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${_intel_sycl_flags}" CACHE STRING "" FORCE) + #set(CMAKE_EXE_LINKER_FLAGS "-fsycl -flink-huge-device-code -fsycl-targets=spir64_gen " CACHE STRING "" FORCE) -#set(CMAKE_TUNE_FLAGS "-O3 -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen" CACHE STRING "" FORCE) -set(CMAKE_EXE_LINKER_FLAGS "-fsycl -flink-huge-device-code " CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-O3 -fsycl -fsycl-device-code-split=per_kernel " CACHE STRING "" FORCE) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsycl -flink-huge-device-code " CACHE STRING "" FORCE) diff --git a/cmake/presets/kokkos-sycl-nvidia.cmake b/cmake/presets/kokkos-sycl-nvidia.cmake index c706aca7d8..678f9f380a 100644 --- a/cmake/presets/kokkos-sycl-nvidia.cmake +++ b/cmake/presets/kokkos-sycl-nvidia.cmake @@ -14,5 +14,13 @@ set(Kokkos_ENABLE_DEPRECATION_WARNINGS OFF CACHE BOOL "" FORCE) set(CMAKE_CXX_COMPILER clang++ CACHE STRING "" FORCE) set(MPI_CXX_COMPILER "mpicxx" CACHE STRING "" FORCE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) -set(CMAKE_SHARED_LINKER_FLAGS "-Xsycl-target-frontend -O3" CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-fgpu-inline-threshold=100000 -Xsycl-target-frontend -O3 -Xsycl-target-frontend -ffp-contract=on -Wno-unknown-cuda-version" CACHE STRING "" FORCE) +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xsycl-target-frontend -O3 " CACHE STRING "" FORCE) + +set(_intel_sycl_flags "-fgpu-inline-threshold=100000 -Xsycl-target-frontend -O3 -Xsycl-target-frontend -ffp-contract=on -Wno-unknown-cuda-version") +if (CMAKE_CXX_FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +endif() +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${_intel_sycl_flags}" CACHE STRING "" FORCE) diff --git a/cmake/presets/mingw-cross.cmake b/cmake/presets/mingw-cross.cmake index 413744b078..dbcd4ef11d 100644 --- a/cmake/presets/mingw-cross.cmake +++ b/cmake/presets/mingw-cross.cmake @@ -91,7 +91,13 @@ endif() set(DOWNLOAD_VORO ON CACHE BOOL "" FORCE) set(DOWNLOAD_EIGEN3 ON CACHE BOOL "" FORCE) set(LAMMPS_MEMALIGN "0" CACHE STRING "" FORCE) -set(CMAKE_TUNE_FLAGS "-Wno-missing-include-dirs" CACHE STRING "" FORCE) +if (CMAKE_CXX_FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-include-dirs" CACHE STRING "" FORCE) +endif() +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-missing-include-dirs" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-missing-include-dirs" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-missing-include-dirs" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Wno-missing-include-dirs" CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-stdcall-fixup,--as-needed,-lssp" CACHE STRING "" FORCE) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-stdcall-fixup,--as-needed,-lssp" CACHE STRING "" FORCE) set(BUILD_TOOLS ON CACHE BOOL "" FORCE) diff --git a/cmake/presets/windows-intel-llvm.cmake b/cmake/presets/windows-intel-llvm.cmake index e9d88d22fe..cdde3c146a 100644 --- a/cmake/presets/windows-intel-llvm.cmake +++ b/cmake/presets/windows-intel-llvm.cmake @@ -5,4 +5,10 @@ set(CMAKE_C_COMPILER "icx" CACHE STRING "" FORCE) set(CMAKE_Fortran_COMPILER "ifx" CACHE STRING "" FORCE) set(INTEL_LRT_MODE "C++11" CACHE STRING "" FORCE) unset(HAVE_OMP_H_INCLUDE CACHE) -set(CMAKE_TUNE_FLAGS -Wno-unused-command-line-argument) +if (CMAKE_CXX_FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) +endif() +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) diff --git a/doc/src/Build_basics.rst b/doc/src/Build_basics.rst index be4b312578..f9cf251688 100644 --- a/doc/src/Build_basics.rst +++ b/doc/src/Build_basics.rst @@ -212,11 +212,7 @@ LAMMPS. You can tell CMake to look for a specific compiler with setting CMake variables (listed below) during configuration. For a few common choices, there are also presets in the ``cmake/presets`` - folder. For convenience, there is a ``CMAKE_TUNE_FLAGS`` variable - that can be set to apply global compiler options (applied to - compilation only), to be used for adding compiler or host specific - optimization flags in addition to the "flags" variables listed - below. You may also specify the corresponding ``CMAKE_*_FLAGS`` + folder. You may also specify the corresponding ``CMAKE_*_FLAGS`` variables individually, if you want to experiment with alternate optimization flags. You should specify all 3 compilers, so that the (few) LAMMPS source files written in C or Fortran are built @@ -266,10 +262,6 @@ LAMMPS. ``-C ../cmake/presets/pgi.cmake`` will switch the compiler to the PGI compilers, and ``-C ../cmake/presets/nvhpc.cmake`` will switch to the NVHPC compilers. - Furthermore, you can set ``CMAKE_TUNE_FLAGS`` to specifically add - compiler flags to tune for optimal performance on given hosts. - This variable is empty by default. - .. note:: When the cmake command completes, it prints a summary to the diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index 226e19bfc3..7c16409995 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -18,7 +18,6 @@ explains how to do this for building both with CMake and make. * `Memory allocation alignment`_ * `Workaround for long long integers`_ * `Exception handling when using LAMMPS as a library`_ to capture errors -* `Trigger selected floating-point exceptions`_ ---------- @@ -659,40 +658,3 @@ code has to be set up to *catch* exceptions thrown from within LAMMPS. throw an exception and thus other MPI ranks may get stuck waiting for messages from the ones with errors. ----------- - -.. _trap_fpe: - -Trigger selected floating-point exceptions ------------------------------------------- - -Many kinds of CPUs have the capability to detect when a calculation -results in an invalid math operation, like a division by zero or calling -the square root with a negative argument. The default behavior on -most operating systems is to continue and have values for ``NaN`` (= not -a number) or ``Inf`` (= infinity). This allows software to detect and -recover from such conditions. This behavior can be changed, however, -often through use of compiler flags. On Linux systems (or more general -on systems using the GNU C library), these so-called floating-point traps -can also be selectively enabled through library calls. LAMMPS supports -that by setting the ``-DLAMMPS_TRAP_FPE`` pre-processor define. As it is -done in the ``main()`` function, this applies only to the standalone -executable, not the library. - -.. tabs:: - - .. tab:: CMake build - - .. code-block:: bash - - -D CMAKE_TUNE_FLAGS=-DLAMMPS_TRAP_FPE - - .. tab:: Traditional make - - .. code-block:: make - - LMP_INC = -DLAMMPS_TRAP_FPE - -After compilation with this flag set, the LAMMPS executable will stop -and produce a core dump when a division by zero, overflow, illegal math -function argument or other invalid floating point operation is encountered. diff --git a/doc/src/Howto_cmake.rst b/doc/src/Howto_cmake.rst index 6b8fc82bad..64acee47dd 100644 --- a/doc/src/Howto_cmake.rst +++ b/doc/src/Howto_cmake.rst @@ -285,7 +285,7 @@ when used before the CMake directory, there may be a space between the can have boolean values (on/off, yes/no, or 1/0 are all valid) or are strings representing a choice, or a path, or are free format. If the string would contain whitespace, it must be put in quotes, for example -``-D CMAKE_TUNE_FLAGS="-ftree-vectorize -ffast-math"``. +``-D CMAKE_CXX_FLAGS="-O3 -Wall -ftree-vectorize -ffast-math"``. CMake variables fall into two categories: 1) common CMake variables that are used by default for any CMake configuration setup and 2) project @@ -341,8 +341,6 @@ Some common LAMMPS specific variables - compile some additional executables from the ``tools`` folder (default: ``off``) * - ``BUILD_DOC`` - include building the HTML format documentation for packaging/installing (default: ``off``) - * - ``CMAKE_TUNE_FLAGS`` - - common compiler flags, for optimization or instrumentation (default:) * - ``LAMMPS_MACHINE`` - when set to ``name`` the LAMMPS executable and library will be called ``lmp_name`` and ``liblammps_name.a`` * - ``FFT`` From ac76176dd5099dc727e0ab195ea83ecfa05b8729 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 07:29:35 -0400 Subject: [PATCH 063/396] must set lj cutoff to avoid uninitialized data access --- src/KOKKOS/pair_coul_long_kokkos.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/KOKKOS/pair_coul_long_kokkos.cpp b/src/KOKKOS/pair_coul_long_kokkos.cpp index 0452a08b8f..abbe46e660 100644 --- a/src/KOKKOS/pair_coul_long_kokkos.cpp +++ b/src/KOKKOS/pair_coul_long_kokkos.cpp @@ -378,6 +378,7 @@ void PairCoulLongKokkos::init_style() PairCoulLong::init_style(); Kokkos::deep_copy(d_cut_coulsq,cut_coulsq); + Kokkos::deep_copy(d_cut_ljsq,cut_coulsq); // error if rRESPA with inner levels @@ -415,6 +416,7 @@ double PairCoulLongKokkos::init_one(int i, int j) m_params[i][j] = m_params[j][i] = k_params.h_view(i,j); m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone; m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsq; + m_cut_ljsq[j][i] = m_cut_ljsq[i][j] = cut_coulsq; } k_cutsq.h_view(i,j) = cutone*cutone; From c6d2812d2dfb1dd1cff9a8691fb395557328ff92 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 07:51:52 -0400 Subject: [PATCH 064/396] Revert "match documentation to return 0 when checking for size of columns on 1d arrays" This reverts commit 6272acd9c6fabfccb3e5e9f546c96a5e803be2e5. Which isn't needed --- src/atom.cpp | 146 +++++++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 75 deletions(-) diff --git a/src/atom.cpp b/src/atom.cpp index ae06a9070d..0e0b1350ac 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -3409,111 +3409,107 @@ int Atom::extract_size(const char *name, int type) } } } else { - if (type == LMP_SIZE_COLS) { - return 0; - } else if (type == LMP_SIZE_ROWS) { - if (strcmp(name,"mass") == 0) return ntypes + 1; + if (strcmp(name,"mass") == 0) return ntypes + 1; - if (strcmp(name,"id") == 0) return nall; - if (strcmp(name,"type") == 0) return nall; - if (strcmp(name,"mask") == 0) return nall; - if (strcmp(name,"image") == 0) return nlocal; - if (strcmp(name,"molecule") == 0) return nall; - if (strcmp(name,"q") == 0) return nall; - if (strcmp(name,"radius") == 0) return nall; - if (strcmp(name,"rmass") == 0) return nall; + if (strcmp(name,"id") == 0) return nall; + if (strcmp(name,"type") == 0) return nall; + if (strcmp(name,"mask") == 0) return nall; + if (strcmp(name,"image") == 0) return nlocal; + if (strcmp(name,"molecule") == 0) return nall; + if (strcmp(name,"q") == 0) return nall; + if (strcmp(name,"radius") == 0) return nall; + if (strcmp(name,"rmass") == 0) return nall; - // ASPHERE package + // ASPHERE package - if (strcmp(name,"ellipsoid") == 0) return nlocal; + if (strcmp(name,"ellipsoid") == 0) return nlocal; - // BODY package + // BODY package - if (strcmp(name,"line") == 0) return nlocal; - if (strcmp(name,"tri") == 0) return nlocal; - if (strcmp(name,"body") == 0) return nlocal; + if (strcmp(name,"line") == 0) return nlocal; + if (strcmp(name,"tri") == 0) return nlocal; + if (strcmp(name,"body") == 0) return nlocal; - // PERI package (and in part MACHDYN) + // PERI package (and in part MACHDYN) - if (strcmp(name,"vfrac") == 0) return nall; - if (strcmp(name,"s0") == 0) return nall; + if (strcmp(name,"vfrac") == 0) return nall; + if (strcmp(name,"s0") == 0) return nall; - // AWPMD package (and in part EFF and ELECTRODE) + // AWPMD package (and in part EFF and ELECTRODE) - if (strcmp(name,"espin") == 0) return nall; - if (strcmp(name,"spin") == 0) return nall; // backwards compatibility - if (strcmp(name,"eradius") == 0) return nall; - if (strcmp(name,"ervel") == 0) return nlocal; - if (strcmp(name,"erforce") == 0) return nlocal; - if (strcmp(name,"ervelforce") == 0) return nlocal; - if (strcmp(name,"etag") == 0) return nall; + if (strcmp(name,"espin") == 0) return nall; + if (strcmp(name,"spin") == 0) return nall; // backwards compatibility + if (strcmp(name,"eradius") == 0) return nall; + if (strcmp(name,"ervel") == 0) return nlocal; + if (strcmp(name,"erforce") == 0) return nlocal; + if (strcmp(name,"ervelforce") == 0) return nlocal; + if (strcmp(name,"etag") == 0) return nall; - // CG-DNA package + // CG-DNA package - if (strcmp(name,"id5p") == 0) return nall; + if (strcmp(name,"id5p") == 0) return nall; - // RHEO package + // RHEO package - if (strcmp(name,"temperature") == 0) return nlocal; - if (strcmp(name,"heatflow") == 0) return nlocal; - if (strcmp(name,"rheo_status") == 0) return nall; - if (strcmp(name,"conductivity") == 0) return nlocal; - if (strcmp(name,"pressure") == 0) return nlocal; - if (strcmp(name,"viscosity") == 0) return nlocal; + if (strcmp(name,"temperature") == 0) return nlocal; + if (strcmp(name,"heatflow") == 0) return nlocal; + if (strcmp(name,"rheo_status") == 0) return nall; + if (strcmp(name,"conductivity") == 0) return nlocal; + if (strcmp(name,"pressure") == 0) return nlocal; + if (strcmp(name,"viscosity") == 0) return nlocal; - // SPH package + // SPH package - if (strcmp(name,"rho") == 0) return nall; - if (strcmp(name,"drho") == 0) return nlocal; - if (strcmp(name,"esph") == 0) return nall; - if (strcmp(name,"desph") == 0) return nlocal; - if (strcmp(name,"cv") == 0) return nall; + if (strcmp(name,"rho") == 0) return nall; + if (strcmp(name,"drho") == 0) return nlocal; + if (strcmp(name,"esph") == 0) return nall; + if (strcmp(name,"desph") == 0) return nlocal; + if (strcmp(name,"cv") == 0) return nall; - // MACHDYN package + // MACHDYN package - if (strcmp(name, "contact_radius") == 0) return nall; - if (strcmp(name, "eff_plastic_strain") == 0) return nlocal; - if (strcmp(name, "eff_plastic_strain_rate") == 0) return nlocal; - if (strcmp(name, "damage") == 0) return nlocal; + if (strcmp(name, "contact_radius") == 0) return nall; + if (strcmp(name, "eff_plastic_strain") == 0) return nlocal; + if (strcmp(name, "eff_plastic_strain_rate") == 0) return nlocal; + if (strcmp(name, "damage") == 0) return nlocal; - // DPD-REACT package + // DPD-REACT package - if (strcmp(name,"dpdTheta") == 0) return nall; + if (strcmp(name,"dpdTheta") == 0) return nall; - // DPD-MESO package + // DPD-MESO package - if (strcmp(name,"edpd_temp") == 0) return nall; + if (strcmp(name,"edpd_temp") == 0) return nall; - // DIELECTRIC package + // DIELECTRIC package - if (strcmp(name,"area") == 0) return nall; - if (strcmp(name,"ed") == 0) return nall; - if (strcmp(name,"em") == 0) return nall; - if (strcmp(name,"epsilon") == 0) return nall; - if (strcmp(name,"curvature") == 0) return nall; - if (strcmp(name,"q_unscaled") == 0) return nall; + if (strcmp(name,"area") == 0) return nall; + if (strcmp(name,"ed") == 0) return nall; + if (strcmp(name,"em") == 0) return nall; + if (strcmp(name,"epsilon") == 0) return nall; + if (strcmp(name,"curvature") == 0) return nall; + if (strcmp(name,"q_unscaled") == 0) return nall; - // end of customization section - // -------------------------------------------------------------------- + // end of customization section + // -------------------------------------------------------------------- - // custom vectors + // custom vectors - if (utils::strmatch(name,"^[id]_")) { - int which = 0; - if (name[0] == 'd') which = 1; + if (utils::strmatch(name,"^[id]_")) { + int which = 0; + if (name[0] == 'd') which = 1; - int index,flag,cols,ghost; - index = find_custom_ghost(&name[2],flag,cols,ghost); + int index,flag,cols,ghost; + index = find_custom_ghost(&name[2],flag,cols,ghost); - // consistency checks - if (index < 0) return -1; - if (which != flag) return -1; - if (cols) return -1; + // consistency checks + if (index < 0) return -1; + if (which != flag) return -1; + if (cols) return -1; - if (ghost) return nall; - else return nlocal; - } + if (ghost) return nall; + else return nlocal; } } return -1; From cf3ffb9dfc6e221a961257f7e6b5f4c665385bb1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 10:25:31 -0400 Subject: [PATCH 065/396] simplify fingerprint to match more suppression cases --- tools/valgrind/Kokkos.supp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/valgrind/Kokkos.supp b/tools/valgrind/Kokkos.supp index a9d62ce2e2..88eac2faa6 100644 --- a/tools/valgrind/Kokkos.supp +++ b/tools/valgrind/Kokkos.supp @@ -22,8 +22,5 @@ fun:_ZNK6Kokkos9HostSpace13impl_allocateEPKcmm28Kokkos_Profiling_SpaceHandle fun:_ZNK6Kokkos9HostSpace8allocateEPKcmm fun:_ZN6Kokkos4Impl14OpenMPInternal18resize_thread_dataEmmmm - fun:execute - ... - fun:operator() ... } From d4bcd3b7eb3560abe21dfd2b0fe564a5b3898ddc Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 10:25:56 -0400 Subject: [PATCH 066/396] plug memory leak in SO3 descriptor for pair style mliap/kk --- src/KOKKOS/mliap_descriptor_so3_kokkos.cpp | 9 +++++++++ src/KOKKOS/mliap_descriptor_so3_kokkos.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp b/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp index 9f18078ac6..815d2696a9 100644 --- a/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp +++ b/src/KOKKOS/mliap_descriptor_so3_kokkos.cpp @@ -28,6 +28,7 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ + template MLIAPDescriptorSO3Kokkos::MLIAPDescriptorSO3Kokkos(LAMMPS *lmp, char *paramfilename) // TODO: why take self as param, shouldn't be needed @@ -39,6 +40,14 @@ MLIAPDescriptorSO3Kokkos::MLIAPDescriptorSO3Kokkos(LAMMPS *lmp, char /* ---------------------------------------------------------------------- */ +template +MLIAPDescriptorSO3Kokkos::~MLIAPDescriptorSO3Kokkos() +{ + delete so3ptr_kokkos; +} + +/* ---------------------------------------------------------------------- */ + template void MLIAPDescriptorSO3Kokkos::compute_descriptors(class MLIAPData *data_) { diff --git a/src/KOKKOS/mliap_descriptor_so3_kokkos.h b/src/KOKKOS/mliap_descriptor_so3_kokkos.h index 6676b60004..26b3462508 100644 --- a/src/KOKKOS/mliap_descriptor_so3_kokkos.h +++ b/src/KOKKOS/mliap_descriptor_so3_kokkos.h @@ -29,6 +29,7 @@ class MLIAPDescriptorSO3Kokkos : public MLIAPDescriptorKokkos { public: MLIAPDescriptorSO3Kokkos(LAMMPS *, char *); + ~MLIAPDescriptorSO3Kokkos() override; void compute_descriptors(class MLIAPData *) override; void compute_forces(class MLIAPData *) override; From 2a1fb835ade908a39253e61e635e20ca8a099c0e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 10:33:05 -0400 Subject: [PATCH 067/396] must not allocate eatom and vatom when called from KOKKOS version (which sets copymode to 1) --- src/ML-PACE/pair_pace.cpp | 3 ++- src/ML-PACE/pair_pace_extrapolation.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ML-PACE/pair_pace.cpp b/src/ML-PACE/pair_pace.cpp index 56dd34916f..79d2f92455 100644 --- a/src/ML-PACE/pair_pace.cpp +++ b/src/ML-PACE/pair_pace.cpp @@ -128,7 +128,8 @@ void PairPACE::compute(int eflag, int vflag) double fij[3]; int *ilist, *jlist, *numneigh, **firstneigh; - ev_init(eflag, vflag); + if (copymode) ev_init(eflag, vflag, 0); + else ev_init(eflag, vflag, 1); double **x = atom->x; double **f = atom->f; diff --git a/src/ML-PACE/pair_pace_extrapolation.cpp b/src/ML-PACE/pair_pace_extrapolation.cpp index 957e53d0ad..2946729905 100644 --- a/src/ML-PACE/pair_pace_extrapolation.cpp +++ b/src/ML-PACE/pair_pace_extrapolation.cpp @@ -131,7 +131,9 @@ void PairPACEExtrapolation::compute(int eflag, int vflag) double delx, dely, delz, evdwl; double fij[3]; int *ilist, *jlist, *numneigh, **firstneigh; - ev_init(eflag, vflag); + + if (copymode) ev_init(eflag, vflag, 0); + else ev_init(eflag, vflag, 1); // downwards modified by YL From 911b3eb8116ec14ad8d43afcf197584234c96126 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 11:16:58 -0400 Subject: [PATCH 068/396] cleanup format --- src/KOKKOS/memory_kokkos.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/KOKKOS/memory_kokkos.h b/src/KOKKOS/memory_kokkos.h index a94d9eb1e6..b57a048db7 100644 --- a/src/KOKKOS/memory_kokkos.h +++ b/src/KOKKOS/memory_kokkos.h @@ -1,4 +1,3 @@ -// clang-format off /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://www.lammps.org/, Sandia National Laboratories @@ -11,6 +10,7 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +// clang-format off #ifndef LMP_MEMORY_KOKKOS_H #define LMP_MEMORY_KOKKOS_H @@ -35,8 +35,7 @@ class MemoryKokkos : public Memory { ------------------------------------------------------------------------- */ template -TYPE create_kokkos(TYPE &data, typename TYPE::value_type *&array, - int n1, const char *name) +TYPE create_kokkos(TYPE &data, typename TYPE::value_type *&array, int n1, const char *name) { data = TYPE(name,n1); array = data.h_view.data(); @@ -44,8 +43,7 @@ TYPE create_kokkos(TYPE &data, typename TYPE::value_type *&array, } template - TYPE create_kokkos(TYPE &data, HTYPE &h_data, - typename TYPE::value_type *&array, int n1, + TYPE create_kokkos(TYPE &data, HTYPE &h_data, typename TYPE::value_type *&array, int n1, const char *name) { data = TYPE(std::string(name),n1); @@ -56,8 +54,7 @@ template template - TYPE create_kokkos(TYPE &data, HTYPE &h_data, - int n1, const char *name) + TYPE create_kokkos(TYPE &data, HTYPE &h_data, int n1, const char *name) { data = TYPE(std::string(name),n1); h_data = Kokkos::create_mirror_view(data); @@ -69,8 +66,7 @@ template ------------------------------------------------------------------------- */ template -TYPE grow_kokkos(TYPE &data, typename TYPE::value_type *&array, - int n1, const char *name) +TYPE grow_kokkos(TYPE &data, typename TYPE::value_type *&array, int n1, const char *name) { if (array == nullptr) return create_kokkos(data,array,n1,name); @@ -96,12 +92,11 @@ void destroy_kokkos(TYPE data, typename TYPE::value_type* &array) ------------------------------------------------------------------------- */ template - TYPE create_kokkos(TYPE &data, HTYPE &h_data, int n1, int n2, - const char *name) + TYPE create_kokkos(TYPE &data, HTYPE &h_data, int n1, int n2, const char *name) { data = TYPE(std::string(name),n1,n2); h_data = Kokkos::create_mirror_view(data); - //printf(">>> name: %s\n", name); + return data; } @@ -112,7 +107,6 @@ TYPE create_kokkos(TYPE &data, typename TYPE::value_type **&array, data = TYPE(std::string(name),n1,n2); bigint nbytes = ((bigint) sizeof(typename TYPE::value_type *)) * n1; array = (typename TYPE::value_type **) smalloc(nbytes,name); - //printf(">>> name %s nbytes %d\n", name, nbytes); for (int i = 0; i < n1; i++) { if (n2 == 0) From 6267389801bd808e57a1e7771388425cce8a34c2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 11:30:41 -0400 Subject: [PATCH 069/396] must force OMP_NUM_THREADS=1 for all tests to pass --- unittest/python/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/python/CMakeLists.txt b/unittest/python/CMakeLists.txt index 881c18423d..7eeba268e5 100644 --- a/unittest/python/CMakeLists.txt +++ b/unittest/python/CMakeLists.txt @@ -40,6 +40,7 @@ endif() list(APPEND PYTHON_TEST_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") list(APPEND PYTHON_TEST_ENVIRONMENT "PYTHONUNBUFFERED=1") list(APPEND PYTHON_TEST_ENVIRONMENT "PYTHONDONTWRITEBYTECODE=1") +list(APPEND PYTHON_TEST_ENVIRONMENT "OMP_NUM_THREADS=1") if(APPLE) list(APPEND PYTHON_TEST_ENVIRONMENT "DYLD_LIBRARY_PATH=${LAMMPS_LIB_PATH}:$ENV{DYLD_LIBRARY_PATH}") elseif(WIN32) From 7034e930fd5b13af551cd396a6f92bfebd8a3938 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 6 Apr 2025 15:03:39 -0400 Subject: [PATCH 070/396] update date --- tools/valgrind/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/valgrind/README b/tools/valgrind/README index 77479d52d3..acf6ce391c 100644 --- a/tools/valgrind/README +++ b/tools/valgrind/README @@ -37,4 +37,4 @@ Or you can create a file $HOME/.valgrindrc with one option per line: These options will be automatically added to the valgrind command line, so it becomes: valgrind lmp -in in.melt -Last update: 2025-04-04 +Last update: 2025-04-06 From 27ac8c0ea1f217d3788ae761faa74f7426c3fe3d Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 09:05:42 +0200 Subject: [PATCH 071/396] extract() implementation for dihedral opls --- doc/src/fix_adapt.rst | 2 ++ src/MOLECULE/dihedral_opls.cpp | 14 ++++++++++++++ src/MOLECULE/dihedral_opls.h | 1 + unittest/force-styles/tests/dihedral-opls.yaml | 6 +++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 681f9bb0af..2922a87b37 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -457,6 +457,8 @@ all types from 1 to :math:`N`. A leading asterisk means all types from If :doc:`dihedral_style hybrid ` is used, *dstyle* should be a sub-style name. The dihedral styles that currently work with fix adapt are: ++---------------------------------------------------------+----------------+----------------+ +| :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | +---------------------------------------------------------+----------------+----------------+ | :doc:`quadratic ` | k,phi0 | type dihedrals | +---------------------------------------------------------+----------------+----------------+ diff --git a/src/MOLECULE/dihedral_opls.cpp b/src/MOLECULE/dihedral_opls.cpp index 1ec2f869a5..0989e1d7e4 100644 --- a/src/MOLECULE/dihedral_opls.cpp +++ b/src/MOLECULE/dihedral_opls.cpp @@ -431,3 +431,17 @@ void DihedralOPLS::born_matrix(int nd, int i1, int i2, int i3, int i4, double &d 16.0 * k4[type] * si * cos(4.0 * phi) - 4.0 * k4[type] * sin(4.0 * phi)) / (si * si * si); } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralOPLS::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "k1") == 0) return (void *) k1; + if (strcmp(str, "k2") == 0) return (void *) k2; + if (strcmp(str, "k3") == 0) return (void *) k3; + if (strcmp(str, "k4") == 0) return (void *) k4; + return nullptr; + } diff --git a/src/MOLECULE/dihedral_opls.h b/src/MOLECULE/dihedral_opls.h index 82180cf323..9a483960cc 100644 --- a/src/MOLECULE/dihedral_opls.h +++ b/src/MOLECULE/dihedral_opls.h @@ -34,6 +34,7 @@ class DihedralOPLS : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *k1, *k2, *k3, *k4; diff --git a/unittest/force-styles/tests/dihedral-opls.yaml b/unittest/force-styles/tests/dihedral-opls.yaml index 7cf3578d1e..7a28a2d0fe 100644 --- a/unittest/force-styles/tests/dihedral-opls.yaml +++ b/unittest/force-styles/tests/dihedral-opls.yaml @@ -16,7 +16,11 @@ dihedral_coeff: ! | 3 56 10 32 84 4 23 80 61 83 5 19 90 13 15 -extract: ! "" +extract: ! | + k1 1 + k2 1 + k3 1 + k4 1 natoms: 29 init_energy: 2260.6834525285753 init_stress: ! |- From 55964c123330e5143b736b9992a0832ede68713b Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 09:11:42 +0200 Subject: [PATCH 072/396] extract() implementation for dihedral cosine squared restricted --- doc/src/fix_adapt.rst | 12 +++++++----- .../dihedral_cosine_squared_restricted.cpp | 12 ++++++++++++ .../dihedral_cosine_squared_restricted.h | 1 + .../tests/dihedral-cosine_squared_restricted.yaml | 4 +++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 2922a87b37..9dd8b0cd2f 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -457,11 +457,13 @@ all types from 1 to :math:`N`. A leading asterisk means all types from If :doc:`dihedral_style hybrid ` is used, *dstyle* should be a sub-style name. The dihedral styles that currently work with fix adapt are: -+---------------------------------------------------------+----------------+----------------+ -| :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | -+---------------------------------------------------------+----------------+----------------+ -| :doc:`quadratic ` | k,phi0 | type dihedrals | -+---------------------------------------------------------+----------------+----------------+ ++------------------------------------------------------------------------+----------------+----------------+ +| :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | ++------------------------------------------------------------------------+----------------+----------------+ +| :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | ++------------------------------------------------------------------------+----------------+----------------+ +| :doc:`quadratic ` | k,phi0 | type dihedrals | ++------------------------------------------------------------------------+----------------+----------------+ Note that internally, phi0 is stored in radians, so the variable this fix use to reset phi0 needs to generate values in radians. diff --git a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp index d8e34189d9..2edc87bb00 100644 --- a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp +++ b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp @@ -393,3 +393,15 @@ void DihedralCosineSquaredRestricted::born_matrix(int nd, int i1, int i2, int i3 du2 = 2 * k[type] * numerator / denominator; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralCosineSquaredRestricted::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "phi0") == 0) return (void *) phi0; + return nullptr; + } diff --git a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h index b9e2e1d9d8..f44d893cd0 100644 --- a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h +++ b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.h @@ -34,6 +34,7 @@ class DihedralCosineSquaredRestricted : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *k, *phi0; diff --git a/unittest/force-styles/tests/dihedral-cosine_squared_restricted.yaml b/unittest/force-styles/tests/dihedral-cosine_squared_restricted.yaml index 0e43bc1741..12098105c5 100644 --- a/unittest/force-styles/tests/dihedral-cosine_squared_restricted.yaml +++ b/unittest/force-styles/tests/dihedral-cosine_squared_restricted.yaml @@ -16,7 +16,9 @@ dihedral_coeff: ! | 3 15.0 -10.0 4 12.0 0.0 5 11.0 45.0 -extract: ! "" +extract: ! | + k 1 + phi0 1 natoms: 29 init_energy: 10643.96352037142 init_stress: ! |2- From e956e5ccdabe36620d7698a8fcccf346ae5848ef Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 09:24:44 +0200 Subject: [PATCH 073/396] extract() implementation for dihedral charmm and charmmfsw --- doc/src/fix_adapt.rst | 4 ++++ src/MOLECULE/dihedral_charmm.cpp | 13 +++++++++++++ src/MOLECULE/dihedral_charmm.h | 1 + src/MOLECULE/dihedral_charmmfsw.cpp | 13 +++++++++++++ src/MOLECULE/dihedral_charmmfsw.h | 1 + unittest/force-styles/tests/dihedral-charmm.yaml | 5 ++++- unittest/force-styles/tests/dihedral-charmmfsw.yaml | 5 ++++- 7 files changed, 40 insertions(+), 2 deletions(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 9dd8b0cd2f..3238f43f47 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -457,6 +457,10 @@ all types from 1 to :math:`N`. A leading asterisk means all types from If :doc:`dihedral_style hybrid ` is used, *dstyle* should be a sub-style name. The dihedral styles that currently work with fix adapt are: ++------------------------------------------------------------------------+----------------+----------------+ +| :doc:`charmm ` | k,n,d | type dihedrals | ++------------------------------------------------------------------------+----------------+----------------+ +| :doc:`charmmfsw ` | k,n,d | type dihedrals | +------------------------------------------------------------------------+----------------+----------------+ | :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | +------------------------------------------------------------------------+----------------+----------------+ diff --git a/src/MOLECULE/dihedral_charmm.cpp b/src/MOLECULE/dihedral_charmm.cpp index de6d59c1d4..2d8979493c 100644 --- a/src/MOLECULE/dihedral_charmm.cpp +++ b/src/MOLECULE/dihedral_charmm.cpp @@ -432,3 +432,16 @@ void DihedralCharmm::write_data(FILE *fp) for (int i = 1; i <= atom->ndihedraltypes; i++) fprintf(fp, "%d %g %d %d %g\n", i, k[i], multiplicity[i], shift[i], weight[i]); } + + /* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralCharmm::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + if (strcmp(str, "d") == 0) return (void *) shift; + return nullptr; + } diff --git a/src/MOLECULE/dihedral_charmm.h b/src/MOLECULE/dihedral_charmm.h index 71e857d5f0..d9af7a56cf 100644 --- a/src/MOLECULE/dihedral_charmm.h +++ b/src/MOLECULE/dihedral_charmm.h @@ -34,6 +34,7 @@ class DihedralCharmm : public Dihedral { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k, *weight, *cos_shift, *sin_shift; diff --git a/src/MOLECULE/dihedral_charmmfsw.cpp b/src/MOLECULE/dihedral_charmmfsw.cpp index a46fb8680c..1b249ea9e8 100644 --- a/src/MOLECULE/dihedral_charmmfsw.cpp +++ b/src/MOLECULE/dihedral_charmmfsw.cpp @@ -475,3 +475,16 @@ void DihedralCharmmfsw::write_data(FILE *fp) for (int i = 1; i <= atom->ndihedraltypes; i++) fprintf(fp, "%d %g %d %d %g\n", i, k[i], multiplicity[i], shift[i], weight[i]); } + + /* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralCharmmfsw::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + if (strcmp(str, "d") == 0) return (void *) shift; + return nullptr; + } diff --git a/src/MOLECULE/dihedral_charmmfsw.h b/src/MOLECULE/dihedral_charmmfsw.h index 3930034356..660dafcd08 100644 --- a/src/MOLECULE/dihedral_charmmfsw.h +++ b/src/MOLECULE/dihedral_charmmfsw.h @@ -34,6 +34,7 @@ class DihedralCharmmfsw : public Dihedral { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: int implicit, weightflag, dihedflag; diff --git a/unittest/force-styles/tests/dihedral-charmm.yaml b/unittest/force-styles/tests/dihedral-charmm.yaml index cf407709b0..ebd47e2f41 100644 --- a/unittest/force-styles/tests/dihedral-charmm.yaml +++ b/unittest/force-styles/tests/dihedral-charmm.yaml @@ -19,7 +19,10 @@ dihedral_coeff: ! | 3 56.0 0 110 0.0 4 23.0 1 180 0.5 5 19.0 3 90 1.0 -extract: ! "" +extract: ! | + k 1 + n 1 + d 1 natoms: 29 init_energy: 1317.959844120986 init_stress: ! |2- diff --git a/unittest/force-styles/tests/dihedral-charmmfsw.yaml b/unittest/force-styles/tests/dihedral-charmmfsw.yaml index 6d2035acc5..3e1e32f5e3 100644 --- a/unittest/force-styles/tests/dihedral-charmmfsw.yaml +++ b/unittest/force-styles/tests/dihedral-charmmfsw.yaml @@ -19,7 +19,10 @@ dihedral_coeff: ! | 3 56.0 0 110 0.0 4 23.0 1 180 0.5 5 19.0 3 90 1.0 -extract: ! "" +extract: ! | + k 1 + n 1 + d 1 natoms: 29 init_energy: 1317.959844120986 init_stress: ! |2- From 7655a4cb84480ed971cc9cd2a54629b58339a55d Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 09:30:44 +0200 Subject: [PATCH 074/396] extract() implementation for dihedral multi/harmonic --- doc/src/fix_adapt.rst | 2 ++ src/MOLECULE/dihedral_multi_harmonic.cpp | 16 ++++++++++++++++ src/MOLECULE/dihedral_multi_harmonic.h | 1 + .../tests/dihedral-multi_harmonic.yaml | 7 ++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 3238f43f47..709a22ad6c 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -464,6 +464,8 @@ sub-style name. The dihedral styles that currently work with fix adapt are: +------------------------------------------------------------------------+----------------+----------------+ | :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | +------------------------------------------------------------------------+----------------+----------------+ +| :doc:`multi/harmonic ` | a1,a2,a3,a4,a5 | type dihedrals | ++------------------------------------------------------------------------+----------------+----------------+ | :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | +------------------------------------------------------------------------+----------------+----------------+ | :doc:`quadratic ` | k,phi0 | type dihedrals | diff --git a/src/MOLECULE/dihedral_multi_harmonic.cpp b/src/MOLECULE/dihedral_multi_harmonic.cpp index a952d1ad41..89577fca9d 100644 --- a/src/MOLECULE/dihedral_multi_harmonic.cpp +++ b/src/MOLECULE/dihedral_multi_harmonic.cpp @@ -407,3 +407,19 @@ void DihedralMultiHarmonic::born_matrix(int nd, int i1, int i2, int i3, int i4, du = a2[type] + c * (2.0 * a3[type] + c * (3.0 * a4[type] + c * 4.0 * a5[type])); du2 = 2.0 * a3[type] + 6.0 * c * (a4[type] + 2.0 * a5[type] * c); } + + + /* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralMultiHarmonic::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "a1") == 0) return (void *) a1; + if (strcmp(str, "a2") == 0) return (void *) a2; + if (strcmp(str, "a3") == 0) return (void *) a3; + if (strcmp(str, "a4") == 0) return (void *) a4; + if (strcmp(str, "a5") == 0) return (void *) a5; + return nullptr; + } diff --git a/src/MOLECULE/dihedral_multi_harmonic.h b/src/MOLECULE/dihedral_multi_harmonic.h index b1f46bd4bf..1d0ef4a573 100644 --- a/src/MOLECULE/dihedral_multi_harmonic.h +++ b/src/MOLECULE/dihedral_multi_harmonic.h @@ -34,6 +34,7 @@ class DihedralMultiHarmonic : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *a1, *a2, *a3, *a4, *a5; diff --git a/unittest/force-styles/tests/dihedral-multi_harmonic.yaml b/unittest/force-styles/tests/dihedral-multi_harmonic.yaml index 567e61ad7f..dbbd054829 100644 --- a/unittest/force-styles/tests/dihedral-multi_harmonic.yaml +++ b/unittest/force-styles/tests/dihedral-multi_harmonic.yaml @@ -16,7 +16,12 @@ dihedral_coeff: ! | 3 56 10 32 84 52 4 23 80 61 83 74 5 19 90 13 15 58 -extract: ! "" +extract: ! | + a1 1 + a2 1 + a3 1 + a4 1 + a5 1 natoms: 29 init_energy: 2854.9857316566695 init_stress: ! |2- From e93709d34e714ed47bd3887bdab570a947cb61ac Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 11:20:53 +0200 Subject: [PATCH 075/396] extract() implementation for dihedral helix --- doc/src/fix_adapt.rst | 2 ++ src/EXTRA-MOLECULE/dihedral_helix.cpp | 13 +++++++++++++ src/EXTRA-MOLECULE/dihedral_helix.h | 1 + unittest/force-styles/tests/dihedral-helix.yaml | 5 ++++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index 709a22ad6c..ed611b2c7c 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -464,6 +464,8 @@ sub-style name. The dihedral styles that currently work with fix adapt are: +------------------------------------------------------------------------+----------------+----------------+ | :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | +------------------------------------------------------------------------+----------------+----------------+ +| :doc:`helix ` | a,b,c | type dihedrals | ++------------------------------------------------------------------------+----------------+----------------+ | :doc:`multi/harmonic ` | a1,a2,a3,a4,a5 | type dihedrals | +------------------------------------------------------------------------+----------------+----------------+ | :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | diff --git a/src/EXTRA-MOLECULE/dihedral_helix.cpp b/src/EXTRA-MOLECULE/dihedral_helix.cpp index 4693d29cd7..55ac8ee776 100644 --- a/src/EXTRA-MOLECULE/dihedral_helix.cpp +++ b/src/EXTRA-MOLECULE/dihedral_helix.cpp @@ -430,3 +430,16 @@ void DihedralHelix::born_matrix(int nd, int i1, int i2, int i3, int i4, du2 = -(9.0*bphi[type]*cos(3.0*phi) + cphi[type]*cos(phi + MY_PI4))*siinv*siinv + (3.0*bphi[type]*sin(3.0*phi) + cphi[type]*sin(phi + MY_PI4))*c*siinv*siinv*siinv; } + +/* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralHelix::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "a") == 0) return (void *) aphi; + if (strcmp(str, "b") == 0) return (void *) bphi; + if (strcmp(str, "c") == 0) return (void *) cphi; + return nullptr; + } diff --git a/src/EXTRA-MOLECULE/dihedral_helix.h b/src/EXTRA-MOLECULE/dihedral_helix.h index 172a8c3469..be7263f900 100644 --- a/src/EXTRA-MOLECULE/dihedral_helix.h +++ b/src/EXTRA-MOLECULE/dihedral_helix.h @@ -34,6 +34,7 @@ class DihedralHelix : public Dihedral { void read_restart(FILE *) override; void write_data(FILE *) override; void born_matrix(int, int, int, int, int, double &, double &) override; + void *extract(const char *, int &) override; protected: double *aphi, *bphi, *cphi; diff --git a/unittest/force-styles/tests/dihedral-helix.yaml b/unittest/force-styles/tests/dihedral-helix.yaml index e2372c8809..a6430b749b 100644 --- a/unittest/force-styles/tests/dihedral-helix.yaml +++ b/unittest/force-styles/tests/dihedral-helix.yaml @@ -16,7 +16,10 @@ dihedral_coeff: ! | 3 56 10 32 4 23 80 61 5 19 90 13 -extract: ! "" +extract: ! | + a 1 + b 1 + c 1 natoms: 29 init_energy: 4634.436545707672 init_stress: ! |- From 2b38b6d1c079dcecca320841dec2752fa4c89b26 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 11:35:20 +0200 Subject: [PATCH 076/396] extract() implementation for dihedral class2 --- doc/src/fix_adapt.rst | 32 ++++++++++--------- src/CLASS2/dihedral_class2.cpp | 15 +++++++++ src/CLASS2/dihedral_class2.h | 1 + .../force-styles/tests/dihedral-class2.yaml | 8 ++++- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/doc/src/fix_adapt.rst b/doc/src/fix_adapt.rst index ed611b2c7c..8fb103f5c6 100644 --- a/doc/src/fix_adapt.rst +++ b/doc/src/fix_adapt.rst @@ -457,21 +457,23 @@ all types from 1 to :math:`N`. A leading asterisk means all types from If :doc:`dihedral_style hybrid ` is used, *dstyle* should be a sub-style name. The dihedral styles that currently work with fix adapt are: -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`charmm ` | k,n,d | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`charmmfsw ` | k,n,d | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`helix ` | a,b,c | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`multi/harmonic ` | a1,a2,a3,a4,a5 | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ -| :doc:`quadratic ` | k,phi0 | type dihedrals | -+------------------------------------------------------------------------+----------------+----------------+ ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`charmm ` | k,n,d | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`charmmfsw ` | k,n,d | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`class2 ` | k1,k2,k3,phi1,phi2,phi3 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`cosine/squared/restricted ` | k,phi0 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`helix ` | a,b,c | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`multi/harmonic ` | a1,a2,a3,a4,a5 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`opls ` | k1,k2,k3,k4 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ +| :doc:`quadratic ` | k,phi0 | type dihedrals | ++------------------------------------------------------------------------+-------------------------+----------------+ Note that internally, phi0 is stored in radians, so the variable this fix use to reset phi0 needs to generate values in radians. diff --git a/src/CLASS2/dihedral_class2.cpp b/src/CLASS2/dihedral_class2.cpp index 9c4c1ad871..3ca8c52717 100644 --- a/src/CLASS2/dihedral_class2.cpp +++ b/src/CLASS2/dihedral_class2.cpp @@ -946,3 +946,18 @@ void DihedralClass2::write_data(FILE *fp) at_theta0_1[i]*180.0/MY_PI,at_theta0_2[i]*180.0/MY_PI); } +/* ---------------------------------------------------------------------- + return ptr to internal members upon request + ------------------------------------------------------------------------ */ + + void *DihedralClass2::extract(const char *str, int &dim) + { + dim = 1; + if (strcmp(str, "k1") == 0) return (void *) k1; + if (strcmp(str, "k2") == 0) return (void *) k2; + if (strcmp(str, "k3") == 0) return (void *) k3; + if (strcmp(str, "phi1") == 0) return (void *) phi1; + if (strcmp(str, "phi2") == 0) return (void *) phi2; + if (strcmp(str, "phi3") == 0) return (void *) phi3; + return nullptr; + } diff --git a/src/CLASS2/dihedral_class2.h b/src/CLASS2/dihedral_class2.h index ad42c5c3a1..d87dfb8a7b 100644 --- a/src/CLASS2/dihedral_class2.h +++ b/src/CLASS2/dihedral_class2.h @@ -33,6 +33,7 @@ class DihedralClass2 : public Dihedral { void write_restart(FILE *) override; void read_restart(FILE *) override; void write_data(FILE *) override; + void *extract(const char *, int &) override; protected: double *k1, *k2, *k3; diff --git a/unittest/force-styles/tests/dihedral-class2.yaml b/unittest/force-styles/tests/dihedral-class2.yaml index b041d4ebcb..572bc4e5d8 100644 --- a/unittest/force-styles/tests/dihedral-class2.yaml +++ b/unittest/force-styles/tests/dihedral-class2.yaml @@ -17,7 +17,13 @@ dihedral_coeff: ! | * at 75 42 31 75 42 31 120 50 * aat 75 120 160 * bb13 75 1.4 1.4 -extract: ! "" +extract: ! | + k1 1 + k2 1 + k3 1 + phi1 1 + phi2 1 + phi3 1 natoms: 29 init_energy: 3355.0074717375933 init_stress: ! |2- From 239eb64cbbff9a732178606bc88172d9ec1fa028 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 11:58:24 +0200 Subject: [PATCH 077/396] modifications in fix adapt.cpp --- src/fix_adapt.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp index eb7125caf7..6af96ae29e 100644 --- a/src/fix_adapt.cpp +++ b/src/fix_adapt.cpp @@ -19,6 +19,8 @@ #include "atom.h" #include "bond.h" #include "bond_hybrid.h" +#include "dihedral.h" +#include "dihedral_hybrid.h" #include "domain.h" #include "error.h" #include "fix_store_atom.h" @@ -43,14 +45,14 @@ using namespace LAMMPS_NS; using namespace FixConst; using namespace MathConst; -enum{PAIR, KSPACE, ATOM, BOND, ANGLE, IMPROPER}; +enum{PAIR, KSPACE, ATOM, BOND, ANGLE, DIHEDRAL, IMPROPER}; enum{DIAMETER, CHARGE}; /* ---------------------------------------------------------------------- */ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), nadapt(0), anypair(0), anybond(0), anyangle(0), - anyimproper(0), id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) + anydihedral(0), anyimproper(0), id_fix_diam(nullptr), id_fix_chg(nullptr), adapt(nullptr) { if (narg < 5) utils::missing_cmd_args(FLERR,"fix adapt", error); nevery = utils::inumeric(FLERR,arg[3],false,lmp); @@ -85,6 +87,10 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt angle", error); nadapt++; iarg += 5; + } else if (strcmp(arg[iarg],"dihedral") == 0) { + if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt dihedral", error); + nadapt++; + iarg += 5; } else if (strcmp(arg[iarg],"improper") == 0) { if (iarg+5 > narg) utils::missing_cmd_args(FLERR,"fix adapt improper", error); nadapt++; @@ -155,6 +161,19 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : nadapt++; iarg += 5; + } else if (strcmp(arg[iarg],"dihedral") == 0) { + adapt[nadapt].which = DIHEDRAL; + adapt[nadapt].dihedral = nullptr; + adapt[nadapt].dstyle = utils::strdup(arg[iarg+1]); + adapt[nadapt].dparam = utils::strdup(arg[iarg+2]); + utils::bounds_typelabel(FLERR, arg[iarg+3], 1, atom->ndihedraltypes, + adapt[nadapt].ilo, adapt[nadapt].ihi, lmp, Atom::DIHEDRAL); + if (utils::strmatch(arg[iarg+4],"^v_")) { + adapt[nadapt].var = utils::strdup(arg[iarg+4]+2); + } else error->all(FLERR,"Argument #{} must be variable not {}", iarg+5, arg[iarg+4]); + nadapt++; + iarg += 5; + } else if (strcmp(arg[iarg],"improper") == 0) { adapt[nadapt].which = IMPROPER; adapt[nadapt].improper = nullptr; @@ -246,6 +265,12 @@ FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : // allocate improper style arrays: + n = atom->ndihedraltypes; + for (int m = 0; m < nadapt; ++m) + if (adapt[m].which == DIHEDRAL) memory->create(adapt[m].vector_orig,n+1,"adapt:vector_orig"); + + // allocate improper style arrays: + n = atom->nimpropertypes; for (int m = 0; m < nadapt; ++m) if (adapt[m].which == IMPROPER) memory->create(adapt[m].vector_orig,n+1,"adapt:vector_orig"); @@ -270,6 +295,10 @@ FixAdapt::~FixAdapt() delete[] adapt[m].astyle; delete[] adapt[m].aparam; memory->destroy(adapt[m].vector_orig); + } else if (adapt[m].which == DIHEDRAL) { + delete[] adapt[m].dstyle; + delete[] adapt[m].dparam; + memory->destroy(adapt[m].vector_orig); } else if (adapt[m].which == IMPROPER) { delete[] adapt[m].istyle; delete[] adapt[m].iparam; @@ -368,6 +397,7 @@ void FixAdapt::init() anypair = 0; anybond = 0; anyangle = 0; + anydihedral = 0; anyimproper = 0; for (int m = 0; m < nadapt; m++) { @@ -509,6 +539,40 @@ void FixAdapt::init() delete[] astyle; + } else if (ad->which == DIHEDRAL) { + ad->dihedral = nullptr; + anydihedral = 1; + + char *dstyle = utils::strdup(ad->dstyle); + if (lmp->suffix_enable) + ad->dihedral = force->dihedral_match(fmt::format("{}/{}",dstyle,lmp->suffix)); + + if (ad->dihedral == nullptr) ad->dihedral = force->dihedral_match(dstyle); + if (ad->dihedral == nullptr ) + error->all(FLERR,"Fix adapt dihedral style {} does not exist", dstyle); + + void *ptr = ad->dihedral->extract(ad->dparam,ad->ddim); + + if (ptr == nullptr) + error->all(FLERR,"Fix adapt dihedral style parameter {} not supported", ad->dparam); + + // for dihedral styles, use a vector + + if (ad->ddim == 1) ad->vector = (double *) ptr; + + if (utils::strmatch(force->dihedral_style,"^hybrid")) { + auto dihedral = dynamic_cast(force->dihedral); + if (dihedral) { + for (i = ad->ilo; i <= ad->ihi; i++) { + if (!dihedral->check_itype(i,dstyle)) + error->all(FLERR,"Fix adapt type dihedral range is not valid " + "for dihedral hybrid sub-style {}", dstyle); + } + } + } + + delete[] dstyle; + } else if (ad->which == IMPROPER) { ad->improper = nullptr; anyimproper = 1; @@ -569,7 +633,7 @@ void FixAdapt::init() if (restart_reset) restart_reset = 0; - // make copy of original pair/bond/angle/improper array values + // make copy of original pair/bond/angle/dihedral/improper array values for (int m = 0; m < nadapt; m++) { Adapt *ad = &adapt[m]; @@ -588,6 +652,10 @@ void FixAdapt::init() for (i = ad->ilo; i <= ad->ihi; ++i ) ad->vector_orig[i] = ad->vector[i]; + } else if (ad->which == DIHEDRAL && ad->ddim == 1) { + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector_orig[i] = ad->vector[i]; + } else if (ad->which == IMPROPER && ad->idim == 1) { for (i = ad->ilo; i <= ad->ihi; ++i ) ad->vector_orig[i] = ad->vector[i]; @@ -710,6 +778,18 @@ void FixAdapt::change_settings() ad->vector[i] = value; } + // set dihedral type array values: + + } else if (ad->which == DIHEDRAL) { + if (ad->ddim == 1) { + if (scaleflag) + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector[i] = value*ad->vector_orig[i]; + else + for (i = ad->ilo; i <= ad->ihi; ++i ) + ad->vector[i] = value; + } + // set improper type array values: } else if (ad->which == IMPROPER) { @@ -797,6 +877,7 @@ void FixAdapt::change_settings() if (anypair) force->pair->reinit(); if (anybond) force->bond->reinit(); if (anyangle) force->angle->reinit(); + if (anydihedral) force->dihedral->reinit(); if (anyimproper) force->improper->reinit(); // reset KSpace charges if charges have changed @@ -832,6 +913,12 @@ void FixAdapt::restore_settings() ad->vector[i] = ad->vector_orig[i]; } + } else if (ad->which == DIHEDRAL) { + if (ad->ddim == 1) { + for (int i = ad->ilo; i <= ad->ihi; i++) + ad->vector[i] = ad->vector_orig[i]; + } + } else if (ad->which == IMPROPER) { if (ad->idim == 1) { for (int i = ad->ilo; i <= ad->ihi; i++) @@ -878,6 +965,7 @@ void FixAdapt::restore_settings() if (anypair) force->pair->reinit(); if (anybond) force->bond->reinit(); if (anyangle) force->angle->reinit(); + if (anydihedral) force->dihedral->reinit(); if (anyimproper) force->improper->reinit(); if (chgflag && force->kspace) force->kspace->qsum_qsq(); } From fe9915f3072fe16f11f8e637593276325aeb573e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 14:37:35 -0400 Subject: [PATCH 078/396] disable support for neighbors of ghosts. see also bff980b56faf7b98b422677bbc28a79b9d7da575 --- src/ML-IAP/pair_mliap.cpp | 9 +++++++-- unittest/force-styles/test_mliappy_unified.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ML-IAP/pair_mliap.cpp b/src/ML-IAP/pair_mliap.cpp index 5b569702d0..88d291a682 100644 --- a/src/ML-IAP/pair_mliap.cpp +++ b/src/ML-IAP/pair_mliap.cpp @@ -336,12 +336,17 @@ void PairMLIAP::v_tally(int i, int j, double *fij, double *rij) void PairMLIAP::init_style() { if (force->newton_pair == 0) - error->all(FLERR,"Pair style MLIAP requires newton pair on"); + error->all(FLERR, Error::NOLASTLINE, "Pair style mliap requires newton pair on"); // need a full neighbor list if (ghostneigh == 1) { - neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST); + // AK: 2025-04-07 nothing seems to be using this feature and it was leaking memory, too. + error->all(FLERR, Error::NOLASTLINE, + "Pair_style mliap does not support requesting neighbors of ghost atoms anymore.\n" + "If you have a model requiring this setting, please contact the LAMMPS developers" + + utils::errorurl(35)); + // neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST); } else { neighbor->add_request(this, NeighConst::REQ_FULL); } diff --git a/unittest/force-styles/test_mliappy_unified.cpp b/unittest/force-styles/test_mliappy_unified.cpp index a8309feb21..996d4d82d5 100644 --- a/unittest/force-styles/test_mliappy_unified.cpp +++ b/unittest/force-styles/test_mliappy_unified.cpp @@ -77,6 +77,11 @@ TEST(MliapUnified, VersusLJMelt) lammps_close(mliap); } +#if 0 + +// This setting was producing wrong results and leaking memory. +// Thus support for it was removed from LAMMPS. + TEST(MliapUnified, VersusLJMeltGhost) { const char *lmpargv[] = {"melt", "-log", "none", "-nocite"}; @@ -112,5 +117,5 @@ TEST(MliapUnified, VersusLJMeltGhost) lammps_close(ljmelt); lammps_close(mliap); } - +#endif } // namespace LAMMPS_NS From d012d13c1946a4367ae5f0c8c409aea3ea418d7f Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 20:52:55 +0200 Subject: [PATCH 079/396] fix typo in dihedral_quadratic.cpp --- src/EXTRA-MOLECULE/dihedral_quadratic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EXTRA-MOLECULE/dihedral_quadratic.cpp b/src/EXTRA-MOLECULE/dihedral_quadratic.cpp index e61f9eff74..27cf6e2ab6 100644 --- a/src/EXTRA-MOLECULE/dihedral_quadratic.cpp +++ b/src/EXTRA-MOLECULE/dihedral_quadratic.cpp @@ -443,7 +443,7 @@ void DihedralQuadratic::born_matrix(int nd, int i1, int i2, int i3, int i4, void *DihedralQuadratic::extract(const char *str, int &dim) { dim = 1; - if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "k") == 0) return (void *) k; if (strcmp(str, "phi0") == 0) return (void *) phi0; return nullptr; } From 7b0c5f3e04a964404731c4978d67f425587710d2 Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 21:07:52 +0200 Subject: [PATCH 080/396] Fix typo indihedral_charmmfsw.cpp --- src/MOLECULE/dihedral_charmmfsw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MOLECULE/dihedral_charmmfsw.cpp b/src/MOLECULE/dihedral_charmmfsw.cpp index 1b249ea9e8..2415dff8cd 100644 --- a/src/MOLECULE/dihedral_charmmfsw.cpp +++ b/src/MOLECULE/dihedral_charmmfsw.cpp @@ -483,7 +483,7 @@ void DihedralCharmmfsw::write_data(FILE *fp) void *DihedralCharmmfsw::extract(const char *str, int &dim) { dim = 1; - if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "k") == 0) return (void *) k; if (strcmp(str, "n") == 0) return (void *) multiplicity; if (strcmp(str, "d") == 0) return (void *) shift; return nullptr; From 809d5b5b93a2a0413c5e61e272ad04b842fe430f Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Mon, 7 Apr 2025 21:08:35 +0200 Subject: [PATCH 081/396] Fix typo in dihedral_charmm.cpp --- src/MOLECULE/dihedral_charmm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MOLECULE/dihedral_charmm.cpp b/src/MOLECULE/dihedral_charmm.cpp index 2d8979493c..1ec29da780 100644 --- a/src/MOLECULE/dihedral_charmm.cpp +++ b/src/MOLECULE/dihedral_charmm.cpp @@ -440,7 +440,7 @@ void DihedralCharmm::write_data(FILE *fp) void *DihedralCharmm::extract(const char *str, int &dim) { dim = 1; - if (strcmp(str, "k") == 0) return (void *) k0; + if (strcmp(str, "k") == 0) return (void *) k; if (strcmp(str, "n") == 0) return (void *) multiplicity; if (strcmp(str, "d") == 0) return (void *) shift; return nullptr; From 499192a1b2eba5c0aa6cdb6c1bb79faaa92a29db Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 16:27:16 -0400 Subject: [PATCH 082/396] restore option to request neighbor lists with neighbors of ghosts --- src/ML-IAP/pair_mliap.cpp | 9 +++------ unittest/force-styles/test_mliappy_unified.cpp | 6 ------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/ML-IAP/pair_mliap.cpp b/src/ML-IAP/pair_mliap.cpp index 88d291a682..4858c7e0ea 100644 --- a/src/ML-IAP/pair_mliap.cpp +++ b/src/ML-IAP/pair_mliap.cpp @@ -73,6 +73,7 @@ PairMLIAP::~PairMLIAP() memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(map); + memory->destroy(cutghost); } } @@ -125,6 +126,7 @@ void PairMLIAP::allocate() memory->create(setflag,n+1,n+1,"pair:setflag"); memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(map,n+1,"pair:map"); + if (ghostneigh) memory->create(cutghost, n+1, n+1, "pair:cutghost"); } /* ---------------------------------------------------------------------- @@ -341,12 +343,7 @@ void PairMLIAP::init_style() // need a full neighbor list if (ghostneigh == 1) { - // AK: 2025-04-07 nothing seems to be using this feature and it was leaking memory, too. - error->all(FLERR, Error::NOLASTLINE, - "Pair_style mliap does not support requesting neighbors of ghost atoms anymore.\n" - "If you have a model requiring this setting, please contact the LAMMPS developers" - + utils::errorurl(35)); - // neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST); + neighbor->add_request(this, NeighConst::REQ_FULL | NeighConst::REQ_GHOST); } else { neighbor->add_request(this, NeighConst::REQ_FULL); } diff --git a/unittest/force-styles/test_mliappy_unified.cpp b/unittest/force-styles/test_mliappy_unified.cpp index 996d4d82d5..53cb07cb0f 100644 --- a/unittest/force-styles/test_mliappy_unified.cpp +++ b/unittest/force-styles/test_mliappy_unified.cpp @@ -77,11 +77,6 @@ TEST(MliapUnified, VersusLJMelt) lammps_close(mliap); } -#if 0 - -// This setting was producing wrong results and leaking memory. -// Thus support for it was removed from LAMMPS. - TEST(MliapUnified, VersusLJMeltGhost) { const char *lmpargv[] = {"melt", "-log", "none", "-nocite"}; @@ -117,5 +112,4 @@ TEST(MliapUnified, VersusLJMeltGhost) lammps_close(ljmelt); lammps_close(mliap); } -#endif } // namespace LAMMPS_NS From bfd496bee7faa95f8f1c28e639bcdd36a24b8203 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 17:59:12 -0400 Subject: [PATCH 083/396] plug memory leaks in pyx files --- src/KOKKOS/mliap_unified_couple_kokkos.pyx | 2 ++ src/ML-IAP/mliap_unified_couple.pyx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/KOKKOS/mliap_unified_couple_kokkos.pyx b/src/KOKKOS/mliap_unified_couple_kokkos.pyx index 16fdefdb83..1492962013 100644 --- a/src/KOKKOS/mliap_unified_couple_kokkos.pyx +++ b/src/KOKKOS/mliap_unified_couple_kokkos.pyx @@ -543,6 +543,8 @@ cdef public object mliap_unified_connect_kokkos(char *fname, MLIAPDummyModel * m unified_int.descriptor.set_elements(elements, nelements) unified_int.model.nelements = nelements + for i, elem in enumerate(unified.element_types): + free(elements[i]) free(elements) return unified_int diff --git a/src/ML-IAP/mliap_unified_couple.pyx b/src/ML-IAP/mliap_unified_couple.pyx index 6c8331d0fa..891ba8e28a 100644 --- a/src/ML-IAP/mliap_unified_couple.pyx +++ b/src/ML-IAP/mliap_unified_couple.pyx @@ -411,6 +411,8 @@ cdef public object mliap_unified_connect(char *fname, MLIAPDummyModel * model, unified_int.descriptor.set_elements(elements, nelements) unified_int.model.nelements = nelements + for i, elem in enumerate(unified.element_types): + free(elements[i]) free(elements) return unified_int From 52ce35adbc44d399285d82ca6bf0effabe19a11a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 17:59:45 -0400 Subject: [PATCH 084/396] make sure cutghost is initialized --- src/ML-IAP/pair_mliap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ML-IAP/pair_mliap.cpp b/src/ML-IAP/pair_mliap.cpp index 4858c7e0ea..ecf216e8e0 100644 --- a/src/ML-IAP/pair_mliap.cpp +++ b/src/ML-IAP/pair_mliap.cpp @@ -361,6 +361,7 @@ double PairMLIAP::init_one(int i, int j) "All pair coeffs are not set. Status\n" + Info::get_pair_coeff_status(lmp)); double cutmax = sqrt(descriptor->cutsq[map[i]][map[j]]); + if (ghostneigh) cutghost[i][j] = cutghost[j][i] = cutmax; return cutmax; } From 6c337ba65577dc94f6353161bea8d78345ce4151 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 18:00:56 -0400 Subject: [PATCH 085/396] manage cutghost array for KOKKOS, if requested by pair style command --- src/KOKKOS/pair_mliap_kokkos.cpp | 2 ++ src/KOKKOS/pair_mliap_kokkos.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/KOKKOS/pair_mliap_kokkos.cpp b/src/KOKKOS/pair_mliap_kokkos.cpp index 8c06e7983d..338afe4e42 100644 --- a/src/KOKKOS/pair_mliap_kokkos.cpp +++ b/src/KOKKOS/pair_mliap_kokkos.cpp @@ -57,6 +57,7 @@ PairMLIAPKokkos::~PairMLIAPKokkos() memoryKK->destroy_kokkos(k_setflag, setflag); memoryKK->destroy_kokkos(k_eatom, eatom); memoryKK->destroy_kokkos(k_vatom, vatom); + if (ghostneigh) memoryKK->destroy_kokkos(k_cutghost, cutghost); delete model; delete descriptor; model=nullptr; @@ -147,6 +148,7 @@ void PairMLIAPKokkos::allocate() memoryKK->create_kokkos(k_cutsq, cutsq, n+1, n+1, "pair_mliap:cutsq"); memoryKK->create_kokkos(k_setflag, setflag, n+1, n+1, "pair_mliap:setflag"); + if (ghostneigh) memoryKK->create_kokkos(k_cutghost, cutghost, n+1, n+1, "pair_mliap:cutghost"); // this is for the base class so it doesn't double delete allocated = 1; } diff --git a/src/KOKKOS/pair_mliap_kokkos.h b/src/KOKKOS/pair_mliap_kokkos.h index cbef6e5966..3f56a89692 100644 --- a/src/KOKKOS/pair_mliap_kokkos.h +++ b/src/KOKKOS/pair_mliap_kokkos.h @@ -108,6 +108,7 @@ public: typename AT::t_f_array f; DAT::tdual_int_1d k_map; DAT::tdual_double_2d k_cutsq; + DAT::tdual_double_2d k_cutghost; DAT::tdual_int_2d k_setflag; DAT::tdual_efloat_1d k_eatom; DAT::tdual_double_2d k_vatom; From 8ea6c5c395bd95c5777d78eb99be3ebe431c4f70 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 18:05:35 -0400 Subject: [PATCH 086/396] avoid memory leak for element names --- src/ML-IAP/mliap_descriptor.cpp | 3 ++- src/ML-IAP/mliap_descriptor_ace.cpp | 2 +- src/ML-IAP/mliap_unified.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ML-IAP/mliap_descriptor.cpp b/src/ML-IAP/mliap_descriptor.cpp index 615cd75102..017d36e5e7 100644 --- a/src/ML-IAP/mliap_descriptor.cpp +++ b/src/ML-IAP/mliap_descriptor.cpp @@ -35,7 +35,8 @@ MLIAPDescriptor::MLIAPDescriptor(LAMMPS *lmp) : MLIAPDescriptor::~MLIAPDescriptor() { - for (int i = 0; i < nelements; i++) delete[] elements[i]; + if (allocated_elements) + for (int i = 0; i < nelements; i++) delete[] elements[i]; delete[] elements; memory->destroy(cutsq); memory->destroy(radelem); diff --git a/src/ML-IAP/mliap_descriptor_ace.cpp b/src/ML-IAP/mliap_descriptor_ace.cpp index b13699193c..9b5d473123 100644 --- a/src/ML-IAP/mliap_descriptor_ace.cpp +++ b/src/ML-IAP/mliap_descriptor_ace.cpp @@ -82,7 +82,7 @@ MLIAPDescriptorACE::MLIAPDescriptorACE(LAMMPS *_lmp, char *yacefilename) : for (int iielem = 0; iielem < nelements; iielem++) delete[] elements[iielem]; delete[] elements; allocated_elements = 0; - } else if (not allocated_elements) { + } else if (!allocated_elements) { elements = new char *[nelements]; for (int iielem = 0; iielem < nelements; iielem++) { elements[iielem] = utils::strdup(acemlimpl->basis_set->elements_name[iielem]); diff --git a/src/ML-IAP/mliap_unified.cpp b/src/ML-IAP/mliap_unified.cpp index a7970022f4..d95bd060d7 100644 --- a/src/ML-IAP/mliap_unified.cpp +++ b/src/ML-IAP/mliap_unified.cpp @@ -111,7 +111,8 @@ void MLIAPDummyDescriptor::set_elements(char **elems, int nelems) { nelements = nelems; elements = new char *[nelems]; - for (int i = 0; i < nelems; i++) { elements[i] = utils::strdup(elems[i]); } + for (int i = 0; i < nelems; i++) elements[i] = utils::strdup(elems[i]); + allocated_elements = 1; } /* ---------------------------------------------------------------------- */ From c505bfbdfeea5cdc1943a46cf0fa3c85b2175065 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 18:06:07 -0400 Subject: [PATCH 087/396] make sure OpenMP has a sufficient number of threads allocated --- unittest/force-styles/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/force-styles/CMakeLists.txt b/unittest/force-styles/CMakeLists.txt index fb6cd1a63b..5eb4c0ee8e 100644 --- a/unittest/force-styles/CMakeLists.txt +++ b/unittest/force-styles/CMakeLists.txt @@ -71,6 +71,7 @@ endif() list(APPEND FORCE_TEST_ENVIRONMENT "PYTHONUNBUFFERED=1") list(APPEND FORCE_TEST_ENVIRONMENT "PYTHONDONTWRITEBYTECODE=1") list(APPEND FORCE_TEST_ENVIRONMENT "OMP_PROC_BIND=false") +list(APPEND FORCE_TEST_ENVIRONMENT "OMP_NUM_THREADS=4") list(APPEND FORCE_TEST_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(BUILD_IS_MULTI_CONFIG) From 99b484a0ccc5c4157f1a6dfe57a968a4354a9807 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 18:06:31 -0400 Subject: [PATCH 088/396] add Kokkos/OpenMP version of mliap unified test --- .../force-styles/test_mliappy_unified.cpp | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/unittest/force-styles/test_mliappy_unified.cpp b/unittest/force-styles/test_mliappy_unified.cpp index 53cb07cb0f..412ea3b22a 100644 --- a/unittest/force-styles/test_mliappy_unified.cpp +++ b/unittest/force-styles/test_mliappy_unified.cpp @@ -13,6 +13,8 @@ #include "library.h" +#include "info.h" + #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -112,4 +114,94 @@ TEST(MliapUnified, VersusLJMeltGhost) lammps_close(ljmelt); lammps_close(mliap); } +TEST(MliapUnified, VersusLJMeltKokkos) +{ + if (!LAMMPS::is_installed_pkg("KOKKOS")) GTEST_SKIP(); + if (!Info::has_accelerator_feature("KOKKOS", "api", "openmp")) GTEST_SKIP(); + // if KOKKOS has GPU support enabled, it *must* be used. We cannot test OpenMP only. + if (Info::has_accelerator_feature("KOKKOS", "api", "cuda") || + Info::has_accelerator_feature("KOKKOS", "api", "hip") || + Info::has_accelerator_feature("KOKKOS", "api", "sycl")) { + GTEST_SKIP() << "Cannot test KOKKOS/OpenMP with GPU support enabled"; + } + + const char *lmpargv[] = {"melt", "-log", "none", "-echo", "screen", "-nocite", + "-k", "on", "t", "4", "-sf", "kk"}; + int lmpargc = sizeof(lmpargv) / sizeof(const char *); + + void *ljmelt = lammps_open_no_mpi(lmpargc, (char **)lmpargv, nullptr); + void *mliap = lammps_open_no_mpi(lmpargc, (char **)lmpargv, nullptr); + + lammps_commands_string(ljmelt, first); + lammps_command(ljmelt, "pair_style lj/cut 2.5"); + lammps_command(ljmelt, "pair_coeff * * 1.0 1.0"); + lammps_commands_string(ljmelt, second); + + lammps_command(mliap, pickle); + lammps_command(mliap, "python create_pickle invoke"); + + lammps_commands_string(mliap, first); + lammps_command(mliap, "pair_style mliap unified mliap_unified_lj_Ar.pkl 0"); + lammps_command(mliap, "pair_coeff * * Ar"); + lammps_commands_string(mliap, second); + + double lj_pe = lammps_get_thermo(ljmelt, "pe"); + double ml_pe = lammps_get_thermo(mliap, "pe"); + EXPECT_NEAR(lj_pe, ml_pe, 1.0e-14); + double lj_ke = lammps_get_thermo(ljmelt, "ke"); + double ml_ke = lammps_get_thermo(mliap, "ke"); + EXPECT_NEAR(lj_ke, ml_ke, 1.0e-14); + double lj_press = lammps_get_thermo(ljmelt, "press"); + double ml_press = lammps_get_thermo(mliap, "press"); + EXPECT_NEAR(lj_press, ml_press, 1.0e-14); + + lammps_command(mliap, "shell rm mliap_unified_lj_Ar.pkl"); + lammps_close(ljmelt); + lammps_close(mliap); +} +TEST(MliapUnified, VersusLJMeltGhostKokkos) +{ + if (!LAMMPS::is_installed_pkg("KOKKOS")) GTEST_SKIP(); + if (!Info::has_accelerator_feature("KOKKOS", "api", "openmp")) GTEST_SKIP(); + // if KOKKOS has GPU support enabled, it *must* be used. We cannot test OpenMP only. + if (Info::has_accelerator_feature("KOKKOS", "api", "cuda") || + Info::has_accelerator_feature("KOKKOS", "api", "hip") || + Info::has_accelerator_feature("KOKKOS", "api", "sycl")) { + GTEST_SKIP() << "Cannot test KOKKOS/OpenMP with GPU support enabled"; + } + + const char *lmpargv[] = {"melt", "-log", "none", "-echo", "screen", "-nocite", + "-k", "on", "t", "4", "-sf", "kk"}; + int lmpargc = sizeof(lmpargv) / sizeof(const char *); + + void *ljmelt = lammps_open_no_mpi(lmpargc, (char **)lmpargv, nullptr); + void *mliap = lammps_open_no_mpi(lmpargc, (char **)lmpargv, nullptr); + + lammps_commands_string(ljmelt, first); + lammps_command(ljmelt, "pair_style lj/cut 2.5"); + lammps_command(ljmelt, "pair_coeff * * 1.0 1.0"); + lammps_commands_string(ljmelt, second); + + lammps_command(mliap, pickle); + lammps_command(mliap, "python create_pickle invoke"); + + lammps_commands_string(mliap, first); + lammps_command(mliap, "pair_style mliap unified mliap_unified_lj_Ar.pkl 1"); + lammps_command(mliap, "pair_coeff * * Ar"); + lammps_commands_string(mliap, second); + + double lj_pe = lammps_get_thermo(ljmelt, "pe"); + double ml_pe = lammps_get_thermo(mliap, "pe"); + EXPECT_NEAR(lj_pe, ml_pe, 1.0e-14); + double lj_ke = lammps_get_thermo(ljmelt, "ke"); + double ml_ke = lammps_get_thermo(mliap, "ke"); + EXPECT_NEAR(lj_ke, ml_ke, 1.0e-14); + double lj_press = lammps_get_thermo(ljmelt, "press"); + double ml_press = lammps_get_thermo(mliap, "press"); + EXPECT_NEAR(lj_press, ml_press, 1.0e-14); + + lammps_command(mliap, "shell rm mliap_unified_lj_Ar.pkl"); + lammps_close(ljmelt); + lammps_close(mliap); +} } // namespace LAMMPS_NS From dcb04032fb63c822c144f78c1072513342c35c1b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 18:18:16 -0400 Subject: [PATCH 089/396] avoid memory leak on element names --- src/ML-IAP/mliap_descriptor_snap.cpp | 7 +++++-- src/ML-IAP/mliap_descriptor_so3.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ML-IAP/mliap_descriptor_snap.cpp b/src/ML-IAP/mliap_descriptor_snap.cpp index e8f6eec977..90590d50d4 100644 --- a/src/ML-IAP/mliap_descriptor_snap.cpp +++ b/src/ML-IAP/mliap_descriptor_snap.cpp @@ -363,8 +363,10 @@ void MLIAPDescriptorSNAP::read_paramfile(char *paramfilename) int sinnerflag = 0; int dinnerflag = 0; - for (int i = 0; i < nelements; i++) delete[] elements[i]; - delete[] elements; + if (elements) { + for (int i = 0; i < nelements; i++) delete[] elements[i]; + delete[] elements; + } memory->destroy(radelem); memory->destroy(wjelem); memory->destroy(cutsq); @@ -422,6 +424,7 @@ void MLIAPDescriptorSNAP::read_paramfile(char *paramfilename) for (int ielem = 0; ielem < nelements; ielem++) elements[ielem] = utils::strdup(words.next()); elementsflag = 1; + allocated_elements = 1; } else if (keywd == "radelems") { for (int ielem = 0; ielem < nelements; ielem++) radelem[ielem] = utils::numeric(FLERR, words.next(), false, lmp); diff --git a/src/ML-IAP/mliap_descriptor_so3.cpp b/src/ML-IAP/mliap_descriptor_so3.cpp index 676c53a4a8..a8b086cc03 100644 --- a/src/ML-IAP/mliap_descriptor_so3.cpp +++ b/src/ML-IAP/mliap_descriptor_so3.cpp @@ -73,8 +73,10 @@ void MLIAPDescriptorSO3::read_paramfile(char *paramfilename) rfac0 = 0.99363; rmin0 = 0.0; - for (int i = 0; i < nelements; i++) delete[] elements[i]; - delete[] elements; + if (elements) { + for (int i = 0; i < nelements; i++) delete[] elements[i]; + delete[] elements; + } memory->destroy(radelem); memory->destroy(wjelem); memory->destroy(cutsq); @@ -138,6 +140,7 @@ void MLIAPDescriptorSO3::read_paramfile(char *paramfilename) } elementsflag = 1; + allocated_elements = 1; } else if (skeywd == "radelems") { for (int ielem = 0; ielem < nelements; ielem++) { radelem[ielem] = utils::numeric(FLERR, skeyval, false, lmp); From 319e14c8e300e76135cbb2baf1db29bdd2bf9553 Mon Sep 17 00:00:00 2001 From: Gabriel Alkuino <107645552+gsalkuin@users.noreply.github.com> Date: Mon, 7 Apr 2025 18:28:33 -0400 Subject: [PATCH 090/396] Update atom->quat in fix_rigid.cpp --- src/RIGID/fix_rigid.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/RIGID/fix_rigid.cpp b/src/RIGID/fix_rigid.cpp index b0c6d46ee4..95c274e8e3 100644 --- a/src/RIGID/fix_rigid.cpp +++ b/src/RIGID/fix_rigid.cpp @@ -1516,6 +1516,11 @@ void FixRigid::set_xv() MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone, inertiaatom,angmom_one[i]); } + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::quatquat(quat[ibody],orient[i],quatatom); + MathExtra::qnormalize(quatatom); + } if (eflags[i] & DIPOLE) { MathExtra::quat_to_mat(quat[ibody],p); MathExtra::matvec(p,dorient[i],mu[i]); @@ -1713,7 +1718,7 @@ void FixRigid::setup_bodies_static() } // grow extended arrays and set extended flags for each particle - // orientflag = 4 if any particle stores ellipsoid or tri orientation + // orientflag = 4 if any particle stores ellipsoid or tri orientation or quat // orientflag = 1 if any particle stores line orientation // dorientflag = 1 if any particle stores dipole orientation @@ -1721,6 +1726,7 @@ void FixRigid::setup_bodies_static() if (atom->ellipsoid_flag) orientflag = 4; if (atom->line_flag) orientflag = 1; if (atom->tri_flag) orientflag = 4; + if (atom->quat_flag) orientflag = 4; if (atom->mu_flag) dorientflag = 1; grow_arrays(atom->nmax); @@ -2061,7 +2067,12 @@ void FixRigid::setup_bodies_static() ez_space[ibody],delta,displace[i]); if (extended) { - if (eflags[i] & ELLIPSOID) { + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::qconjugate(quat[ibody],qc); + MathExtra::quatquat(qc,quatatom,orient[i]); + MathExtra::qnormalize(orient[i]); + } else if (eflags[i] & ELLIPSOID) { quatatom = ebonus[ellipsoid[i]].quat; MathExtra::qconjugate(quat[ibody],qc); MathExtra::quatquat(qc,quatatom,orient[i]); From 641d496d4b075b9feeb08006af5b08d53fbe864e Mon Sep 17 00:00:00 2001 From: talinke Date: Mon, 7 Apr 2025 17:36:48 -0700 Subject: [PATCH 091/396] Refined keyword options --- src/EXTRA-FIX/fix_langevin_gjf.cpp | 706 +++++++++++++++++++++++++++++ src/EXTRA-FIX/fix_langevin_gjf.h | 85 ++++ 2 files changed, 791 insertions(+) create mode 100644 src/EXTRA-FIX/fix_langevin_gjf.cpp create mode 100644 src/EXTRA-FIX/fix_langevin_gjf.h diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp new file mode 100644 index 0000000000..7f38a4d201 --- /dev/null +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -0,0 +1,706 @@ +/* ---------------------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Tim Linke & Niels Gronbech-Jensen (UC Davis) +------------------------------------------------------------------------- */ + +#include "fix_langevin.h" + +#include "atom.h" +#include "atom_vec_ellipsoid.h" +#include "comm.h" +#include "compute.h" +#include "error.h" +#include "force.h" +#include "group.h" +#include "input.h" +#include "math_extra.h" +#include "memory.h" +#include "modify.h" +#include "random_mars.h" +#include "respa.h" +#include "update.h" +#include "variable.h" + +#include +#include + +using namespace LAMMPS_NS; +using namespace FixConst; + +enum { NOBIAS, BIAS }; +enum { CONSTANT, EQUAL, ATOM }; + +/* ---------------------------------------------------------------------- */ + +FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), gjfflag(0), gfactor1(nullptr), gfactor2(nullptr), ratio(nullptr), + tstr(nullptr), flangevin(nullptr), tforce(nullptr), lv(nullptr), id_temp(nullptr), random(nullptr) +{ + if (narg < 8) error->all(FLERR, "Illegal fix langevin/gjf command"); + + time_integrate = 1; + restart_peratom = 1; + // dynamic_group_allow = 1; + // scalar_flag = 1; + // global_freq = 1; + // extscalar = 1; + // ecouple_flag = 1; + nevery = 1; + + if (utils::strmatch(arg[3], "^v_")) { + tstr = utils::strdup(arg[3] + 2); + } else { + t_start = utils::numeric(FLERR, arg[3], false, lmp); + t_target = t_start; + tstyle = CONSTANT; + } + + t_stop = utils::numeric(FLERR, arg[4], false, lmp); + t_period = utils::numeric(FLERR, arg[5], false, lmp); + seed = utils::inumeric(FLERR, arg[6], false, lmp); + + if (t_period <= 0.0) error->all(FLERR, "Fix langevin/gjf period must be > 0.0"); + if (seed <= 0) error->all(FLERR, "Illegal fix langevin/gjf command"); + + // initialize Marsaglia RNG with processor-unique seed + + random = new RanMars(lmp, seed + comm->me); + + // allocate per-type arrays for force prefactors + + // gfactor1 = new double[atom->ntypes + 1]; + // gfactor2 = new double[atom->ntypes + 1]; + // ratio = new double[atom->ntypes + 1]; + int GJmethods = 8 // number of currently implemented GJ methods + + // optional args + + for (int i = 1; i <= atom->ntypes; i++) ratio[i] = 1.0; + osflag = 0; + GJmethod = 0; + + int iarg = 7; + while (iarg < narg) { + if (strcmp(arg[iarg], "vel") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix langevin/gjf command"); + if (strcmp(arg[iarg + 1], "vfull") == 0) { + osflag = 1; + } else if (strcmp(arg[iarg + 1], "vhalf") == 0) { + osflag = 0; + } else + error->all(FLERR, "Illegal fix langevin/gjf command"); + iarg += 2; + } else if (strcmp(arg[iarg], "method") == 0) { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix langevin/gjf command"); + GJmethod = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); + if (GJmethod <= 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in langevin/gjf command"); + iarg += 2; + } else + error->all(FLERR, "Illegal fix langevin/gjf command"); + } + + // set temperature = nullptr, user can override via fix_modify if wants bias + + id_temp = nullptr; + temperature = nullptr; + + energy = 0.0; + + // flangevin is unallocated until first call to setup() + // compute_scalar checks for this and returns 0.0 + // if flangevin_allocated is not set + + flangevin = nullptr; + flangevin_allocated = 0; + lv = nullptr; + tforce = nullptr; + maxatom1 = maxatom2 = 0; + + // setup atom-based array for lv + // register with Atom class + // no need to set peratom_flag, b/c data is for internal use only + + + FixLangevin::grow_arrays(atom->nmax); + atom->add_callback(Atom::GROW); + + // initialize lv to zero + + int nlocal = atom->nlocal; + for (int i = 0; i < nlocal; i++) { + lv[i][0] = 0.0; + lv[i][1] = 0.0; + lv[i][2] = 0.0; + } +} + +/* ---------------------------------------------------------------------- */ + +FixLangevin::~FixLangevin() +{ + if (copymode) return; + + delete random; + delete[] tstr; + delete[] gfactor1; + delete[] gfactor2; + delete[] ratio; + delete[] id_temp; + memory->destroy(flangevin); + memory->destroy(tforce); + + memory->destroy(lv); + if (modify->get_fix_by_id(id)) atom->delete_callback(id, Atom::GROW); +} + +/* ---------------------------------------------------------------------- */ + +int FixLangevin::setmask() +{ + int mask = 0; + mask |= INITIAL_INTEGRATE; + mask |= FINAL_INTEGRATE; + mask |= END_OF_STEP; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixLangevin::init() +{ + if (id_temp) { + temperature = modify->get_compute_by_id(id_temp); + if (!temperature) { + error->all(FLERR, "Temperature compute ID {} for fix {} does not exist", id_temp, style); + } else { + if (temperature->tempflag == 0) + error->all(FLERR, "Compute ID {} for fix {} does not compute temperature", id_temp, style); + } + } + // check variable + + if (tstr) { + tvar = input->variable->find(tstr); + if (tvar < 0) error->all(FLERR, "Variable name {} for fix langevin does not exist", tstr); + if (input->variable->equalstyle(tvar)) + tstyle = EQUAL; + else if (input->variable->atomstyle(tvar)) + tstyle = ATOM; + else + error->all(FLERR, "Variable {} for fix langevin is invalid style", tstr); + } + + // set force prefactors + + if (!atom->rmass) { + for (int i = 1; i <= atom->ntypes; i++) { + gfactor1[i] = -atom->mass[i] / t_period / force->ftm2v; + gfactor2[i] = sqrt(atom->mass[i]) / force->ftm2v; + gfactor2[i] *= sqrt(2.0 * update->dt * force->boltz / t_period / force->mvv2e); // gjfflag + } + } + + if (temperature && temperature->tempbias) + tbiasflag = BIAS; + else + tbiasflag = NOBIAS; + + if (utils::strmatch(update->integrate_style, "^respa")) { + nlevels_respa = (static_cast(update->integrate))->nlevels; + if (gjfflag) error->all(FLERR, "Fix langevin gjf and run style respa are not compatible"); + } + + if (gjfflag) { + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); + gjfc1 = 1.0 / (1.0 + update->dt / 2.0 / t_period); + } + + switch (GJmethod) { + case 1: + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); + gjfc1 = 1.0 / (1.0 + update->dt / 2.0 / t_period); + break; + case 2: + // Insert logic for method 2 + break; + case 3: + // Insert logic for method 3 + break; + case 4: + // Insert logic for method 4 + break; + case 5: + // Insert logic for method 5 + break; + case 6: + // Insert logic for method 6 + break; + case 7: + // Insert logic for method 7 + break; + case 8: + // Insert logic for method 8 + break; + default: + error->all(FLERR, "Fix langevin/gjf method not found"); + break; +} +} + +/* ---------------------------------------------------------------------- + integrate position and velocity according to the GJF method + in Grønbech-Jensen, J Stat Phys 191, 137 (2024). The general workflow is + 1. Langevin GJF Initial Integration + 2. Force Update + 3. Langevin GJF Final Integration + 4. Velocity Choice in end_of_step() +------------------------------------------------------------------------- */ + +void FixLangevin::initial_integrate(int /* vflag */) +{ + double gamma1,gamma2; + + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + double *mass = atom->mass; + double *rmass = atom->rmass; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double fran[3]; + + double boltz = force->boltz; + double dt = update->dt; + double mvv2e = force->mvv2e; + double ftm2v = force->ftm2v; + + double dtf = 0.5 * dt * ftm2v; + double dtfm; + double c1sqrt = sqrt(gjfc1); + + // NVE integrates position and velocity according to Eq. 8a, 8b + // This function embeds the GJF formulation into the NVE framework, which corresponds to the GJF case c1=c3. + + //NVE + if (rmass) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / rmass[i]; + v[i][0] += dtfm * f[i][0]; + v[i][1] += dtfm * f[i][1]; + v[i][2] += dtfm * f[i][2]; + x[i][0] += dt * v[i][0]; + x[i][1] += dt * v[i][1]; + x[i][2] += dt * v[i][2]; + } + + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / mass[type[i]]; + v[i][0] += dtfm * f[i][0]; + v[i][1] += dtfm * f[i][1]; + v[i][2] += dtfm * f[i][2]; + x[i][0] += dt * v[i][0]; + x[i][1] += dt * v[i][1]; + x[i][2] += dt * v[i][2]; + } + } + + // The initial NVE integration should always use the on-site velocity. Therefore, a velocity correction + // must be done when using the half-step option. + //---------- + if (!osflag) { + if (rmass) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / rmass[i]; + // Undo NVE integration + x[i][0] -= dt * v[i][0]; + x[i][1] -= dt * v[i][1]; + x[i][2] -= dt * v[i][2]; + // Obtain Eq. 24a. lv[][] stores on-site velocity from previous timestep + v[i][0] = lv[i][0] + dtfm * f[i][0]; + v[i][1] = lv[i][1] + dtfm * f[i][1]; + v[i][2] = lv[i][2] + dtfm * f[i][2]; + // Redo NVE integration with correct velocity + x[i][0] += dt * v[i][0]; + x[i][1] += dt * v[i][1]; + x[i][2] += dt * v[i][2]; + } + + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / mass[type[i]]; + // Undo NVE integration + x[i][0] -= dt * v[i][0]; + x[i][1] -= dt * v[i][1]; + x[i][2] -= dt * v[i][2]; + // Obtain Eq. 24a. lv[][] stores on-site velocity from previous timestep + v[i][0] = lv[i][0] + dtfm * f[i][0]; + v[i][1] = lv[i][1] + dtfm * f[i][1]; + v[i][2] = lv[i][2] + dtfm * f[i][2]; + // Redo NVE integration with correct velocity + x[i][0] += dt * v[i][0]; + x[i][1] += dt * v[i][1]; + x[i][2] += dt * v[i][2]; + } + } + } + //---------- + + compute_target(); + + if (tbiasflag == BIAS) temperature->compute_scalar(); + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + if (tstyle == ATOM) tsqrt = sqrt(tforce[i]); + if (rmass) { + gamma2 = sqrt(rmass[i]) * sqrt(2.0*dt*boltz/t_period/mvv2e) / ftm2v; + gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt; + } else { + gamma2 = gfactor2[type[i]] * tsqrt; + } + fran[0] = gamma2*random->gaussian(); + fran[1] = gamma2*random->gaussian(); + fran[2] = gamma2*random->gaussian(); + + // NVE integrator delivers Eq. 24a, but also overshoots position integration. Calculate Eq. 24b: + x[i][0] -= 0.5 * dt * v[i][0]; + x[i][1] -= 0.5 * dt * v[i][1]; + x[i][2] -= 0.5 * dt * v[i][2]; + // Calculate Eq. 24c: + if (tbiasflag == BIAS) + temperature->remove_bias(i,v[i]); + if (rmass) { + lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c1sqrt / (2.0 * rmass[i])) * fran[0]; + lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c1sqrt / (2.0 * rmass[i])) * fran[1]; + lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c1sqrt / (2.0 * rmass[i])) * fran[2]; + } else { + lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c1sqrt / (2.0 * mass[type[i]])) * fran[0]; + lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c1sqrt / (2.0 * mass[type[i]])) * fran[1]; + lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c1sqrt / (2.0 * mass[type[i]])) * fran[2]; + } + if (tbiasflag == BIAS) + temperature->restore_bias(i,v[i]); + if (tbiasflag == BIAS) + temperature->restore_bias(i,lv[i]); + + // Calculate Eq. 24d + if (tbiasflag == BIAS) temperature->remove_bias(i, lv[i]); + if (atom->rmass) { + v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * (0.5 / rmass[i]) * fran[0]; + v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * (0.5 / rmass[i]) * fran[1]; + v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * (0.5 / rmass[i]) * fran[2]; + } else { + v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * (0.5 / mass[type[i]]) * fran[0]; + v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * (0.5 / mass[type[i]]) * fran[1]; + v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * (0.5 / mass[type[i]]) * fran[2]; + } + if (tbiasflag == BIAS) temperature->restore_bias(i, lv[i]); + // Calculate Eq. 24e. NVE integrator then calculates Eq. 24f. + x[i][0] += 0.5 * dt * v[i][0]; + x[i][1] += 0.5 * dt * v[i][1]; + x[i][2] += 0.5 * dt * v[i][2]; + } + } +} + +void FixLangevin::final_integrate() +{ + double dtfm; + double dt = update->dt; + double ftm2v = force->ftm2v; + double dtf = 0.5 * dt * ftm2v; + + // update v of atoms in group + + double **v = atom->v; + double **f = atom->f; + double *rmass = atom->rmass; + double *mass = atom->mass; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + if (igroup == atom->firstgroup) nlocal = atom->nfirst; + + if (rmass) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / rmass[i]; + v[i][0] += dtfm * f[i][0]; + v[i][1] += dtfm * f[i][1]; + v[i][2] += dtfm * f[i][2]; + } + + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + dtfm = dtf / mass[type[i]]; + v[i][0] += dtfm * f[i][0]; + v[i][1] += dtfm * f[i][1]; + v[i][2] += dtfm * f[i][2]; + } + } +} + +/* ---------------------------------------------------------------------- + set current t_target and t_sqrt +------------------------------------------------------------------------- */ + +void FixLangevin::compute_target() +{ + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double delta = update->ntimestep - update->beginstep; + if (delta != 0.0) delta /= update->endstep - update->beginstep; + + // if variable temp, evaluate variable, wrap with clear/add + // reallocate tforce array if necessary + + if (tstyle == CONSTANT) { + t_target = t_start + delta * (t_stop-t_start); + tsqrt = sqrt(t_target); + } else { + modify->clearstep_compute(); + if (tstyle == EQUAL) { + t_target = input->variable->compute_equal(tvar); + if (t_target < 0.0) + error->one(FLERR, "Fix langevin variable returned negative temperature"); + tsqrt = sqrt(t_target); + } else { + if (atom->nmax > maxatom2) { + maxatom2 = atom->nmax; + memory->destroy(tforce); + memory->create(tforce,maxatom2,"langevin:tforce"); + } + input->variable->compute_atom(tvar,igroup,tforce,1,0); + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + if (tforce[i] < 0.0) + error->one(FLERR, "Fix langevin variable returned negative temperature"); + } + modify->addstep_compute(update->ntimestep + 1); + } +} + +/* ---------------------------------------------------------------------- + tally energy transfer to thermal reservoir, select velocity for GJF +------------------------------------------------------------------------- */ + +void FixLangevin::end_of_step() +{ + double **v = atom->v; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + energy_onestep = 0.0; + + if (tallyflag) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + energy_onestep += flangevin[i][0]*v[i][0] + flangevin[i][1]*v[i][1] + + flangevin[i][2]*v[i][2]; + } + + energy += energy_onestep*update->dt; + + // After the NVE integrator delivers 24f, either the on-site or half-step + // velocity is used in remaining simulation tasks, depending on user input + if (gjfflag && !osflag) { + double tmp[3]; + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + // v is Eq. 24f + tmp[0] = v[i][0]; + tmp[1] = v[i][1]; + tmp[2] = v[i][2]; + // Move on with half-step velocity + v[i][0] = lv[i][0]; + v[i][1] = lv[i][1]; + v[i][2] = lv[i][2]; + // store Eq. 24f in lv for next timestep + lv[i][0] = tmp[0]; + lv[i][1] = tmp[1]; + lv[i][2] = tmp[2]; + } + } +} + +// clang-format on +/* ---------------------------------------------------------------------- */ + +void FixLangevin::reset_target(double t_new) +{ + t_target = t_start = t_stop = t_new; +} + +/* ---------------------------------------------------------------------- */ + +void FixLangevin::reset_dt() +{ + if (atom->mass) { + for (int i = 1; i <= atom->ntypes; i++) { + gfactor2[i] = sqrt(atom->mass[i]) / force->ftm2v; + if (gjfflag) + gfactor2[i] *= sqrt(2.0 * update->dt * force->boltz / t_period / force->mvv2e); // sqrt(2*alpha*kT*dt) + else + gfactor2[i] *= sqrt(24.0 * force->boltz / t_period / update->dt / force->mvv2e); + gfactor2[i] *= 1.0 / sqrt(ratio[i]); + } + } + if (gjfflag) { + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); + gjfc1 = 1.0 / (1.0 + update->dt / 2.0 / t_period); + } +} + +/* ---------------------------------------------------------------------- */ + +int FixLangevin::modify_param(int narg, char **arg) +{ + if (strcmp(arg[0], "temp") == 0) { + if (narg < 2) utils::missing_cmd_args(FLERR, "fix_modify", error); + delete[] id_temp; + id_temp = utils::strdup(arg[1]); + temperature = modify->get_compute_by_id(id_temp); + if (!temperature) + error->all(FLERR, "Could not find fix_modify temperature compute ID: {}", id_temp); + + if (temperature->tempflag == 0) + error->all(FLERR, "Fix_modify temperature compute {} does not compute temperature", id_temp); + if (temperature->igroup != igroup && comm->me == 0) + error->warning(FLERR, "Group for fix_modify temp != fix group: {} vs {}", + group->names[igroup], group->names[temperature->igroup]); + return 2; + } + return 0; +} + +/* ---------------------------------------------------------------------- */ + +double FixLangevin::compute_scalar() +{ + if (!tallyflag || !flangevin_allocated) return 0.0; + + // capture the very first energy transfer to thermal reservoir + + double **v = atom->v; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + if (update->ntimestep == update->beginstep) { + energy_onestep = 0.0; + if (!gjfflag) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + energy_onestep += + flangevin[i][0] * v[i][0] + flangevin[i][1] * v[i][1] + flangevin[i][2] * v[i][2]; + energy = 0.5 * energy_onestep * update->dt; + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + if (tbiasflag) temperature->remove_bias(i, lv[i]); + energy_onestep += + flangevin[i][0] * lv[i][0] + flangevin[i][1] * lv[i][1] + flangevin[i][2] * lv[i][2]; + if (tbiasflag) temperature->restore_bias(i, lv[i]); + } + energy = -0.5 * energy_onestep * update->dt; + } + } + + // convert midstep energy back to previous fullstep energy + + double energy_me = energy - 0.5 * energy_onestep * update->dt; + + double energy_all; + MPI_Allreduce(&energy_me, &energy_all, 1, MPI_DOUBLE, MPI_SUM, world); + return -energy_all; +} + +/* ---------------------------------------------------------------------- + extract thermostat properties +------------------------------------------------------------------------- */ + +void *FixLangevin::extract(const char *str, int &dim) +{ + dim = 0; + if (strcmp(str, "t_target") == 0) { return &t_target; } + return nullptr; +} + +/* ---------------------------------------------------------------------- + memory usage of tally array +------------------------------------------------------------------------- */ + +double FixLangevin::memory_usage() +{ + double bytes = 0.0; + if (gjfflag) bytes += (double) atom->nmax * 3 * sizeof(double); + if (tallyflag || osflag) bytes += (double) atom->nmax * 3 * sizeof(double); + if (tforce) bytes += (double) atom->nmax * sizeof(double); + return bytes; +} + +/* ---------------------------------------------------------------------- + allocate atom-based array for lv +------------------------------------------------------------------------- */ + +void FixLangevin::grow_arrays(int nmax) +{ + memory->grow(lv, nmax, 3, "fix_langevin:lv"); +} + +/* ---------------------------------------------------------------------- + copy values within local atom-based array +------------------------------------------------------------------------- */ + +void FixLangevin::copy_arrays(int i, int j, int /*delflag*/) +{ + lv[j][0] = lv[i][0]; + lv[j][1] = lv[i][1]; + lv[j][2] = lv[i][2]; +} + +/* ---------------------------------------------------------------------- + pack values in local atom-based array for exchange with another proc +------------------------------------------------------------------------- */ + +int FixLangevin::pack_exchange(int i, double *buf) +{ + int n = 0; + buf[n++] = lv[i][0]; + buf[n++] = lv[i][1]; + buf[n++] = lv[i][2]; + return n; +} + +/* ---------------------------------------------------------------------- + unpack values in local atom-based array from exchange with another proc +------------------------------------------------------------------------- */ + +int FixLangevin::unpack_exchange(int nlocal, double *buf) +{ + int n = 0; + lv[nlocal][0] = buf[n++]; + lv[nlocal][1] = buf[n++]; + lv[nlocal][2] = buf[n++]; + return n; +} diff --git a/src/EXTRA-FIX/fix_langevin_gjf.h b/src/EXTRA-FIX/fix_langevin_gjf.h new file mode 100644 index 0000000000..c54772c457 --- /dev/null +++ b/src/EXTRA-FIX/fix_langevin_gjf.h @@ -0,0 +1,85 @@ +/* -*- 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(langevin,FixLangevin); +// clang-format on +#else + +#ifndef LMP_FIX_LANGEVIN_H +#define LMP_FIX_LANGEVIN_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixLangevin : public Fix { + public: + FixLangevin(class LAMMPS *, int, char **); + ~FixLangevin() override; + int setmask() override; + void init() override; + void setup(int) override; + void initial_integrate(int) override; + void post_force(int) override; + void post_force_respa(int, int, int) override; + void end_of_step() override; + void reset_target(double) override; + void reset_dt() override; + int modify_param(int, char **) override; + double compute_scalar() override; + double memory_usage() override; + void *extract(const char *, int &) override; + void grow_arrays(int) override; + void copy_arrays(int, int, int) override; + int pack_exchange(int, double *) override; + int unpack_exchange(int, double *) override; + + protected: + int osflag, GJmethod; + int flangevin_allocated; + double t_start, t_stop, t_period, t_target; + double *gfactor1, *gfactor2, *ratio; + double energy, energy_onestep; + double tsqrt; + double gjfc1, gjfc2; + int tstyle, tvar; + char *tstr; + + class AtomVecEllipsoid *avec; + + int maxatom1, maxatom2; + double **flangevin; + double *tforce; + double **lv; //half step velocity + + char *id_temp; + class Compute *temperature; + + int nlevels_respa; + class RanMars *random; + int seed; + + template + void post_force_templated(); + + void omega_thermostat(); + void angmom_thermostat(); + void compute_target(); +}; + +} // namespace LAMMPS_NS + +#endif +#endif From fc3d295560590e3843de6ccdbd9a1f9cb20fb62b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 21:29:53 -0400 Subject: [PATCH 092/396] add missing entry to OpenMP reduction clause. --- src/DIELECTRIC/pppm_dielectric.cpp | 2 +- src/DIELECTRIC/pppm_disp_dielectric.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DIELECTRIC/pppm_dielectric.cpp b/src/DIELECTRIC/pppm_dielectric.cpp index e5b0c5abb1..40ebbe4794 100644 --- a/src/DIELECTRIC/pppm_dielectric.cpp +++ b/src/DIELECTRIC/pppm_dielectric.cpp @@ -282,7 +282,7 @@ void PPPMDielectric::qsum_qsq(int warning_flag) double qsqsume; #if defined(_OPENMP) -#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local) +#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local,qsqsume_local) #endif for (int i = 0; i < nlocal; i++) { qsum_local += q[i]; diff --git a/src/DIELECTRIC/pppm_disp_dielectric.cpp b/src/DIELECTRIC/pppm_disp_dielectric.cpp index 052b617351..e0652195b7 100644 --- a/src/DIELECTRIC/pppm_disp_dielectric.cpp +++ b/src/DIELECTRIC/pppm_disp_dielectric.cpp @@ -556,7 +556,7 @@ void PPPMDispDielectric::qsum_qsq(int warning_flag) double qsqsume; #if defined(_OPENMP) -#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local) +#pragma omp parallel for default(shared) reduction(+:qsum_local,qsqsum_local,qsqsume_local) #endif for (int i = 0; i < nlocal; i++) { qsum_local += q[i]; From 647bc7538d3bc010894836372f586285ef73110f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 21:46:09 -0400 Subject: [PATCH 093/396] programming style fix --- src/KOKKOS/pair_mliap_kokkos.cpp | 1 - src/KOKKOS/pair_mliap_kokkos.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KOKKOS/pair_mliap_kokkos.cpp b/src/KOKKOS/pair_mliap_kokkos.cpp index 338afe4e42..e91d1bea9d 100644 --- a/src/KOKKOS/pair_mliap_kokkos.cpp +++ b/src/KOKKOS/pair_mliap_kokkos.cpp @@ -240,7 +240,6 @@ void PairMLIAPKokkos::coeff(int narg, char **arg) { if (strcmp(elemname,descriptor->elements[jelem]) == 0) break; - //printf(">>> nelements: %d\n", descriptor->nelements); if (jelem < descriptor->nelements) map[i] = jelem; else if (strcmp(elemname,"NULL") == 0) map[i] = -1; diff --git a/src/KOKKOS/pair_mliap_kokkos.h b/src/KOKKOS/pair_mliap_kokkos.h index 3f56a89692..b0d160133e 100644 --- a/src/KOKKOS/pair_mliap_kokkos.h +++ b/src/KOKKOS/pair_mliap_kokkos.h @@ -31,6 +31,7 @@ PairStyle(mliap/kk/host,PairMLIAPKokkos); #include "kokkos_type.h" #include "kokkos_base.h" #include "comm.h" + #include namespace LAMMPS_NS { From 3d132272873ff9f6f70bc6177dad02e25c9bf923 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 22:17:08 -0400 Subject: [PATCH 094/396] convert compiler workaround from augmenting compiler flags to target_compile_definition() --- cmake/CMakeLists.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 6fb2f0c65e..3aa26e1228 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -129,19 +129,6 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC") OR (CMAKE_CXX_COMPILER_ID STREQUAL " set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -Minform=severe") endif() -# this hack is required to compile fmt lib with CrayClang version 15.0.2 -# CrayClang is only directly recognized by version 3.28 and later -if(CMAKE_VERSION VERSION_LESS 3.28) - get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) - if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -DFMT_STATIC_THOUSANDS_SEPARATOR") - endif() -else() - if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -DFMT_STATIC_THOUSANDS_SEPARATOR") - endif() -endif() - # silence nvcc warnings if((PKG_KOKKOS) AND (Kokkos_ENABLE_CUDA) AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") @@ -450,6 +437,19 @@ if(NOT ${LAMMPS_MEMALIGN} STREQUAL "0") target_compile_definitions(lammps PRIVATE -DLAMMPS_MEMALIGN=${LAMMPS_MEMALIGN}) endif() +# this hack is required to compile fmt lib with CrayClang version 15.0.2 +# CrayClang is only directly recognized by CMake version 3.28 and later +if(CMAKE_VERSION VERSION_LESS 3.28) + get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) + if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) + target_compile_definitions(lammps PRIVATE -DFMT_STATIC_THOUSANDS_SEPARATOR) + endif() +else() + if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") + target_compile_definitions(lammps PRIVATE -DFMT_STATIC_THOUSANDS_SEPARATOR) + endif() +endif() + # "hard" dependencies between packages resulting # in an error instead of skipping over files pkg_depends(ML-IAP ML-SNAP) From b6dae216d3baac9428b273cc2af2173ddafd02b7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 22:48:18 -0400 Subject: [PATCH 095/396] no need to set build type specific flags --- cmake/CMakeLists.txt | 26 +++++++++++++------------- cmake/presets/kokkos-hip.cmake | 9 +-------- cmake/presets/kokkos-sycl-intel.cmake | 8 +------- cmake/presets/kokkos-sycl-nvidia.cmake | 8 +------- cmake/presets/mingw-cross.cmake | 8 +------- cmake/presets/windows-intel-llvm.cmake | 8 +------- 6 files changed, 18 insertions(+), 49 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 3aa26e1228..61ad229923 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -102,36 +102,36 @@ include(CheckIncludeFileCXX) if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") if(CMAKE_SYSTEM_NAME STREQUAL "Windows") if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} /Qrestrict") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Qrestrict") endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} /QxCOMMON-AVX512") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /QxCOMMON-AVX512") else() - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} /QxHost") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /QxHost") endif() else() - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -restrict") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -xCOMMON-AVX512") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -xCOMMON-AVX512") else() - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -xHost -fp-model fast=2 -no-prec-div -qoverride-limits -diag-disable=10441 -diag-disable=11074 -diag-disable=11076 -diag-disable=2196") endif() endif() endif() # silence excessive warnings for new Intel Compilers if(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -fp-model precise -Wno-tautological-constant-compare -Wno-unused-command-line-argument") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fp-model precise -Wno-tautological-constant-compare -Wno-unused-command-line-argument") endif() # silence excessive warnings for PGI/NVHPC compilers if((CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC") OR (CMAKE_CXX_COMPILER_ID STREQUAL "PGI")) - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}} -Minform=severe") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Minform=severe") endif() # silence nvcc warnings if((PKG_KOKKOS) AND (Kokkos_ENABLE_CUDA) AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) - set(CMAKE_CXX_FLAGS_${BTYPE} "${CMAKE_CXX_FLAGS_${BTYPE}}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" "-Xcudafe --diag_suppress=unrecognized_pragma,--diag_suppress=128") endif() # we *require* C++11 without extensions but prefer C++17. @@ -507,13 +507,13 @@ if(BUILD_OMP) if(CMAKE_VERSION VERSION_LESS 3.28) get_filename_component(_exe "${CMAKE_CXX_COMPILER}" NAME) if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (_exe STREQUAL "crayCC")) - set(CMAKE_SHARED_LINKER_FLAGS_${BTYPE} "${CMAKE_SHARED_LINKER_FLAGS_${BTYPE}} -fopenmp") - set(CMAKE_STATIC_LINKER_FLAGS_${BTYPE} "${CMAKE_STATIC_LINKER_FLAGS_${BTYPE}} -fopenmp") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fopenmp") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fopenmp") endif() else() if(CMAKE_CXX_COMPILER_ID STREQUAL "CrayClang") - set(CMAKE_SHARED_LINKER_FLAGS_${BTYPE} "${CMAKE_SHARED_LINKER_FLAGS_${BTYPE}} -fopenmp") - set(CMAKE_STATIC_LINKER_FLAGS_${BTYPE} "${CMAKE_STATIC_LINKER_FLAGS_${BTYPE}} -fopenmp") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fopenmp") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fopenmp") endif() endif() endif() diff --git a/cmake/presets/kokkos-hip.cmake b/cmake/presets/kokkos-hip.cmake index ba1eeb1853..c1968c0ffa 100644 --- a/cmake/presets/kokkos-hip.cmake +++ b/cmake/presets/kokkos-hip.cmake @@ -9,14 +9,7 @@ set(Kokkos_ARCH_VEGA90A on CACHE BOOL "" FORCE) set(Kokkos_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS ON CACHE BOOL "" FORCE) set(BUILD_OMP ON CACHE BOOL "" FORCE) -set(CMAKE_CXX_COMPILER hipcc CACHE STRING "" FORCE) -if (CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -munsafe-fp-atomics" CACHE STRING "" FORCE) -endif() -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -munsafe-fp-atomics" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -munsafe-fp-atomics" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -munsafe-fp-atomics" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -munsafe-fp-atomics" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -munsafe-fp-atomics" CACHE STRING "" FORCE) # If KSPACE is also enabled, use CUFFT for FFTs set(FFT_KOKKOS "HIPFFT" CACHE STRING "" FORCE) diff --git a/cmake/presets/kokkos-sycl-intel.cmake b/cmake/presets/kokkos-sycl-intel.cmake index 163d35e031..fe5999dae6 100644 --- a/cmake/presets/kokkos-sycl-intel.cmake +++ b/cmake/presets/kokkos-sycl-intel.cmake @@ -24,13 +24,7 @@ set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) # set(_intel_sycl_flags " -w -fsycl -flink-huge-device-code -fsycl-targets=spir64_gen " set(_intel_sycl_flags " -w -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen " -if (CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -endif() -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) #set(CMAKE_EXE_LINKER_FLAGS "-fsycl -flink-huge-device-code -fsycl-targets=spir64_gen " CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsycl -flink-huge-device-code " CACHE STRING "" FORCE) diff --git a/cmake/presets/kokkos-sycl-nvidia.cmake b/cmake/presets/kokkos-sycl-nvidia.cmake index 678f9f380a..bf4dfba225 100644 --- a/cmake/presets/kokkos-sycl-nvidia.cmake +++ b/cmake/presets/kokkos-sycl-nvidia.cmake @@ -17,10 +17,4 @@ set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xsycl-target-frontend -O3 " CACHE STRING "" FORCE) set(_intel_sycl_flags "-fgpu-inline-threshold=100000 -Xsycl-target-frontend -O3 -Xsycl-target-frontend -ffp-contract=on -Wno-unknown-cuda-version") -if (CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -endif() -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${_intel_sycl_flags}" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${_intel_sycl_flags}" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_intel_sycl_flags}" CACHE STRING "" FORCE) diff --git a/cmake/presets/mingw-cross.cmake b/cmake/presets/mingw-cross.cmake index dbcd4ef11d..b5c5adb1f6 100644 --- a/cmake/presets/mingw-cross.cmake +++ b/cmake/presets/mingw-cross.cmake @@ -91,13 +91,7 @@ endif() set(DOWNLOAD_VORO ON CACHE BOOL "" FORCE) set(DOWNLOAD_EIGEN3 ON CACHE BOOL "" FORCE) set(LAMMPS_MEMALIGN "0" CACHE STRING "" FORCE) -if (CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-include-dirs" CACHE STRING "" FORCE) -endif() -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-missing-include-dirs" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-missing-include-dirs" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-missing-include-dirs" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Wno-missing-include-dirs" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-include-dirs" CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-stdcall-fixup,--as-needed,-lssp" CACHE STRING "" FORCE) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-stdcall-fixup,--as-needed,-lssp" CACHE STRING "" FORCE) set(BUILD_TOOLS ON CACHE BOOL "" FORCE) diff --git a/cmake/presets/windows-intel-llvm.cmake b/cmake/presets/windows-intel-llvm.cmake index cdde3c146a..ead4fbcfb5 100644 --- a/cmake/presets/windows-intel-llvm.cmake +++ b/cmake/presets/windows-intel-llvm.cmake @@ -5,10 +5,4 @@ set(CMAKE_C_COMPILER "icx" CACHE STRING "" FORCE) set(CMAKE_Fortran_COMPILER "ifx" CACHE STRING "" FORCE) set(INTEL_LRT_MODE "C++11" CACHE STRING "" FORCE) unset(HAVE_OMP_H_INCLUDE CACHE) -if (CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) -endif() -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument" CACHE STRING "" FORCE) From c9f25a69e50b029d425b6725655797aed1906922 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 22:48:44 -0400 Subject: [PATCH 096/396] remove rarely working hack --- src/main.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a1f9772455..649550735c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,10 +21,6 @@ #include #include -#if defined(LAMMPS_TRAP_FPE) && defined(_GNU_SOURCE) -#include -#endif - // import MolSSI Driver Interface library #if defined(LMP_MDI) #include @@ -62,17 +58,6 @@ int main(int argc, char **argv) if (MDI_MPI_get_world_comm(&lammps_comm)) MPI_Abort(MPI_COMM_WORLD, 1); #endif -#if defined(LAMMPS_TRAP_FPE) && defined(_GNU_SOURCE) - // enable trapping selected floating point exceptions. - // this uses GNU extensions and is only tested on Linux - // therefore we make it depend on -D_GNU_SOURCE, too. - fesetenv(FE_NOMASK_ENV); - fedisableexcept(FE_ALL_EXCEPT); - feenableexcept(FE_DIVBYZERO); - feenableexcept(FE_INVALID); - feenableexcept(FE_OVERFLOW); -#endif - try { auto lammps = new LAMMPS(argc, argv, lammps_comm); lammps->input->file(); From af718e8162e9d34d8de1f3f46f33fc462d05799d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 7 Apr 2025 22:50:38 -0400 Subject: [PATCH 097/396] remove one more use to CMAKE_TUNE_FLAGS --- unittest/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 7c94cad4e3..dcb44ffbe7 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -33,10 +33,6 @@ mark_as_advanced(SKIP_DEATH_TESTS) if(SKIP_DEATH_TESTS) add_compile_definitions(LAMMPS_SKIP_DEATH_TESTS) endif() -# import -foreach(_FLAG ${CMAKE_TUNE_FLAGS}) - add_compile_options(${_FLAG}) -endforeach() # must repeat handling coverage for older CMake if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND ENABLE_COVERAGE) From 7643c901ebbf8309916f024cfb72e738d323ae38 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Mon, 7 Apr 2025 22:57:29 -0400 Subject: [PATCH 098/396] cleaned mdr damping and updated velocity damping for mdr use --- doc/src/pair_granular.rst | 22 ++++++++++++---------- examples/granular/in.tableting.200 | 2 +- src/GRANULAR/gran_sub_mod_damping.cpp | 13 +++++++++++-- src/GRANULAR/gran_sub_mod_normal.cpp | 10 +++++----- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 9804c90cef..6e17d604fd 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -89,7 +89,7 @@ and their required arguments are: 4. *dmt* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 5. *jkr* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, -:math:`\psi_b`, :math:`\eta_{n0}` + :math:`\psi_b`, :math:`\eta_{n0}` Here, :math:`k_n` is spring stiffness (with units that depend on model choice, see below); :math:`\eta_{n0}` is a damping prefactor (or, in its @@ -178,8 +178,9 @@ two-part series :ref:`Zunker and Kamrin Part I ` and :ref:`Zunker and Kamrin Part II `. Further development and demonstrations of its application to industrially relevant powder compaction processes are presented in :ref:`Zunker et al. `. -If you use the *mdr* normal model, is recommended you use the *mdr* damping model -described below. +If you use the *mdr* normal model, the default, and recommended damping model is +the *mdr* damping model described below. The other currently supported damping model +for the *mdr* normal model is *velocity*, all others will result in an error. The model requires the following inputs: @@ -203,8 +204,8 @@ The model requires the following inputs: triggered. Lower values of :math:`\psi_b` delay the onset of the bulk elastic response. - 6. *Coefficient of restitution* :math:`0 \le e \le 1` : The coefficient of - restitution is a tunable parameter that controls damping in the normal direction. + 6. *Damping coefficent* :math:`\eta_{n0} \ge 0` : The damping coefficient + is a tunable parameter that controls damping in the normal direction. .. note:: @@ -216,7 +217,7 @@ The *mdr* model produces a nonlinear force-displacement response, therefore the critical timestep :math:`\Delta t` depends on the inputs and level of deformation. As a conservative starting point the timestep can be assumed to be dictated by the bulk elastic response such that -:math:`\Delta t = 0.35\sqrt{m/k_\textrm{bulk}}`, where :math:`m` is the mass of +:math:`\Delta t = 0.08\sqrt{m/k_\textrm{bulk}}`, where :math:`m` is the mass of the smallest particle and :math:`k_\textrm{bulk} = \kappa R_\textrm{min}` is an effective stiffness related to the bulk elastic response. Here, :math:`\kappa = E/(3(1-2\nu))` is the bulk modulus and @@ -334,7 +335,8 @@ for the damping model currently supported are: *mdr* contact model is defined. If the *damping* keyword is not specified, the *viscoelastic* model is -used by default. +used by default. The exception is when the normal model is set +to *mdr* then the *mdr* damping model will be used by default. For *damping velocity*, the normal damping is simply equal to the user-specified damping coefficient in the *normal* model: @@ -344,7 +346,7 @@ user-specified damping coefficient in the *normal* model: \eta_n = \eta_{n0} Here, :math:`\eta_{n0}` is the damping coefficient specified for the normal -contact model, in units of *mass*\ /\ *time*\ . +contact model, in units of *mass*\ /\ *time*\ . For *damping mass_velocity*, the normal damping is given by: @@ -1082,8 +1084,8 @@ a bulk elastic response. Journal of the Mechanics and Physics of Solids, **(Zunker et al, 2025)** Zunker, W., Dunatunga, S., Thakur, S., Tang, P., & Kamrin, K. (2025). Experimentally validated DEM for large -deformation powder compaction: mechanically-derived contact model and -screening of non-physical contacts. +deformation powder compaction: Mechanically-derived contact model and +screening of non-physical contacts. Powder Technology, 120972. .. _Luding2008: diff --git a/examples/granular/in.tableting.200 b/examples/granular/in.tableting.200 index b9443cc36d..d1ecc28aa1 100644 --- a/examples/granular/in.tableting.200 +++ b/examples/granular/in.tableting.200 @@ -34,7 +34,7 @@ variable YieldStress equal 1.9e5 variable PoissonsRatio equal 0.4 variable SurfaceEnergy equal 2 variable SurfaceEnergyWall equal 0.0 -variable damp equal 1.0 +variable damp equal 0.2 variable psi_b equal 0.5 # linear_history = k_t, x_gammat, mu_s diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index a171f70654..13041b1a0b 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -77,7 +77,17 @@ GranSubModDampingVelocity::GranSubModDampingVelocity(GranularModel *gm, LAMMPS * double GranSubModDampingVelocity::calculate_forces() { - damp_prefactor = damp; + if (gm->normal_model->name == "mdr") { + using namespace Granular_MDR_NS; + double *history = & gm->history[gm->normal_model->history_index]; + if (history[DAMP_SCALE] == 0.0) { + damp_prefactor == 0.0; + } else { + damp_prefactor = damp; + } + } else { + damp_prefactor = damp; + } return -damp_prefactor * gm->vnnr; } @@ -181,7 +191,6 @@ void GranSubModDampingCoeffRestitution::init() GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : GranSubModDamping(gm, lmp) { - contact_radius_flag = 1; } /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 9eb30e2a0e..ec75fd2f71 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -73,8 +73,9 @@ static const char cite_mdr[] = " author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken},\n" " title = {Experimentally validated DEM for large deformation powder compaction:\n" " mechanically-derived contact model and screening of non-physical contacts},\n" + " journal = {Powder Technology},\n" " year = {2025},\n" - " journal = {engrXiv},\n" + " pages = {120972},\n" "}\n\n"; /* ---------------------------------------------------------------------- @@ -958,19 +959,18 @@ double GranSubModNormalMDR::calculate_forces() double damp_scale; if (gm->contact_type != PAIR) { a_damp = a_damp/2.0; - damp_scale = 0.5*sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); + damp_scale = sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); double *deltao_offset = &history[DELTAO_0]; const double wfm = std::exp(10.7*(*deltao_offset)/Rinitial[gm->i] - 10.0) + 1.0; // wall force magnifier - //const double wfm = 1.0; F = wij * F0 * wfm; } else { - damp_scale = 0.5*sqrt(gm->meff * 2.0 * Eeff * a_damp); + damp_scale = sqrt(gm->meff * 2.0 * Eeff * a_damp); F = wij * (F0 + F1) * 0.5; } if (history_update) { double *damp_scale_offset = & history[DAMP_SCALE]; - (a_damp < 0.0) ? *damp_scale_offset = 0.0 : *damp_scale_offset = damp_scale; + (a_damp <= 0.0) ? *damp_scale_offset = 0.0 : *damp_scale_offset = damp_scale; } return F; From 586d24f5efed3ec5e2b8b1ff6bbd08ec8fc3b124 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Mon, 7 Apr 2025 23:02:00 -0400 Subject: [PATCH 099/396] whitespace --- doc/src/pair_granular.rst | 2 +- src/GRANULAR/gran_sub_mod_damping.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 6e17d604fd..8cd8e04af5 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -346,7 +346,7 @@ user-specified damping coefficient in the *normal* model: \eta_n = \eta_{n0} Here, :math:`\eta_{n0}` is the damping coefficient specified for the normal -contact model, in units of *mass*\ /\ *time*\ . +contact model, in units of *mass*\ /\ *time*\ . For *damping mass_velocity*, the normal damping is given by: diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index 13041b1a0b..da9aa81079 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -85,7 +85,7 @@ double GranSubModDampingVelocity::calculate_forces() } else { damp_prefactor = damp; } - } else { + } else { damp_prefactor = damp; } return -damp_prefactor * gm->vnnr; From 813e65026e78706250c347f1cd5e139cccbcba0a Mon Sep 17 00:00:00 2001 From: Evangelos Voyiatzis Date: Tue, 8 Apr 2025 15:53:45 +0200 Subject: [PATCH 100/396] fixing whitespaces --- .../dihedral_cosine_squared_restricted.cpp | 18 ++++++------ src/MOLECULE/dihedral_charmm.cpp | 24 ++++++++-------- src/MOLECULE/dihedral_charmmfsw.cpp | 24 ++++++++-------- src/MOLECULE/dihedral_multi_harmonic.cpp | 28 +++++++++---------- src/MOLECULE/dihedral_opls.cpp | 24 ++++++++-------- 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp index 2edc87bb00..ae82a7873d 100644 --- a/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp +++ b/src/EXTRA-MOLECULE/dihedral_cosine_squared_restricted.cpp @@ -396,12 +396,12 @@ void DihedralCosineSquaredRestricted::born_matrix(int nd, int i1, int i2, int i3 /* ---------------------------------------------------------------------- return ptr to internal members upon request - ------------------------------------------------------------------------ */ - - void *DihedralCosineSquaredRestricted::extract(const char *str, int &dim) - { - dim = 1; - if (strcmp(str, "k") == 0) return (void *) k; - if (strcmp(str, "phi0") == 0) return (void *) phi0; - return nullptr; - } +------------------------------------------------------------------------ */ + +void *DihedralCosineSquaredRestricted::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "phi0") == 0) return (void *) phi0; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_charmm.cpp b/src/MOLECULE/dihedral_charmm.cpp index 1ec29da780..ddce2dd66f 100644 --- a/src/MOLECULE/dihedral_charmm.cpp +++ b/src/MOLECULE/dihedral_charmm.cpp @@ -433,15 +433,15 @@ void DihedralCharmm::write_data(FILE *fp) fprintf(fp, "%d %g %d %d %g\n", i, k[i], multiplicity[i], shift[i], weight[i]); } - /* ---------------------------------------------------------------------- - return ptr to internal members upon request - ------------------------------------------------------------------------ */ - - void *DihedralCharmm::extract(const char *str, int &dim) - { - dim = 1; - if (strcmp(str, "k") == 0) return (void *) k; - if (strcmp(str, "n") == 0) return (void *) multiplicity; - if (strcmp(str, "d") == 0) return (void *) shift; - return nullptr; - } +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralCharmm::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + if (strcmp(str, "d") == 0) return (void *) shift; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_charmmfsw.cpp b/src/MOLECULE/dihedral_charmmfsw.cpp index 2415dff8cd..75e4f688b1 100644 --- a/src/MOLECULE/dihedral_charmmfsw.cpp +++ b/src/MOLECULE/dihedral_charmmfsw.cpp @@ -476,15 +476,15 @@ void DihedralCharmmfsw::write_data(FILE *fp) fprintf(fp, "%d %g %d %d %g\n", i, k[i], multiplicity[i], shift[i], weight[i]); } - /* ---------------------------------------------------------------------- - return ptr to internal members upon request - ------------------------------------------------------------------------ */ - - void *DihedralCharmmfsw::extract(const char *str, int &dim) - { - dim = 1; - if (strcmp(str, "k") == 0) return (void *) k; - if (strcmp(str, "n") == 0) return (void *) multiplicity; - if (strcmp(str, "d") == 0) return (void *) shift; - return nullptr; - } +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralCharmmfsw::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k") == 0) return (void *) k; + if (strcmp(str, "n") == 0) return (void *) multiplicity; + if (strcmp(str, "d") == 0) return (void *) shift; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_multi_harmonic.cpp b/src/MOLECULE/dihedral_multi_harmonic.cpp index 89577fca9d..ef75c6b5e7 100644 --- a/src/MOLECULE/dihedral_multi_harmonic.cpp +++ b/src/MOLECULE/dihedral_multi_harmonic.cpp @@ -409,17 +409,17 @@ void DihedralMultiHarmonic::born_matrix(int nd, int i1, int i2, int i3, int i4, } - /* ---------------------------------------------------------------------- - return ptr to internal members upon request - ------------------------------------------------------------------------ */ - - void *DihedralMultiHarmonic::extract(const char *str, int &dim) - { - dim = 1; - if (strcmp(str, "a1") == 0) return (void *) a1; - if (strcmp(str, "a2") == 0) return (void *) a2; - if (strcmp(str, "a3") == 0) return (void *) a3; - if (strcmp(str, "a4") == 0) return (void *) a4; - if (strcmp(str, "a5") == 0) return (void *) a5; - return nullptr; - } +/* ---------------------------------------------------------------------- + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralMultiHarmonic::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "a1") == 0) return (void *) a1; + if (strcmp(str, "a2") == 0) return (void *) a2; + if (strcmp(str, "a3") == 0) return (void *) a3; + if (strcmp(str, "a4") == 0) return (void *) a4; + if (strcmp(str, "a5") == 0) return (void *) a5; + return nullptr; +} diff --git a/src/MOLECULE/dihedral_opls.cpp b/src/MOLECULE/dihedral_opls.cpp index 0989e1d7e4..2b58f51366 100644 --- a/src/MOLECULE/dihedral_opls.cpp +++ b/src/MOLECULE/dihedral_opls.cpp @@ -433,15 +433,15 @@ void DihedralOPLS::born_matrix(int nd, int i1, int i2, int i3, int i4, double &d } /* ---------------------------------------------------------------------- - return ptr to internal members upon request - ------------------------------------------------------------------------ */ - - void *DihedralOPLS::extract(const char *str, int &dim) - { - dim = 1; - if (strcmp(str, "k1") == 0) return (void *) k1; - if (strcmp(str, "k2") == 0) return (void *) k2; - if (strcmp(str, "k3") == 0) return (void *) k3; - if (strcmp(str, "k4") == 0) return (void *) k4; - return nullptr; - } + return ptr to internal members upon request +------------------------------------------------------------------------ */ + +void *DihedralOPLS::extract(const char *str, int &dim) +{ + dim = 1; + if (strcmp(str, "k1") == 0) return (void *) k1; + if (strcmp(str, "k2") == 0) return (void *) k2; + if (strcmp(str, "k3") == 0) return (void *) k3; + if (strcmp(str, "k4") == 0) return (void *) k4; + return nullptr; +} From d6e9a6a44af5f00d9902e46e40488ddce0f6a554 Mon Sep 17 00:00:00 2001 From: Gabriel Alkuino <107645552+gsalkuin@users.noreply.github.com> Date: Tue, 8 Apr 2025 10:03:36 -0400 Subject: [PATCH 101/396] Update atom->quat in fix_rigid_small.cpp --- src/RIGID/fix_rigid_small.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/RIGID/fix_rigid_small.cpp b/src/RIGID/fix_rigid_small.cpp index 6ba2e5eb1c..d55b1fadd9 100644 --- a/src/RIGID/fix_rigid_small.cpp +++ b/src/RIGID/fix_rigid_small.cpp @@ -1409,6 +1409,11 @@ void FixRigidSmall::set_xv() MathExtra::omega_to_angmom(b->omega,exone,eyone,ezone, inertiaatom,angmom[i]); } + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::quatquat(b->quat,orient[i],quatatom); + MathExtra::qnormalize(quatatom); + } if (eflags[i] & DIPOLE) { MathExtra::quat_to_mat(b->quat,p); MathExtra::matvec(p,dorient[i],mu[i]); @@ -1849,7 +1854,7 @@ void FixRigidSmall::setup_bodies_static() } // grow extended arrays and set extended flags for each particle - // orientflag = 4 if any particle stores ellipsoid or tri orientation + // orientflag = 4 if any particle stores ellipsoid or tri orientation or quat // orientflag = 1 if any particle stores line orientation // dorientflag = 1 if any particle stores dipole orientation @@ -1857,6 +1862,7 @@ void FixRigidSmall::setup_bodies_static() if (atom->ellipsoid_flag) orientflag = 4; if (atom->line_flag) orientflag = 1; if (atom->tri_flag) orientflag = 4; + if (atom->quat_flag) orientflag = 4; if (atom->mu_flag) dorientflag = 1; grow_arrays(atom->nmax); @@ -2209,7 +2215,12 @@ void FixRigidSmall::setup_bodies_static() delta,displace[i]); if (extended) { - if (eflags[i] & ELLIPSOID) { + if (atom->quat_flag) { + quatatom = atom->quat[i]; + MathExtra::qconjugate(b->quat,qc); + MathExtra::quatquat(qc,quatatom,orient[i]); + MathExtra::qnormalize(orient[i]); + } else if (eflags[i] & ELLIPSOID) { quatatom = ebonus[ellipsoid[i]].quat; MathExtra::qconjugate(b->quat,qc); MathExtra::quatquat(qc,quatatom,orient[i]); From 210cddd94e2fefefa48dbdee3814ddc4ee7a79a5 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Tue, 8 Apr 2025 18:32:45 -0400 Subject: [PATCH 102/396] working on adding damping types to mdr damping --- src/GRANULAR/gran_sub_mod_damping.cpp | 27 +++++++++++++++------------ src/GRANULAR/gran_sub_mod_damping.h | 1 + src/GRANULAR/gran_sub_mod_normal.cpp | 16 +++++++++------- src/GRANULAR/gran_sub_mod_normal.h | 2 ++ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index da9aa81079..a5dc5745a4 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -45,6 +45,11 @@ GranSubModDamping::GranSubModDamping(GranularModel *gm, LAMMPS *lmp) : GranSubMo void GranSubModDamping::init() { damp = gm->normal_model->get_damp(); + if (gm->normal_model->name == "mdr") { + if (gm->tangential_model->name != "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + damp_type = gm->normal_model->get_damp_type(); + } } /* ---------------------------------------------------------------------- @@ -77,17 +82,7 @@ GranSubModDampingVelocity::GranSubModDampingVelocity(GranularModel *gm, LAMMPS * double GranSubModDampingVelocity::calculate_forces() { - if (gm->normal_model->name == "mdr") { - using namespace Granular_MDR_NS; - double *history = & gm->history[gm->normal_model->history_index]; - if (history[DAMP_SCALE] == 0.0) { - damp_prefactor == 0.0; - } else { - damp_prefactor = damp; - } - } else { - damp_prefactor = damp; - } + damp_prefactor = damp; return -damp_prefactor * gm->vnnr; } @@ -209,6 +204,14 @@ double GranSubModDampingMDR::calculate_forces() { using namespace Granular_MDR_NS; double *history = & gm->history[gm->normal_model->history_index]; - damp_prefactor = damp * history[DAMP_SCALE]; + if (damp_type == 1) { + damp_prefactor = damp * history[DAMP_SCALE]; + } else if (damp_type == 2) { + if (history[DAMP_SCALE] == 0.0) { + damp_prefactor == 0.0; + } else { + damp_prefactor = damp; + } + } return -damp_prefactor * gm->vnnr; } diff --git a/src/GRANULAR/gran_sub_mod_damping.h b/src/GRANULAR/gran_sub_mod_damping.h index cd7ee3bf1a..c73a4a8e5e 100644 --- a/src/GRANULAR/gran_sub_mod_damping.h +++ b/src/GRANULAR/gran_sub_mod_damping.h @@ -42,6 +42,7 @@ namespace Granular_NS { protected: double damp_prefactor; double damp; + int damp_type; }; /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index ec75fd2f71..ecf53ea24c 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -441,7 +441,7 @@ GranSubModNormalMDR::GranSubModNormalMDR(GranularModel *gm, LAMMPS *lmp) : { if (lmp->citeme) lmp->citeme->add(cite_mdr); - num_coeffs = 6; + num_coeffs = 7; contact_radius_flag = 1; size_history = 27; nsvector = 1; @@ -468,12 +468,13 @@ GranSubModNormalMDR::~GranSubModNormalMDR() void GranSubModNormalMDR::coeffs_to_local() { - E = coeffs[0]; // Young's modulus - nu = coeffs[1]; // Poisson's ratio - Y = coeffs[2]; // yield stress - gamma = coeffs[3]; // effective surface energy - psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} - damp = coeffs[5]; // coefficent of restitution + E = coeffs[0]; // Young's modulus + nu = coeffs[1]; // Poisson's ratio + Y = coeffs[2]; // yield stress + gamma = coeffs[3]; // effective surface energy + psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} + damp = coeffs[5]; // coefficent of restitution + damp_type = coeffs[6]; // damping type 1 = mdr or 2 = velocity if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); if (nu < 0.0 || nu > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); @@ -481,6 +482,7 @@ void GranSubModNormalMDR::coeffs_to_local() if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); + if (damp_type != 1 && damp_type != 2) error->all(FLERR, "Illegal MDR normal model, damping type must an integer equal to 1 (mdr) or 2 (velocity)"); G = E / (2.0 * (1.0 + nu)); // shear modulus kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus diff --git a/src/GRANULAR/gran_sub_mod_normal.h b/src/GRANULAR/gran_sub_mod_normal.h index 8142d88cea..0b7bb664d5 100644 --- a/src/GRANULAR/gran_sub_mod_normal.h +++ b/src/GRANULAR/gran_sub_mod_normal.h @@ -41,6 +41,7 @@ namespace Granular_NS { int get_cohesive_flag() const { return cohesive_flag; } double get_damp() const { return damp; } + double get_damp_type() const { return damp_type; } double get_emod() const { return Emod; } double get_fncrit() const { return Fncrit; } int get_material_properties() const { return material_properties; } @@ -51,6 +52,7 @@ namespace Granular_NS { protected: double damp; // argument historically needed by damping // typically (but not always) equals eta_n0 + int damp_type; // damping type is only used by normal mdr model double Emod, poiss; double Fncrit; int material_properties, cohesive_flag; From 585565edb914060de90804e5e588067c3bc7c843 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Tue, 8 Apr 2025 20:33:28 -0400 Subject: [PATCH 103/396] corrected initialization of damp_type, error checks, doc changes, example script updates --- doc/src/pair_granular.rst | 38 +++++++++++++-------- examples/granular/in.tableting.200 | 7 ++-- examples/granular/in.triaxial.compaction.12 | 7 ++-- src/GRANULAR/gran_sub_mod_damping.cpp | 15 +++++--- src/GRANULAR/gran_sub_mod_normal.cpp | 2 +- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 8cd8e04af5..696c87b0ab 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -44,7 +44,7 @@ Examples pair_coeff * * hertz 1000.0 50.0 tangential mindlin 1000.0 1.0 0.4 heat area 0.1 pair_style granular - pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping mdr + pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping mdr 1 Description """"""""""" @@ -89,7 +89,7 @@ and their required arguments are: 4. *dmt* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 5. *jkr* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, - :math:`\psi_b`, :math:`\eta_{n0}` + :math:`\psi_b`, :math:`\eta_{n0}`, :math:`d_{type}` Here, :math:`k_n` is spring stiffness (with units that depend on model choice, see below); :math:`\eta_{n0}` is a damping prefactor (or, in its @@ -178,9 +178,8 @@ two-part series :ref:`Zunker and Kamrin Part I ` and :ref:`Zunker and Kamrin Part II `. Further development and demonstrations of its application to industrially relevant powder compaction processes are presented in :ref:`Zunker et al. `. -If you use the *mdr* normal model, the default, and recommended damping model is -the *mdr* damping model described below. The other currently supported damping model -for the *mdr* normal model is *velocity*, all others will result in an error. +If you use the *mdr* normal model the only supported damping option is +the *mdr* damping class described below. The model requires the following inputs: @@ -207,6 +206,9 @@ The model requires the following inputs: 6. *Damping coefficent* :math:`\eta_{n0} \ge 0` : The damping coefficient is a tunable parameter that controls damping in the normal direction. + 7. *Damping type* :math:`d_{type} =` 1 or 2 : The damping type specfies the + damping model defined for the *mdr* damping class described below. + .. note:: The values for :math:`E`, :math:`\nu`, :math:`Y`, and :math:`\Delta\gamma` (i.e., @@ -329,14 +331,8 @@ for the damping model currently supported are: 5. *coeff_restitution* 6. *mdr* -.. note:: - - It is suggested to use the *mdr* damping model with when the normal - *mdr* contact model is defined. - If the *damping* keyword is not specified, the *viscoelastic* model is -used by default. The exception is when the normal model is set -to *mdr* then the *mdr* damping model will be used by default. +used by default. For *damping velocity*, the normal damping is simply equal to the user-specified damping coefficient in the *normal* model: @@ -423,8 +419,13 @@ the damping coefficient, it accurately reproduces the specified coefficient of restitution for both monodisperse and polydisperse particle pairs. This damping model is not compatible with cohesive normal models such as *JKR* or *DMT*. -The *mdr* damping model is only compatible with the normal *mdr* contact model. -It takes into account the contact stiffness :math:`k_{mdr}` calulated +The *mdr* damping class contains multiple damping models that can be toggled between +by specifying different integer values for the :math:`d_{type}` parameter in the *mdr* +normal model. This damping option is therefore only compatible with the normal *mdr* +contact model. + +Setting :math:`d_{type} = 1` is the suggested damping option. This specifies a damping +model that takes into account the contact stiffness :math:`k_{mdr}` calulated by the normal *mdr* contact model to determine the damping coefficent: .. math:: @@ -441,6 +442,15 @@ normal *mdr* contact model: In this case, :math:`\eta_{n0}` is simply a dimensionless coefficent that scales the the overall damping coefficent. +The other supported option is :math:`d_{type} = 2`, which defines a simple damping model +similar to the *velocity* option + +.. math:: + + \eta_n = \eta_{n0}, + +but has additional checks to avoid non-physical damping after plastic deformation. + The total normal force is computed as the sum of the elastic and damping components: diff --git a/examples/granular/in.tableting.200 b/examples/granular/in.tableting.200 index d1ecc28aa1..02eb6743de 100644 --- a/examples/granular/in.tableting.200 +++ b/examples/granular/in.tableting.200 @@ -34,8 +34,9 @@ variable YieldStress equal 1.9e5 variable PoissonsRatio equal 0.4 variable SurfaceEnergy equal 2 variable SurfaceEnergyWall equal 0.0 -variable damp equal 0.2 variable psi_b equal 0.5 +variable damp equal 0.2 +variable damp_type equal 1 # linear_history = k_t, x_gammat, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} @@ -49,7 +50,7 @@ variable mu_roll equal 0.6 variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} variable gamma_roll equal 0.0 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} ${damp_type} & damping mdr & tangential linear_history ${kt} ${xgammat} ${mu_s} & rolling sds ${k_roll} ${gamma_roll} ${mu_roll} @@ -59,7 +60,7 @@ pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEne variable disp_upper equal 0.0 variable disp_lower equal 0.0 -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} ${damp_type} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" variable dieHeight2 equal 2*${dieHeight} diff --git a/examples/granular/in.triaxial.compaction.12 b/examples/granular/in.triaxial.compaction.12 index d10e325721..6a948157d3 100644 --- a/examples/granular/in.triaxial.compaction.12 +++ b/examples/granular/in.triaxial.compaction.12 @@ -30,14 +30,15 @@ variable PoissonsRatio equal 0.3 variable YieldStress equal 50e6 variable SurfaceEnergy equal 0.0 variable psi_b equal 0.5 -variable damp equal 1.0 +variable damp equal 0.2 +variable damp_type equal 1 # linear_history = k_t, x_gamma,t, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable xgammat equal 0.0 variable mu_s equal 0.5 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} ${damp_type} & damping mdr & tangential linear_history ${kt} ${xgammat} ${mu_s} @@ -56,7 +57,7 @@ region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_d region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} " +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} ${damp_type} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} " fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index a5dc5745a4..c35d63d668 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -44,12 +44,10 @@ GranSubModDamping::GranSubModDamping(GranularModel *gm, LAMMPS *lmp) : GranSubMo void GranSubModDamping::init() { + if (gm->normal_model->name == "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + damp = gm->normal_model->get_damp(); - if (gm->normal_model->name == "mdr") { - if (gm->tangential_model->name != "mdr") - error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); - damp_type = gm->normal_model->get_damp_type(); - } } /* ---------------------------------------------------------------------- @@ -135,6 +133,9 @@ GranSubModDampingTsuji::GranSubModDampingTsuji(GranularModel *gm, LAMMPS *lmp) : void GranSubModDampingTsuji::init() { + if (gm->normal_model->name == "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + double tmp = gm->normal_model->get_damp(); damp = 1.2728 - 4.2783 * tmp + 11.087 * square(tmp); damp += -22.348 * cube(tmp) + 27.467 * powint(tmp, 4); @@ -168,6 +169,9 @@ GranSubModDampingCoeffRestitution::GranSubModDampingCoeffRestitution(GranularMod void GranSubModDampingCoeffRestitution::init() { + if (gm->normal_model->name == "mdr") + error->all(FLERR, "Only damping mdr may be used with the mdr normal model"); + // Calculate prefactor, assume Hertzian as default double cor = gm->normal_model->get_damp(); double logcor = log(cor); @@ -196,6 +200,7 @@ void GranSubModDampingMDR::init() error->all(FLERR, "Damping mdr can only be used with mdr normal model"); damp = gm->normal_model->get_damp(); + damp_type = gm->normal_model->get_damp_type(); } /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index ecf53ea24c..aa53f5fcf6 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -482,7 +482,7 @@ void GranSubModNormalMDR::coeffs_to_local() if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); - if (damp_type != 1 && damp_type != 2) error->all(FLERR, "Illegal MDR normal model, damping type must an integer equal to 1 (mdr) or 2 (velocity)"); + if (damp_type != 1 && damp_type != 2) error->all(FLERR, "Illegal MDR normal model, damping type must an integer equal to 1 or 2"); G = E / (2.0 * (1.0 + nu)); // shear modulus kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus From bd6bb3ce1082df0c5e71ef9c8dfb46cfeb8f6875 Mon Sep 17 00:00:00 2001 From: talinke Date: Tue, 8 Apr 2025 17:35:09 -0700 Subject: [PATCH 104/396] Updated integrator, streamlined variables --- src/EXTRA-FIX/fix_langevin_gjf.cpp | 423 ++++++++++------------------- src/EXTRA-FIX/fix_langevin_gjf.h | 25 +- 2 files changed, 155 insertions(+), 293 deletions(-) diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp index 7f38a4d201..59d5cff1c5 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.cpp +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -44,8 +44,8 @@ enum { CONSTANT, EQUAL, ATOM }; /* ---------------------------------------------------------------------- */ -FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg), gjfflag(0), gfactor1(nullptr), gfactor2(nullptr), ratio(nullptr), +FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), gjfflag(0), tstr(nullptr), flangevin(nullptr), tforce(nullptr), lv(nullptr), id_temp(nullptr), random(nullptr) { if (narg < 8) error->all(FLERR, "Illegal fix langevin/gjf command"); @@ -78,16 +78,10 @@ FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : random = new RanMars(lmp, seed + comm->me); - // allocate per-type arrays for force prefactors - - // gfactor1 = new double[atom->ntypes + 1]; - // gfactor2 = new double[atom->ntypes + 1]; - // ratio = new double[atom->ntypes + 1]; int GJmethods = 8 // number of currently implemented GJ methods // optional args - for (int i = 1; i <= atom->ntypes; i++) ratio[i] = 1.0; osflag = 0; GJmethod = 0; @@ -105,39 +99,28 @@ FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg], "method") == 0) { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix langevin/gjf command"); GJmethod = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); - if (GJmethod <= 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in langevin/gjf command"); + if (GJmethod < 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in langevin/gjf command"); iarg += 2; } else error->all(FLERR, "Illegal fix langevin/gjf command"); } // set temperature = nullptr, user can override via fix_modify if wants bias - id_temp = nullptr; temperature = nullptr; - energy = 0.0; - - // flangevin is unallocated until first call to setup() - // compute_scalar checks for this and returns 0.0 - // if flangevin_allocated is not set - - flangevin = nullptr; - flangevin_allocated = 0; lv = nullptr; tforce = nullptr; - maxatom1 = maxatom2 = 0; // setup atom-based array for lv // register with Atom class // no need to set peratom_flag, b/c data is for internal use only - FixLangevin::grow_arrays(atom->nmax); + FixLangevinGJF::grow_arrays(atom->nmax); atom->add_callback(Atom::GROW); // initialize lv to zero - int nlocal = atom->nlocal; for (int i = 0; i < nlocal; i++) { lv[i][0] = 0.0; @@ -148,17 +131,13 @@ FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) : /* ---------------------------------------------------------------------- */ -FixLangevin::~FixLangevin() +FixLangevinGJF::~FixLangevinGJF() { if (copymode) return; delete random; delete[] tstr; - delete[] gfactor1; - delete[] gfactor2; - delete[] ratio; delete[] id_temp; - memory->destroy(flangevin); memory->destroy(tforce); memory->destroy(lv); @@ -167,18 +146,18 @@ FixLangevin::~FixLangevin() /* ---------------------------------------------------------------------- */ -int FixLangevin::setmask() +int FixLangevinGJF::setmask() { int mask = 0; mask |= INITIAL_INTEGRATE; mask |= FINAL_INTEGRATE; - mask |= END_OF_STEP; + if (!osflag) mask |= END_OF_STEP; return mask; } /* ---------------------------------------------------------------------- */ -void FixLangevin::init() +void FixLangevinGJF::init() { if (id_temp) { temperature = modify->get_compute_by_id(id_temp); @@ -193,23 +172,13 @@ void FixLangevin::init() if (tstr) { tvar = input->variable->find(tstr); - if (tvar < 0) error->all(FLERR, "Variable name {} for fix langevin does not exist", tstr); + if (tvar < 0) error->all(FLERR, "Variable name {} for fix langevin/gjf does not exist", tstr); if (input->variable->equalstyle(tvar)) tstyle = EQUAL; else if (input->variable->atomstyle(tvar)) tstyle = ATOM; else - error->all(FLERR, "Variable {} for fix langevin is invalid style", tstr); - } - - // set force prefactors - - if (!atom->rmass) { - for (int i = 1; i <= atom->ntypes; i++) { - gfactor1[i] = -atom->mass[i] / t_period / force->ftm2v; - gfactor2[i] = sqrt(atom->mass[i]) / force->ftm2v; - gfactor2[i] *= sqrt(2.0 * update->dt * force->boltz / t_period / force->mvv2e); // gjfflag - } + error->all(FLERR, "Variable {} for fix langevin/gjf is invalid style", tstr); } if (temperature && temperature->tempbias) @@ -219,44 +188,44 @@ void FixLangevin::init() if (utils::strmatch(update->integrate_style, "^respa")) { nlevels_respa = (static_cast(update->integrate))->nlevels; - if (gjfflag) error->all(FLERR, "Fix langevin gjf and run style respa are not compatible"); - } - - if (gjfflag) { - gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); - gjfc1 = 1.0 / (1.0 + update->dt / 2.0 / t_period); + error->all(FLERR, "Fix langevin gjf and run style respa are not compatible"); } + // Complete set of thermostats is given in Gronbech-Jensen, Molecular Physics, 118 (2020) switch (GJmethod) { case 1: gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); - gjfc1 = 1.0 / (1.0 + update->dt / 2.0 / t_period); break; case 2: - // Insert logic for method 2 + gjfc2 = exp(-update->dt / t_period); break; case 3: - // Insert logic for method 3 + gjfc2 = 1.0 - update->dt / t_period; break; case 4: - // Insert logic for method 4 + gjfc2 = ( sqrt(1.0 + 4.0 * (update->dt / t_period) ) - 1.0 ) / ( 2.0 * update->dt / t_period ); break; case 5: - // Insert logic for method 5 + gjfc2 = 1.0 / (1.0 + update->dt / t_period); break; case 6: - // Insert logic for method 6 + gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); break; - case 7: - // Insert logic for method 7 + case 7: // provided in Finkelstein (2021) + gjfc2 = 1; // TODO: correct this break; - case 8: - // Insert logic for method 8 + case 8: // provided in Gronbech-Jensen (2024) + gjfc2 = sqrt( (update->dt / t_period)*(update->dt / t_period) + 1.0 ) - update->dt / t_period; + break; + case 0: + gjfc2 = 0.0; break; default: error->all(FLERR, "Fix langevin/gjf method not found"); break; -} + } + gjfc1 = (1.0 + gjfc2) / 2.0; + gjfc3 = (1.0 - gjfc2) * t_period / update->dt; } /* ---------------------------------------------------------------------- @@ -268,10 +237,9 @@ void FixLangevin::init() 4. Velocity Choice in end_of_step() ------------------------------------------------------------------------- */ -void FixLangevin::initial_integrate(int /* vflag */) +void FixLangevinGJF::initial_integrate(int /* vflag */) { - double gamma1,gamma2; - + // This function provides the integration of the GJ formulation 24a-e double **x = atom->x; double **v = atom->v; double **f = atom->f; @@ -290,79 +258,21 @@ void FixLangevin::initial_integrate(int /* vflag */) double dtf = 0.5 * dt * ftm2v; double dtfm; - double c1sqrt = sqrt(gjfc1); - - // NVE integrates position and velocity according to Eq. 8a, 8b - // This function embeds the GJF formulation into the NVE framework, which corresponds to the GJF case c1=c3. + double c1sq = sqrt(gjfc1); + double c3sq = sqrt(gjfc3); + double csq = sqrt(gjfc3 / gjfc1); + double m, beta; - //NVE - if (rmass) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - dtfm = dtf / rmass[i]; - v[i][0] += dtfm * f[i][0]; - v[i][1] += dtfm * f[i][1]; - v[i][2] += dtfm * f[i][2]; - x[i][0] += dt * v[i][0]; - x[i][1] += dt * v[i][1]; - x[i][2] += dt * v[i][2]; - } - - } else { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - dtfm = dtf / mass[type[i]]; - v[i][0] += dtfm * f[i][0]; - v[i][1] += dtfm * f[i][1]; - v[i][2] += dtfm * f[i][2]; - x[i][0] += dt * v[i][0]; - x[i][1] += dt * v[i][1]; - x[i][2] += dt * v[i][2]; - } - } - - // The initial NVE integration should always use the on-site velocity. Therefore, a velocity correction - // must be done when using the half-step option. - //---------- + // If user elected vhalf, v needs to be reassigned to onsite velocity for integration if (!osflag) { - if (rmass) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - dtfm = dtf / rmass[i]; - // Undo NVE integration - x[i][0] -= dt * v[i][0]; - x[i][1] -= dt * v[i][1]; - x[i][2] -= dt * v[i][2]; - // Obtain Eq. 24a. lv[][] stores on-site velocity from previous timestep - v[i][0] = lv[i][0] + dtfm * f[i][0]; - v[i][1] = lv[i][1] + dtfm * f[i][1]; - v[i][2] = lv[i][2] + dtfm * f[i][2]; - // Redo NVE integration with correct velocity - x[i][0] += dt * v[i][0]; - x[i][1] += dt * v[i][1]; - x[i][2] += dt * v[i][2]; - } - - } else { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - dtfm = dtf / mass[type[i]]; - // Undo NVE integration - x[i][0] -= dt * v[i][0]; - x[i][1] -= dt * v[i][1]; - x[i][2] -= dt * v[i][2]; - // Obtain Eq. 24a. lv[][] stores on-site velocity from previous timestep - v[i][0] = lv[i][0] + dtfm * f[i][0]; - v[i][1] = lv[i][1] + dtfm * f[i][1]; - v[i][2] = lv[i][2] + dtfm * f[i][2]; - // Redo NVE integration with correct velocity - x[i][0] += dt * v[i][0]; - x[i][1] += dt * v[i][1]; - x[i][2] += dt * v[i][2]; - } - } + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + // lv is Eq. 24f from previous time step + v[i][0] = lv[i][0]; + v[i][1] = lv[i][1]; + v[i][2] = lv[i][2]; + } } - //---------- compute_target(); @@ -370,59 +280,58 @@ void FixLangevin::initial_integrate(int /* vflag */) for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { + if (tstyle == ATOM) tsqrt = sqrt(tforce[i]); - if (rmass) { - gamma2 = sqrt(rmass[i]) * sqrt(2.0*dt*boltz/t_period/mvv2e) / ftm2v; - gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt; + if (rmass) { + m = rmass[i]; + beta = tsqrt * sqrt(2.0*dt*rmass[i]*boltz/t_period/mvv2e) / ftm2v; } else { - gamma2 = gfactor2[type[i]] * tsqrt; + m = mass[type[i]]; + beta = tsqrt * sqrt(2.0*dt*atom->mass[i]*boltz/t_period/mvv2e) / ftm2v; } - fran[0] = gamma2*random->gaussian(); - fran[1] = gamma2*random->gaussian(); - fran[2] = gamma2*random->gaussian(); + + fran[0] = beta*random->gaussian(); + fran[1] = beta*random->gaussian(); + fran[2] = beta*random->gaussian(); + + // First integration delivers Eq. 24a and 24b: + dtfm = dtf / m; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; + x[i][0] += 0.5 * csq * dt * v[i][0]; + x[i][1] += 0.5 * csq * dt * v[i][1]; + x[i][2] += 0.5 * csq * dt * v[i][2]; - // NVE integrator delivers Eq. 24a, but also overshoots position integration. Calculate Eq. 24b: - x[i][0] -= 0.5 * dt * v[i][0]; - x[i][1] -= 0.5 * dt * v[i][1]; - x[i][2] -= 0.5 * dt * v[i][2]; // Calculate Eq. 24c: if (tbiasflag == BIAS) temperature->remove_bias(i,v[i]); - if (rmass) { - lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c1sqrt / (2.0 * rmass[i])) * fran[0]; - lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c1sqrt / (2.0 * rmass[i])) * fran[1]; - lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c1sqrt / (2.0 * rmass[i])) * fran[2]; - } else { - lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c1sqrt / (2.0 * mass[type[i]])) * fran[0]; - lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c1sqrt / (2.0 * mass[type[i]])) * fran[1]; - lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c1sqrt / (2.0 * mass[type[i]])) * fran[2]; - } + lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c3sqrt / (2.0 * m)) * fran[0]; + lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c3sqrt / (2.0 * m)) * fran[1]; + lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c3sqrt / (2.0 * m)) * fran[2]; + if (tbiasflag == BIAS) temperature->restore_bias(i,v[i]); if (tbiasflag == BIAS) temperature->restore_bias(i,lv[i]); // Calculate Eq. 24d - if (tbiasflag == BIAS) temperature->remove_bias(i, lv[i]); - if (atom->rmass) { - v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * (0.5 / rmass[i]) * fran[0]; - v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * (0.5 / rmass[i]) * fran[1]; - v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * (0.5 / rmass[i]) * fran[2]; - } else { - v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * (0.5 / mass[type[i]]) * fran[0]; - v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * (0.5 / mass[type[i]]) * fran[1]; - v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * (0.5 / mass[type[i]]) * fran[2]; - } - if (tbiasflag == BIAS) temperature->restore_bias(i, lv[i]); - // Calculate Eq. 24e. NVE integrator then calculates Eq. 24f. - x[i][0] += 0.5 * dt * v[i][0]; - x[i][1] += 0.5 * dt * v[i][1]; - x[i][2] += 0.5 * dt * v[i][2]; + if (tbiasflag == BIAS) temperature->remove_bias(i, v[i]); + + v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * csq * (0.5 / m) * fran[0]; + v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * csq * (0.5 / m) * fran[1]; + v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * csq * (0.5 / m) * fran[2]; + if (tbiasflag == BIAS) temperature->restore_bias(i, v[i]); + + // Calculate Eq. 24e. Final integrator then calculates Eq. 24f after force update. + x[i][0] += 0.5 * csq * dt * v[i][0]; + x[i][1] += 0.5 * csq * dt * v[i][1]; + x[i][2] += 0.5 * csq * dt * v[i][2]; } } } -void FixLangevin::final_integrate() +void FixLangevinGJF::final_integrate() { double dtfm; double dt = update->dt; @@ -444,18 +353,18 @@ void FixLangevin::final_integrate() for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { dtfm = dtf / rmass[i]; - v[i][0] += dtfm * f[i][0]; - v[i][1] += dtfm * f[i][1]; - v[i][2] += dtfm * f[i][2]; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; } } else { for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { dtfm = dtf / mass[type[i]]; - v[i][0] += dtfm * f[i][0]; - v[i][1] += dtfm * f[i][1]; - v[i][2] += dtfm * f[i][2]; + v[i][0] += csq * dtfm * f[i][0]; + v[i][1] += csq * dtfm * f[i][1]; + v[i][2] += csq * dtfm * f[i][2]; } } } @@ -464,7 +373,7 @@ void FixLangevin::final_integrate() set current t_target and t_sqrt ------------------------------------------------------------------------- */ -void FixLangevin::compute_target() +void FixLangevinGJF::compute_target() { int *mask = atom->mask; int nlocal = atom->nlocal; @@ -483,7 +392,7 @@ void FixLangevin::compute_target() if (tstyle == EQUAL) { t_target = input->variable->compute_equal(tvar); if (t_target < 0.0) - error->one(FLERR, "Fix langevin variable returned negative temperature"); + error->one(FLERR, "Fix langevin/gjf variable returned negative temperature"); tsqrt = sqrt(t_target); } else { if (atom->nmax > maxatom2) { @@ -495,86 +404,94 @@ void FixLangevin::compute_target() for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) if (tforce[i] < 0.0) - error->one(FLERR, "Fix langevin variable returned negative temperature"); + error->one(FLERR, "Fix langevin/gjf variable returned negative temperature"); } modify->addstep_compute(update->ntimestep + 1); } } /* ---------------------------------------------------------------------- - tally energy transfer to thermal reservoir, select velocity for GJF + select velocity for GJF ------------------------------------------------------------------------- */ -void FixLangevin::end_of_step() +void FixLangevinGJF::end_of_step() { double **v = atom->v; int *mask = atom->mask; int nlocal = atom->nlocal; - energy_onestep = 0.0; - - if (tallyflag) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - energy_onestep += flangevin[i][0]*v[i][0] + flangevin[i][1]*v[i][1] + - flangevin[i][2]*v[i][2]; - } - - energy += energy_onestep*update->dt; - - // After the NVE integrator delivers 24f, either the on-site or half-step + // After the final integrator delivers 24f, either the on-site or half-step // velocity is used in remaining simulation tasks, depending on user input - if (gjfflag && !osflag) { - double tmp[3]; - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - // v is Eq. 24f - tmp[0] = v[i][0]; - tmp[1] = v[i][1]; - tmp[2] = v[i][2]; - // Move on with half-step velocity - v[i][0] = lv[i][0]; - v[i][1] = lv[i][1]; - v[i][2] = lv[i][2]; - // store Eq. 24f in lv for next timestep - lv[i][0] = tmp[0]; - lv[i][1] = tmp[1]; - lv[i][2] = tmp[2]; - } - } + double tmp[3]; + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + // v is Eq. 24f + tmp[0] = v[i][0]; + tmp[1] = v[i][1]; + tmp[2] = v[i][2]; + // Move on with half-step velocity + v[i][0] = lv[i][0]; + v[i][1] = lv[i][1]; + v[i][2] = lv[i][2]; + // store Eq. 24f in lv for next timestep + lv[i][0] = tmp[0]; + lv[i][1] = tmp[1]; + lv[i][2] = tmp[2]; + } } // clang-format on /* ---------------------------------------------------------------------- */ -void FixLangevin::reset_target(double t_new) +void FixLangevinGJF::reset_target(double t_new) { t_target = t_start = t_stop = t_new; } /* ---------------------------------------------------------------------- */ -void FixLangevin::reset_dt() +void FixLangevinGJF::reset_dt() { - if (atom->mass) { - for (int i = 1; i <= atom->ntypes; i++) { - gfactor2[i] = sqrt(atom->mass[i]) / force->ftm2v; - if (gjfflag) - gfactor2[i] *= sqrt(2.0 * update->dt * force->boltz / t_period / force->mvv2e); // sqrt(2*alpha*kT*dt) - else - gfactor2[i] *= sqrt(24.0 * force->boltz / t_period / update->dt / force->mvv2e); - gfactor2[i] *= 1.0 / sqrt(ratio[i]); - } - } - if (gjfflag) { - gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); - gjfc1 = 1.0 / (1.0 + update->dt / 2.0 / t_period); + // Complete set of thermostats is given in Gronbech-Jensen, Molecular Physics, 118 (2020) + switch (GJmethod) { + case 1: + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); + break; + case 2: + gjfc2 = exp(-update->dt / t_period); + break; + case 3: + gjfc2 = 1.0 - update->dt / t_period; + break; + case 4: + gjfc2 = ( sqrt(1.0 + 4.0 * (update->dt / t_period) ) - 1.0 ) / ( 2.0 * update->dt / t_period ); + break; + case 5: + gjfc2 = 1.0 / (1.0 + update->dt / t_period); + break; + case 6: + gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); + break; + case 7: // provided in Finkelstein (2021) + gjfc2 = 1; // TODO: correct this + break; + case 8: // provided in Gronbech-Jensen (2024) + gjfc2 = sqrt( (update->dt / t_period)*(update->dt / t_period) + 1.0 ) - update->dt / t_period; + break; + case 0: + gjfc2 = 0.0; + break; + default: + error->all(FLERR, "Fix langevin/gjf method not found"); + break; } + gjfc1 = (1.0 + gjfc2) / 2.0; + gjfc3 = (1.0 - gjfc2) * t_period / update->dt; } /* ---------------------------------------------------------------------- */ -int FixLangevin::modify_param(int narg, char **arg) +int FixLangevinGJF::modify_param(int narg, char **arg) { if (strcmp(arg[0], "temp") == 0) { if (narg < 2) utils::missing_cmd_args(FLERR, "fix_modify", error); @@ -594,52 +511,11 @@ int FixLangevin::modify_param(int narg, char **arg) return 0; } -/* ---------------------------------------------------------------------- */ - -double FixLangevin::compute_scalar() -{ - if (!tallyflag || !flangevin_allocated) return 0.0; - - // capture the very first energy transfer to thermal reservoir - - double **v = atom->v; - int *mask = atom->mask; - int nlocal = atom->nlocal; - - if (update->ntimestep == update->beginstep) { - energy_onestep = 0.0; - if (!gjfflag) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - energy_onestep += - flangevin[i][0] * v[i][0] + flangevin[i][1] * v[i][1] + flangevin[i][2] * v[i][2]; - energy = 0.5 * energy_onestep * update->dt; - } else { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - if (tbiasflag) temperature->remove_bias(i, lv[i]); - energy_onestep += - flangevin[i][0] * lv[i][0] + flangevin[i][1] * lv[i][1] + flangevin[i][2] * lv[i][2]; - if (tbiasflag) temperature->restore_bias(i, lv[i]); - } - energy = -0.5 * energy_onestep * update->dt; - } - } - - // convert midstep energy back to previous fullstep energy - - double energy_me = energy - 0.5 * energy_onestep * update->dt; - - double energy_all; - MPI_Allreduce(&energy_me, &energy_all, 1, MPI_DOUBLE, MPI_SUM, world); - return -energy_all; -} - /* ---------------------------------------------------------------------- extract thermostat properties ------------------------------------------------------------------------- */ -void *FixLangevin::extract(const char *str, int &dim) +void *FixLangevinGJF::extract(const char *str, int &dim) { dim = 0; if (strcmp(str, "t_target") == 0) { return &t_target; } @@ -650,11 +526,10 @@ void *FixLangevin::extract(const char *str, int &dim) memory usage of tally array ------------------------------------------------------------------------- */ -double FixLangevin::memory_usage() +double FixLangevinGJF::memory_usage() { double bytes = 0.0; - if (gjfflag) bytes += (double) atom->nmax * 3 * sizeof(double); - if (tallyflag || osflag) bytes += (double) atom->nmax * 3 * sizeof(double); + bytes += (double) atom->nmax * 3 * sizeof(double); if (tforce) bytes += (double) atom->nmax * sizeof(double); return bytes; } @@ -663,16 +538,16 @@ double FixLangevin::memory_usage() allocate atom-based array for lv ------------------------------------------------------------------------- */ -void FixLangevin::grow_arrays(int nmax) +void FixLangevinGJF::grow_arrays(int nmax) { - memory->grow(lv, nmax, 3, "fix_langevin:lv"); + memory->grow(lv, nmax, 3, "fix_langevin_gjf:lv"); } /* ---------------------------------------------------------------------- copy values within local atom-based array ------------------------------------------------------------------------- */ -void FixLangevin::copy_arrays(int i, int j, int /*delflag*/) +void FixLangevinGJF::copy_arrays(int i, int j, int /*delflag*/) { lv[j][0] = lv[i][0]; lv[j][1] = lv[i][1]; @@ -683,7 +558,7 @@ void FixLangevin::copy_arrays(int i, int j, int /*delflag*/) pack values in local atom-based array for exchange with another proc ------------------------------------------------------------------------- */ -int FixLangevin::pack_exchange(int i, double *buf) +int FixLangevinGJF::pack_exchange(int i, double *buf) { int n = 0; buf[n++] = lv[i][0]; @@ -696,7 +571,7 @@ int FixLangevin::pack_exchange(int i, double *buf) unpack values in local atom-based array from exchange with another proc ------------------------------------------------------------------------- */ -int FixLangevin::unpack_exchange(int nlocal, double *buf) +int FixLangevinGJF::unpack_exchange(int nlocal, double *buf) { int n = 0; lv[nlocal][0] = buf[n++]; diff --git a/src/EXTRA-FIX/fix_langevin_gjf.h b/src/EXTRA-FIX/fix_langevin_gjf.h index c54772c457..df6b80e1b7 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.h +++ b/src/EXTRA-FIX/fix_langevin_gjf.h @@ -24,21 +24,19 @@ FixStyle(langevin,FixLangevin); namespace LAMMPS_NS { -class FixLangevin : public Fix { +class FixLangevinGJF : public Fix { public: - FixLangevin(class LAMMPS *, int, char **); - ~FixLangevin() override; + FixLangevinGJF(class LAMMPS *, int, char **); + ~FixLangevinGJF() override; int setmask() override; void init() override; void setup(int) override; void initial_integrate(int) override; - void post_force(int) override; - void post_force_respa(int, int, int) override; + void final_integrate() override; void end_of_step() override; void reset_target(double) override; void reset_dt() override; int modify_param(int, char **) override; - double compute_scalar() override; double memory_usage() override; void *extract(const char *, int &) override; void grow_arrays(int) override; @@ -48,19 +46,13 @@ class FixLangevin : public Fix { protected: int osflag, GJmethod; - int flangevin_allocated; double t_start, t_stop, t_period, t_target; - double *gfactor1, *gfactor2, *ratio; - double energy, energy_onestep; + double *gfactor2; double tsqrt; - double gjfc1, gjfc2; + double gjfc1, gjfc2, gjfc3; int tstyle, tvar; char *tstr; - class AtomVecEllipsoid *avec; - - int maxatom1, maxatom2; - double **flangevin; double *tforce; double **lv; //half step velocity @@ -71,11 +63,6 @@ class FixLangevin : public Fix { class RanMars *random; int seed; - template - void post_force_templated(); - - void omega_thermostat(); - void angmom_thermostat(); void compute_target(); }; From f16f65c8dc10dbad3624344b4aeda5cbc19f443f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Apr 2025 10:45:51 -0400 Subject: [PATCH 105/396] add missing entries --- src/library.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/library.cpp b/src/library.cpp index 01793612be..74186922ec 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -1701,6 +1701,18 @@ report the "native" data type. The following tables are provided: - Type - Length - Description + * - boxlo + - double + - 3 + - lower box boundaries in x-, y-, and z-direction; see :doc:`create_box`. + * - boxhi + - double + - 3 + - lower box boundaries in x-, y-, and z-direction; see :doc:`create_box`. + * - boxxlo + - double + - 1 + - lower box boundary in x-direction; see :doc:`create_box`. * - boxxhi - double - 1 @@ -1724,19 +1736,19 @@ report the "native" data type. The following tables are provided: * - sublo - double - 3 - - subbox lower boundaries + - subbox lower boundaries in x-, y-, and z-direction * - subhi - double - 3 - - subbox upper boundaries + - subbox upper boundaries in x-, y-, and z-direction * - sublo_lambda - double - 3 - - subbox lower boundaries in fractional coordinates (for triclinic cells) + - subbox lower boundaries in fractional coordinates (for triclinic cells only) * - subhi_lambda - double - 3 - - subbox upper boundaries in fractional coordinates (for triclinic cells) + - subbox upper boundaries in fractional coordinates (for triclinic cells only) * - periodicity - int - 3 From 8fd1bf23c9a02cf9639bd9bc2821569f4021276d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Apr 2025 16:12:47 -0400 Subject: [PATCH 106/396] only compute special neighbors of a template if it has bonds --- src/DPD-REACT/npair_half_bin_newton_ssa.cpp | 11 +++++------ src/OPENMP/npair_bin_ghost_omp.cpp | 2 +- src/OPENMP/npair_bin_omp.cpp | 12 ++++++------ src/OPENMP/npair_multi_old_omp.cpp | 4 ++-- src/OPENMP/npair_multi_omp.cpp | 12 ++++++------ src/OPENMP/npair_nsq_ghost_omp.cpp | 2 +- src/OPENMP/npair_nsq_omp.cpp | 4 ++-- src/OPENMP/npair_respa_bin_omp.cpp | 2 +- src/OPENMP/npair_respa_nsq_omp.cpp | 2 +- src/npair_bin.cpp | 12 ++++++------ src/npair_bin_ghost.cpp | 6 +++--- src/npair_multi.cpp | 12 ++++++------ src/npair_multi_old.cpp | 4 ++-- src/npair_nsq.cpp | 4 ++-- src/npair_nsq_ghost.cpp | 7 +++---- src/npair_respa_bin.cpp | 2 +- src/npair_respa_nsq.cpp | 2 +- 17 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/DPD-REACT/npair_half_bin_newton_ssa.cpp b/src/DPD-REACT/npair_half_bin_newton_ssa.cpp index 7393e54f78..902921bc90 100644 --- a/src/DPD-REACT/npair_half_bin_newton_ssa.cpp +++ b/src/DPD-REACT/npair_half_bin_newton_ssa.cpp @@ -203,10 +203,9 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], - onemols[imol]->nspecial[iatom], - tag[j]-tagprev); + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if (domain->minimum_image_check(delx,dely,delz)) @@ -286,11 +285,11 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) which = find_special(special[j],nspecial[j],tag[i]); else { int jmol = molindex[j]; - if (jmol >= 0) { + if ((jmol >= 0) && onemols[jmol]->special) { int jatom = molatom[j]; which = find_special(onemols[jmol]->special[jatom], - onemols[jmol]->nspecial[jatom], - tag[i] - (tag[j] - jatom - 1)); + onemols[jmol]->nspecial[jatom], + tag[i] - (tag[j] - jatom - 1)); } else which = 0; } if (which == 0) neighptr[n++] = j; diff --git a/src/OPENMP/npair_bin_ghost_omp.cpp b/src/OPENMP/npair_bin_ghost_omp.cpp index 93dd7b1110..f33bd821f7 100644 --- a/src/OPENMP/npair_bin_ghost_omp.cpp +++ b/src/OPENMP/npair_bin_ghost_omp.cpp @@ -135,7 +135,7 @@ void NPairBinGhostOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/OPENMP/npair_bin_omp.cpp b/src/OPENMP/npair_bin_omp.cpp index 7922d76612..21bb887177 100644 --- a/src/OPENMP/npair_bin_omp.cpp +++ b/src/OPENMP/npair_bin_omp.cpp @@ -207,9 +207,9 @@ void NPairBinOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol] ->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol] ->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -230,9 +230,9 @@ void NPairBinOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) neighptr[n++] = j; diff --git a/src/OPENMP/npair_multi_old_omp.cpp b/src/OPENMP/npair_multi_old_omp.cpp index fa790e177a..d07240cf9b 100644 --- a/src/OPENMP/npair_multi_old_omp.cpp +++ b/src/OPENMP/npair_multi_old_omp.cpp @@ -204,7 +204,7 @@ void NPairMultiOldOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -223,7 +223,7 @@ void NPairMultiOldOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/OPENMP/npair_multi_omp.cpp b/src/OPENMP/npair_multi_omp.cpp index cbc21ebc29..c85726f4fb 100644 --- a/src/OPENMP/npair_multi_omp.cpp +++ b/src/OPENMP/npair_multi_omp.cpp @@ -232,9 +232,9 @@ void NPairMultiOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -255,9 +255,9 @@ void NPairMultiOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) diff --git a/src/OPENMP/npair_nsq_ghost_omp.cpp b/src/OPENMP/npair_nsq_ghost_omp.cpp index a270fbb84d..59fa8ed6f5 100644 --- a/src/OPENMP/npair_nsq_ghost_omp.cpp +++ b/src/OPENMP/npair_nsq_ghost_omp.cpp @@ -131,7 +131,7 @@ void NPairNsqGhostOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/OPENMP/npair_nsq_omp.cpp b/src/OPENMP/npair_nsq_omp.cpp index 5d6aa518b0..1a7058791c 100644 --- a/src/OPENMP/npair_nsq_omp.cpp +++ b/src/OPENMP/npair_nsq_omp.cpp @@ -181,7 +181,7 @@ void NPairNsqOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -200,7 +200,7 @@ void NPairNsqOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/OPENMP/npair_respa_bin_omp.cpp b/src/OPENMP/npair_respa_bin_omp.cpp index a069affb06..691d807498 100644 --- a/src/OPENMP/npair_respa_bin_omp.cpp +++ b/src/OPENMP/npair_respa_bin_omp.cpp @@ -204,7 +204,7 @@ void NPairRespaBinOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/OPENMP/npair_respa_nsq_omp.cpp b/src/OPENMP/npair_respa_nsq_omp.cpp index deba473678..8483872ca0 100644 --- a/src/OPENMP/npair_respa_nsq_omp.cpp +++ b/src/OPENMP/npair_respa_nsq_omp.cpp @@ -186,7 +186,7 @@ void NPairRespaNsqOmp::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/npair_bin.cpp b/src/npair_bin.cpp index 2c6fbbb49b..3ed567a008 100644 --- a/src/npair_bin.cpp +++ b/src/npair_bin.cpp @@ -199,9 +199,9 @@ void NPairBin::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -222,9 +222,9 @@ void NPairBin::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) diff --git a/src/npair_bin_ghost.cpp b/src/npair_bin_ghost.cpp index 8403bc8f3d..5efe7898bb 100644 --- a/src/npair_bin_ghost.cpp +++ b/src/npair_bin_ghost.cpp @@ -130,9 +130,9 @@ void NPairBinGhost::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) diff --git a/src/npair_multi.cpp b/src/npair_multi.cpp index 44c68a9195..f41088d324 100644 --- a/src/npair_multi.cpp +++ b/src/npair_multi.cpp @@ -229,9 +229,9 @@ void NPairMulti::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) @@ -252,9 +252,9 @@ void NPairMulti::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], - tag[j] - tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) diff --git a/src/npair_multi_old.cpp b/src/npair_multi_old.cpp index 3d983bd7fd..8d2bb71f10 100644 --- a/src/npair_multi_old.cpp +++ b/src/npair_multi_old.cpp @@ -197,7 +197,7 @@ void NPairMultiOld::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -216,7 +216,7 @@ void NPairMultiOld::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/npair_nsq.cpp b/src/npair_nsq.cpp index 9f469de480..ec64e7d2a3 100644 --- a/src/npair_nsq.cpp +++ b/src/npair_nsq.cpp @@ -173,7 +173,7 @@ void NPairNsq::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else @@ -192,7 +192,7 @@ void NPairNsq::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/npair_nsq_ghost.cpp b/src/npair_nsq_ghost.cpp index 47009deff7..2f9c5123b7 100644 --- a/src/npair_nsq_ghost.cpp +++ b/src/npair_nsq_ghost.cpp @@ -127,10 +127,9 @@ void NPairNsqGhost::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i],nspecial[i],tag[j]); - else if (imol >= 0) - which = find_special(onemols[imol]->special[iatom], - onemols[imol]->nspecial[iatom], - tag[j]-tagprev); + else if ((imol >= 0) && onemols[imol]->special) + which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], + tag[j] - tagprev); else which = 0; if (which == 0) neighptr[n++] = j; else if (domain->minimum_image_check(delx,dely,delz)) diff --git a/src/npair_respa_bin.cpp b/src/npair_respa_bin.cpp index 5347f4d3a0..6a6c52de87 100644 --- a/src/npair_respa_bin.cpp +++ b/src/npair_respa_bin.cpp @@ -192,7 +192,7 @@ void NPairRespaBin::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else diff --git a/src/npair_respa_nsq.cpp b/src/npair_respa_nsq.cpp index 065c9eb6d6..43bf0d649c 100644 --- a/src/npair_respa_nsq.cpp +++ b/src/npair_respa_nsq.cpp @@ -179,7 +179,7 @@ void NPairRespaNsq::build(NeighList *list) if (molecular != Atom::ATOMIC) { if (!moltemplate) which = find_special(special[i], nspecial[i], tag[j]); - else if (imol >= 0) + else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], onemols[imol]->nspecial[iatom], tag[j] - tagprev); else From e9695df0e88e884d5d86fac95dd0a44405739103 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Apr 2025 17:22:38 -0400 Subject: [PATCH 107/396] Provide some additional explanations for the "boost neigh_modify one" error --- doc/src/Errors_details.rst | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/doc/src/Errors_details.rst b/doc/src/Errors_details.rst index f2728321e6..442bceebf5 100644 --- a/doc/src/Errors_details.rst +++ b/doc/src/Errors_details.rst @@ -982,3 +982,50 @@ order of preference there are: - Send an email to ``developers@lammps.org`` - Send an email to an :doc:`individual LAMMPS developer ` that you know and trust + +.. _err0036: + +Neighbor list overflow, boost neigh_modify one +---------------------------------------------- + +The neighbor list code in LAMMPS uses a special memory allocation strategy +to speed up building and accessing neighbor lists. + +Instead of making a memory allocation for each list of neighbors of the atoms +LAMMPS allocates "pages" that have room for several neighbor lists. This has +two main advantages: + +#. It is not needed to first count how many neighbors there are for an + atom to determine the storage required. Since the pages are much + larger than individual lists, LAMMPS just "fills up" the page until + there is not enough space left and then allocates a new page. + +#. There are fewer calls to the memory allocator functions (which can be + time consuming for long-running jobs and fragmented memory space) and + the resulting neighbor lists are close to each other physically which + improves cache efficiency. + +This is controlled by the two parameters "one" and "page", respectively, +that can be set via the :doc:`neigh_modify command `. The +parameter "one" is the estimate for the number of entries in a single +neighbor list. The parameter "page" is the size of the page. The +default settings are suitable for most systems. They need to be changed +when simulating a system with a very high density or when setting a very +long cutoff (e.g. :math:`\gtrapprox 15 \AA` with :doc:`units real +`). The value of "page" must be at least 10x the value of "one", +but 50x or 100x are recommended to avoid wasting memory. The neighbor +list storage is typically the largest amount of RAM required by a +LAMMPS calculation. + +Even though the LAMMPS error message recommends to increase the "one" +parameter, this may not be the correct solution since the neighbor list +overflow can be a symptom of some other error that cannot be easily +detected. For example, a frequent reason for an (unexpected) high +density are incorrect box boundaries or coordinates provided as +fractional coordinates. In both cases, LAMMPS cannot easily know +whether the input geometry has such a high density (and thus requiring +more neighbor list storage) intentionally. + +When boosting (= increasing) the "one" parameter, it is recommended to +also increase the value for the "page" parameter to maintain the ratio +between "one" and "page". From 6e7cbbeb9c69668e9b13393422d2dacfeef52905 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Apr 2025 17:35:42 -0400 Subject: [PATCH 108/396] add errorurl(36) message to all "boost neigh_modify one" errors --- src/DPD-REACT/npair_half_bin_newton_ssa.cpp | 12 +++++----- src/INTEL/fix_intel.cpp | 2 +- src/INTEL/npair_halffull_intel.cpp | 8 +++---- src/INTEL/npair_skip_intel.cpp | 4 ++-- src/INTEL/npair_trim_intel.cpp | 2 +- src/INTERLAYER/pair_ilp_graphene_hbn.cpp | 10 ++++---- src/INTERLAYER/pair_ilp_tmd.cpp | 24 +++++++++---------- .../pair_kolmogorov_crespi_full.cpp | 10 ++++---- src/KOKKOS/npair_copy_kokkos.cpp | 2 +- src/KOKKOS/npair_trim_kokkos.cpp | 2 +- src/MANYBODY/pair_airebo.cpp | 2 +- src/MANYBODY/pair_comb.cpp | 2 +- src/MANYBODY/pair_comb3.cpp | 2 +- src/MANYBODY/pair_extep.cpp | 2 +- src/MANYBODY/pair_lcbop.cpp | 2 +- src/MANYBODY/pair_rebomos.cpp | 2 +- src/OPENMP/fix_neigh_history_omp.cpp | 8 +++---- src/OPENMP/npair_bin_ghost_omp.cpp | 2 +- src/OPENMP/npair_bin_omp.cpp | 2 +- src/OPENMP/npair_halffull_omp.cpp | 2 +- src/OPENMP/npair_multi_old_omp.cpp | 2 +- src/OPENMP/npair_multi_omp.cpp | 2 +- src/OPENMP/npair_nsq_ghost_omp.cpp | 2 +- src/OPENMP/npair_nsq_omp.cpp | 2 +- src/OPENMP/npair_respa_bin_omp.cpp | 6 ++--- src/OPENMP/npair_respa_nsq_omp.cpp | 6 ++--- src/OPENMP/npair_trim_omp.cpp | 2 +- src/OPENMP/pair_airebo_omp.cpp | 2 +- src/OPENMP/pair_comb_omp.cpp | 2 +- src/OPENMP/pair_rebomos_omp.cpp | 2 +- src/fix_neigh_history.cpp | 8 +++---- src/npair_bin.cpp | 2 +- src/npair_bin_ghost.cpp | 2 +- src/npair_halffull.cpp | 2 +- src/npair_multi.cpp | 2 +- src/npair_multi_old.cpp | 2 +- src/npair_nsq.cpp | 2 +- src/npair_nsq_ghost.cpp | 2 +- src/npair_respa_bin.cpp | 6 ++--- src/npair_respa_nsq.cpp | 6 ++--- src/npair_skip.cpp | 2 +- src/npair_skip_respa.cpp | 6 ++--- src/npair_skip_size_off2on.cpp | 2 +- src/npair_skip_size_off2on_oneside.cpp | 2 +- src/npair_trim.cpp | 2 +- 45 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/DPD-REACT/npair_half_bin_newton_ssa.cpp b/src/DPD-REACT/npair_half_bin_newton_ssa.cpp index 902921bc90..850330aeaa 100644 --- a/src/DPD-REACT/npair_half_bin_newton_ssa.cpp +++ b/src/DPD-REACT/npair_half_bin_newton_ssa.cpp @@ -99,12 +99,12 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) MyPage *ipage = list->ipage; auto ns_ssa = dynamic_cast(ns); - if (!ns_ssa) error->one(FLERR, "NStencil wasn't a NStencilSSA object"); + if (!ns_ssa) error->one(FLERR, Error::NOLASTLINE, "NStencil wasn't a NStencilSSA object"); int *nstencil_ssa = &(ns_ssa->nstencil_ssa[0]); int nstencil_full = ns_ssa->nstencil; auto nb_ssa = dynamic_cast(nb); - if (!nb_ssa) error->one(FLERR, "NBin wasn't a NBinSSA object"); + if (!nb_ssa) error->one(FLERR, Error::NOLASTLINE, "NBin wasn't a NBinSSA object"); int *bins = nb_ssa->bins; int *binhead = nb_ssa->binhead; int *gairhead_ssa = &(nb_ssa->gairhead_ssa[0]); @@ -160,7 +160,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) for (zbin = lbinzlo + zoff; zbin < lbinzhi; zbin += sz1) { for (ybin = lbinylo + yoff - ns_ssa->sy; ybin < lbinyhi; ybin += sy1) { for (xbin = lbinxlo + xoff - ns_ssa->sx; xbin < lbinxhi; xbin += sx1) { - if (workItem >= phaseLenEstimate) error->one(FLERR,"phaseLenEstimate was too small"); + if (workItem >= phaseLenEstimate) error->one(FLERR, Error::NOLASTLINE, "phaseLenEstimate was too small"); ssa_itemLoc[workPhase][workItem] = inum; // record where workItem starts in ilist for (int subphase = 0; subphase < 4; subphase++) { @@ -223,7 +223,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) } ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } // record where workItem ends in ilist @@ -239,7 +239,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) } } - if (ssa_phaseCt != workPhase) error->one(FLERR,"ssa_phaseCt was wrong"); + if (ssa_phaseCt != workPhase) error->one(FLERR, Error::NOLASTLINE, "ssa_phaseCt was wrong"); list->inum = inum; @@ -309,7 +309,7 @@ void NPairHalfBinNewtonSSA::build(NeighList *list) } ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor (ghost) list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor (ghost) list overflow, boost neigh_modify one" + utils::errorurl(36)); } ssa_gitemLen[workPhase][0] = locAIRct; ssa_gphaseLen[workPhase] = 1; diff --git a/src/INTEL/fix_intel.cpp b/src/INTEL/fix_intel.cpp index 7e82d3a63b..398b7be8b4 100644 --- a/src/INTEL/fix_intel.cpp +++ b/src/INTEL/fix_intel.cpp @@ -942,7 +942,7 @@ void FixIntel::add_off_results(const ft * _noalias const f_in, int nlocal = atom->nlocal; if (neighbor->ago == 0) { if (_off_overflow_flag[LMP_OVERFLOW]) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); _offload_nlocal = _off_overflow_flag[LMP_LOCAL_MAX] + 1; _offload_min_ghost = _off_overflow_flag[LMP_GHOST_MIN]; _offload_nghost = _off_overflow_flag[LMP_GHOST_MAX] + 1 - diff --git a/src/INTEL/npair_halffull_intel.cpp b/src/INTEL/npair_halffull_intel.cpp index 134b768cc5..f88d01a24c 100644 --- a/src/INTEL/npair_halffull_intel.cpp +++ b/src/INTEL/npair_halffull_intel.cpp @@ -149,7 +149,7 @@ void NPairHalffullNewtonIntel::build_t(NeighList *list, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; @@ -223,7 +223,7 @@ void NPairHalffullNewtonIntel::build_t3(NeighList *list, int *numhalf) ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; @@ -396,7 +396,7 @@ void NPairHalffullTrimNewtonIntel::build_t(NeighList *list, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; @@ -490,7 +490,7 @@ void NPairHalffullTrimNewtonIntel::build_t3(NeighList *list, int *numhalf, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_full; diff --git a/src/INTEL/npair_skip_intel.cpp b/src/INTEL/npair_skip_intel.cpp index 9353a6f520..b14e045f54 100644 --- a/src/INTEL/npair_skip_intel.cpp +++ b/src/INTEL/npair_skip_intel.cpp @@ -170,7 +170,7 @@ void NPairSkipIntel::build_t(NeighList *list, int *numhalf, int *cnumneigh, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } _inum_counts[tid] = my_inum; } @@ -415,7 +415,7 @@ void NPairSkipTrimIntel::build_t(NeighList *list, int *numhalf, int *cnumneigh, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } _inum_counts[tid] = my_inum; diff --git a/src/INTEL/npair_trim_intel.cpp b/src/INTEL/npair_trim_intel.cpp index dcf10a3c87..7dd0ab2fb2 100644 --- a/src/INTEL/npair_trim_intel.cpp +++ b/src/INTEL/npair_trim_intel.cpp @@ -116,7 +116,7 @@ void NPairTrimIntel::build_t(NeighList *list, ipage.vgot(n); if (ipage.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } list->inum = inum_copy; diff --git a/src/INTERLAYER/pair_ilp_graphene_hbn.cpp b/src/INTERLAYER/pair_ilp_graphene_hbn.cpp index 5cddbc5edf..af3b9ce36a 100644 --- a/src/INTERLAYER/pair_ilp_graphene_hbn.cpp +++ b/src/INTERLAYER/pair_ilp_graphene_hbn.cpp @@ -692,11 +692,11 @@ void PairILPGrapheneHBN::ILP_neigh() ILP_firstneigh[i] = neighptr; ILP_numneigh[i] = n; if (n > 3) - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -835,7 +835,7 @@ void PairILPGrapheneHBN::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -970,7 +970,7 @@ void PairILPGrapheneHBN::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -1007,7 +1007,7 @@ void PairILPGrapheneHBN::calc_normal() } } } else { - error->one(FLERR, "There are too many neighbors for calculating normals"); + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals"); } //############################################################################################## diff --git a/src/INTERLAYER/pair_ilp_tmd.cpp b/src/INTERLAYER/pair_ilp_tmd.cpp index 73f89803c2..5ac2d867de 100644 --- a/src/INTERLAYER/pair_ilp_tmd.cpp +++ b/src/INTERLAYER/pair_ilp_tmd.cpp @@ -372,7 +372,7 @@ void PairILPTMD::ILP_neigh() ILP_numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -490,7 +490,7 @@ void PairILPTMD::calc_normal() vect[0][1] = x[jH2][1] - ytp; vect[0][2] = x[jH2][2] - ztp; } else { - error->one(FLERR, "The order of atoms in water molecule should be O H H !"); + error->one(FLERR, Error::NOLASTLINE, "The order of atoms in water molecule should be O H H !"); } } Nave[0] = vect[0][0]; @@ -499,7 +499,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -576,7 +576,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -652,7 +652,7 @@ void PairILPTMD::calc_normal() cont = 2; } else { - error->one(FLERR, "The order of atoms in water molecule should be O H H !"); + error->one(FLERR, Error::NOLASTLINE, "The order of atoms in water molecule should be O H H !"); } } if (cont == 2) { @@ -662,7 +662,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -717,7 +717,7 @@ void PairILPTMD::calc_normal() } } else if (cont >= 3) { - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of water molecules"); } } @@ -762,7 +762,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -867,7 +867,7 @@ void PairILPTMD::calc_normal() // the magnitude of the normal vector nn2 = Nave[0] * Nave[0] + Nave[1] * Nave[1] + Nave[2] * Nave[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -911,7 +911,7 @@ void PairILPTMD::calc_normal() } } // end of cont == 3 else - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of B/N/C/H atoms"); } // for B/N/C/H } // end of if(contone(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0.0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = Nave[0] / nn; normal[i][1] = Nave[1] / nn; @@ -1008,7 +1008,7 @@ void PairILPTMD::calc_normal() } } } else { - error->one(FLERR, "There are too many neighbors for calculating normals of TMD atoms"); + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of TMD atoms"); } // end of four cases of cont } // end of i loop } diff --git a/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp b/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp index be6cefa62a..0bfd28fa34 100644 --- a/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp +++ b/src/INTERLAYER/pair_kolmogorov_crespi_full.cpp @@ -673,11 +673,11 @@ void PairKolmogorovCrespiFull::KC_neigh() KC_firstneigh[i] = neighptr; KC_numneigh[i] = n; if (n > 3) - error->one(FLERR, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -815,7 +815,7 @@ void PairKolmogorovCrespiFull::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -955,7 +955,7 @@ void PairKolmogorovCrespiFull::calc_normal() // the magnitude of the normal vector nn2 = n1[0] * n1[0] + n1[1] * n1[1] + n1[2] * n1[2]; nn = sqrt(nn2); - if (nn == 0) error->one(FLERR, "The magnitude of the normal vector is zero"); + if (nn == 0) error->one(FLERR, Error::NOLASTLINE, "The magnitude of the normal vector is zero"); // the unit normal vector normal[i][0] = n1[0] / nn; normal[i][1] = n1[1] / nn; @@ -992,7 +992,7 @@ void PairKolmogorovCrespiFull::calc_normal() } } } else { - error->one(FLERR, "There are too many neighbors for calculating normals"); + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals"); } //############################################################################################## diff --git a/src/KOKKOS/npair_copy_kokkos.cpp b/src/KOKKOS/npair_copy_kokkos.cpp index 6485319883..29687f8221 100644 --- a/src/KOKKOS/npair_copy_kokkos.cpp +++ b/src/KOKKOS/npair_copy_kokkos.cpp @@ -116,7 +116,7 @@ void NPairCopyKokkos::copy_to_cpu(NeighList *list) firstneigh[i] = neighptr; ipage->vgot(jnum); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/KOKKOS/npair_trim_kokkos.cpp b/src/KOKKOS/npair_trim_kokkos.cpp index d04d8676d7..578e62c2c5 100644 --- a/src/KOKKOS/npair_trim_kokkos.cpp +++ b/src/KOKKOS/npair_trim_kokkos.cpp @@ -184,7 +184,7 @@ void NPairTrimKokkos::trim_to_cpu(NeighList *list) numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_airebo.cpp b/src/MANYBODY/pair_airebo.cpp index 705fa34f8b..150eeef9f6 100644 --- a/src/MANYBODY/pair_airebo.cpp +++ b/src/MANYBODY/pair_airebo.cpp @@ -406,7 +406,7 @@ void PairAIREBO::REBO_neigh() REBO_numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_comb.cpp b/src/MANYBODY/pair_comb.cpp index f3cd29b43d..553e912064 100644 --- a/src/MANYBODY/pair_comb.cpp +++ b/src/MANYBODY/pair_comb.cpp @@ -2015,7 +2015,7 @@ void PairComb::Short_neigh() sht_num[i] = nj; ipage->vgot(nj); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_comb3.cpp b/src/MANYBODY/pair_comb3.cpp index bc74bf6361..b657c74c4b 100644 --- a/src/MANYBODY/pair_comb3.cpp +++ b/src/MANYBODY/pair_comb3.cpp @@ -772,7 +772,7 @@ void PairComb3::Short_neigh() sht_num[i] = nj; ipage->vgot(nj); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } // communicating coordination number to all nodes diff --git a/src/MANYBODY/pair_extep.cpp b/src/MANYBODY/pair_extep.cpp index 6915ee81cb..623dc510c4 100644 --- a/src/MANYBODY/pair_extep.cpp +++ b/src/MANYBODY/pair_extep.cpp @@ -165,7 +165,7 @@ void PairExTeP::SR_neigh() ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/MANYBODY/pair_lcbop.cpp b/src/MANYBODY/pair_lcbop.cpp index 3e8020c3af..3325918b82 100644 --- a/src/MANYBODY/pair_lcbop.cpp +++ b/src/MANYBODY/pair_lcbop.cpp @@ -278,7 +278,7 @@ void PairLCBOP::SR_neigh() SR_numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } // calculate M_i diff --git a/src/MANYBODY/pair_rebomos.cpp b/src/MANYBODY/pair_rebomos.cpp index d912c37290..f76cdc4e49 100644 --- a/src/MANYBODY/pair_rebomos.cpp +++ b/src/MANYBODY/pair_rebomos.cpp @@ -349,7 +349,7 @@ void PairREBOMoS::REBO_neigh() REBO_numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/OPENMP/fix_neigh_history_omp.cpp b/src/OPENMP/fix_neigh_history_omp.cpp index 224bfc6bdc..34ba1deb8b 100644 --- a/src/OPENMP/fix_neigh_history_omp.cpp +++ b/src/OPENMP/fix_neigh_history_omp.cpp @@ -137,7 +137,7 @@ void FixNeighHistoryOMP::pre_exchange_onesided() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -274,7 +274,7 @@ void FixNeighHistoryOMP::pre_exchange_newton() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -287,7 +287,7 @@ void FixNeighHistoryOMP::pre_exchange_newton() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) { - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } } @@ -440,7 +440,7 @@ void FixNeighHistoryOMP::pre_exchange_no_newton() partner[i] = ipg.get(n); valuepartner[i] = dpg.get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } diff --git a/src/OPENMP/npair_bin_ghost_omp.cpp b/src/OPENMP/npair_bin_ghost_omp.cpp index f33bd821f7..7d5ae62352 100644 --- a/src/OPENMP/npair_bin_ghost_omp.cpp +++ b/src/OPENMP/npair_bin_ghost_omp.cpp @@ -185,7 +185,7 @@ void NPairBinGhostOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_bin_omp.cpp b/src/OPENMP/npair_bin_omp.cpp index 21bb887177..47f9992de0 100644 --- a/src/OPENMP/npair_bin_omp.cpp +++ b/src/OPENMP/npair_bin_omp.cpp @@ -252,7 +252,7 @@ void NPairBinOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_halffull_omp.cpp b/src/OPENMP/npair_halffull_omp.cpp index bc646accbc..4a18623932 100644 --- a/src/OPENMP/npair_halffull_omp.cpp +++ b/src/OPENMP/npair_halffull_omp.cpp @@ -149,7 +149,7 @@ void NPairHalffullOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = inum_full; diff --git a/src/OPENMP/npair_multi_old_omp.cpp b/src/OPENMP/npair_multi_old_omp.cpp index d07240cf9b..9731887260 100644 --- a/src/OPENMP/npair_multi_old_omp.cpp +++ b/src/OPENMP/npair_multi_old_omp.cpp @@ -245,7 +245,7 @@ void NPairMultiOldOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_multi_omp.cpp b/src/OPENMP/npair_multi_omp.cpp index c85726f4fb..a3f36f60e0 100644 --- a/src/OPENMP/npair_multi_omp.cpp +++ b/src/OPENMP/npair_multi_omp.cpp @@ -279,7 +279,7 @@ void NPairMultiOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_nsq_ghost_omp.cpp b/src/OPENMP/npair_nsq_ghost_omp.cpp index 59fa8ed6f5..5cb7d49233 100644 --- a/src/OPENMP/npair_nsq_ghost_omp.cpp +++ b/src/OPENMP/npair_nsq_ghost_omp.cpp @@ -172,7 +172,7 @@ void NPairNsqGhostOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_nsq_omp.cpp b/src/OPENMP/npair_nsq_omp.cpp index 1a7058791c..3319c2ef2a 100644 --- a/src/OPENMP/npair_nsq_omp.cpp +++ b/src/OPENMP/npair_nsq_omp.cpp @@ -221,7 +221,7 @@ void NPairNsqOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = nlocal; diff --git a/src/OPENMP/npair_respa_bin_omp.cpp b/src/OPENMP/npair_respa_bin_omp.cpp index 691d807498..ca15ebf6b0 100644 --- a/src/OPENMP/npair_respa_bin_omp.cpp +++ b/src/OPENMP/npair_respa_bin_omp.cpp @@ -244,20 +244,20 @@ void NPairRespaBinOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[i] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage.vgot(n_inner); - if (ipage_inner.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[i] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } NPAIR_OMP_CLOSE; diff --git a/src/OPENMP/npair_respa_nsq_omp.cpp b/src/OPENMP/npair_respa_nsq_omp.cpp index 8483872ca0..862f70f2b3 100644 --- a/src/OPENMP/npair_respa_nsq_omp.cpp +++ b/src/OPENMP/npair_respa_nsq_omp.cpp @@ -224,20 +224,20 @@ void NPairRespaNsqOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[i] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage.vgot(n_inner); - if (ipage_inner.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[i] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } NPAIR_OMP_CLOSE; diff --git a/src/OPENMP/npair_trim_omp.cpp b/src/OPENMP/npair_trim_omp.cpp index 0840c1a5f2..a69eb827c6 100644 --- a/src/OPENMP/npair_trim_omp.cpp +++ b/src/OPENMP/npair_trim_omp.cpp @@ -98,7 +98,7 @@ void NPairTrimOmp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage.vgot(n); - if (ipage.status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage.status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } NPAIR_OMP_CLOSE; list->inum = inum_copy; diff --git a/src/OPENMP/pair_airebo_omp.cpp b/src/OPENMP/pair_airebo_omp.cpp index 0effe79bc8..d1e283d278 100644 --- a/src/OPENMP/pair_airebo_omp.cpp +++ b/src/OPENMP/pair_airebo_omp.cpp @@ -174,7 +174,7 @@ void PairAIREBOOMP::REBO_neigh_thr() REBO_numneigh[i] = n; ipg.vgot(n); if (ipg.status()) - error->one(FLERR,"REBO list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "REBO list overflow, boost neigh_modify one" + utils::errorurl(36)); } } } diff --git a/src/OPENMP/pair_comb_omp.cpp b/src/OPENMP/pair_comb_omp.cpp index 87d467a846..705003379b 100644 --- a/src/OPENMP/pair_comb_omp.cpp +++ b/src/OPENMP/pair_comb_omp.cpp @@ -629,7 +629,7 @@ void PairCombOMP::Short_neigh_thr() sht_num[i] = nj; ipg.vgot(nj); if (ipg.status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } } diff --git a/src/OPENMP/pair_rebomos_omp.cpp b/src/OPENMP/pair_rebomos_omp.cpp index 06b979d41a..00dadde13e 100644 --- a/src/OPENMP/pair_rebomos_omp.cpp +++ b/src/OPENMP/pair_rebomos_omp.cpp @@ -186,7 +186,7 @@ void PairREBOMoSOMP::REBO_neigh_thr() REBO_numneigh[i] = n; ipg.vgot(n); if (ipg.status()) - error->one(FLERR,"REBO list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "REBO list overflow, boost neigh_modify one" + utils::errorurl(36)); } } } diff --git a/src/fix_neigh_history.cpp b/src/fix_neigh_history.cpp index cdf8fb0527..911dee2984 100644 --- a/src/fix_neigh_history.cpp +++ b/src/fix_neigh_history.cpp @@ -286,7 +286,7 @@ void FixNeighHistory::pre_exchange_onesided() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } // 2nd loop over neighbor list, I = sphere, J = tri @@ -394,7 +394,7 @@ void FixNeighHistory::pre_exchange_newton() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) { - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -403,7 +403,7 @@ void FixNeighHistory::pre_exchange_newton() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) { - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } } @@ -519,7 +519,7 @@ void FixNeighHistory::pre_exchange_no_newton() partner[i] = ipage_atom->get(n); valuepartner[i] = dpage_atom->get(dnum * n); if (partner[i] == nullptr || valuepartner[i] == nullptr) - error->one(FLERR, "Neighbor history overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor history overflow, boost neigh_modify one" + utils::errorurl(36)); } // 2nd loop over neighbor list diff --git a/src/npair_bin.cpp b/src/npair_bin.cpp index 3ed567a008..9c3cbe8e91 100644 --- a/src/npair_bin.cpp +++ b/src/npair_bin.cpp @@ -245,7 +245,7 @@ void NPairBin::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; diff --git a/src/npair_bin_ghost.cpp b/src/npair_bin_ghost.cpp index 5efe7898bb..9f0631ef2a 100644 --- a/src/npair_bin_ghost.cpp +++ b/src/npair_bin_ghost.cpp @@ -179,7 +179,7 @@ void NPairBinGhost::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = atom->nlocal; diff --git a/src/npair_halffull.cpp b/src/npair_halffull.cpp index 7a815a5137..7773ff5a58 100644 --- a/src/npair_halffull.cpp +++ b/src/npair_halffull.cpp @@ -150,7 +150,7 @@ void NPairHalffull::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; if (!NEWTON) diff --git a/src/npair_multi.cpp b/src/npair_multi.cpp index f41088d324..7893626876 100644 --- a/src/npair_multi.cpp +++ b/src/npair_multi.cpp @@ -276,7 +276,7 @@ void NPairMulti::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; diff --git a/src/npair_multi_old.cpp b/src/npair_multi_old.cpp index 8d2bb71f10..cbcc565414 100644 --- a/src/npair_multi_old.cpp +++ b/src/npair_multi_old.cpp @@ -238,7 +238,7 @@ void NPairMultiOld::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; diff --git a/src/npair_nsq.cpp b/src/npair_nsq.cpp index ec64e7d2a3..be6a3d84ad 100644 --- a/src/npair_nsq.cpp +++ b/src/npair_nsq.cpp @@ -213,7 +213,7 @@ void NPairNsq::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; diff --git a/src/npair_nsq_ghost.cpp b/src/npair_nsq_ghost.cpp index 2f9c5123b7..52d0ebdd5b 100644 --- a/src/npair_nsq_ghost.cpp +++ b/src/npair_nsq_ghost.cpp @@ -166,7 +166,7 @@ void NPairNsqGhost::build(NeighList *list) numneigh[i] = n; ipage->vgot(n); if (ipage->status()) - error->one(FLERR,"Neighbor list overflow, boost neigh_modify one"); + error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = atom->nlocal; diff --git a/src/npair_respa_bin.cpp b/src/npair_respa_bin.cpp index 6a6c52de87..eba11b8699 100644 --- a/src/npair_respa_bin.cpp +++ b/src/npair_respa_bin.cpp @@ -232,20 +232,20 @@ void NPairRespaBin::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); - if (ipage_inner->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } inum++; diff --git a/src/npair_respa_nsq.cpp b/src/npair_respa_nsq.cpp index 43bf0d649c..c660b7002f 100644 --- a/src/npair_respa_nsq.cpp +++ b/src/npair_respa_nsq.cpp @@ -217,20 +217,20 @@ void NPairRespaNsq::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n_inner); - if (ipage_inner->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n_middle); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } inum++; diff --git a/src/npair_skip.cpp b/src/npair_skip.cpp index ab23a4fe5f..5cb8affc9b 100644 --- a/src/npair_skip.cpp +++ b/src/npair_skip.cpp @@ -116,7 +116,7 @@ void NPairSkipTemp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; diff --git a/src/npair_skip_respa.cpp b/src/npair_skip_respa.cpp index 90566e8786..196af58216 100644 --- a/src/npair_skip_respa.cpp +++ b/src/npair_skip_respa.cpp @@ -193,20 +193,20 @@ void NPairSkipRespaTemp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); ilist_inner[inum] = i; firstneigh_inner[i] = neighptr_inner; numneigh_inner[i] = n_inner; ipage_inner->vgot(n); - if (ipage_inner->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_inner->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); if (respamiddle) { ilist_middle[inum] = i; firstneigh_middle[i] = neighptr_middle; numneigh_middle[i] = n_middle; ipage_middle->vgot(n); - if (ipage_middle->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage_middle->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } inum++; diff --git a/src/npair_skip_size_off2on.cpp b/src/npair_skip_size_off2on.cpp index 46bc90a1ed..c4c00534fd 100644 --- a/src/npair_skip_size_off2on.cpp +++ b/src/npair_skip_size_off2on.cpp @@ -112,7 +112,7 @@ void NPairSkipSizeOff2onTemp::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } list->inum = inum; } diff --git a/src/npair_skip_size_off2on_oneside.cpp b/src/npair_skip_size_off2on_oneside.cpp index 20a2f11cd1..739ef41475 100644 --- a/src/npair_skip_size_off2on_oneside.cpp +++ b/src/npair_skip_size_off2on_oneside.cpp @@ -128,7 +128,7 @@ void NPairSkipSizeOff2onOnesideTemp::build(NeighList *list) for (i = 0; i < nlocal; i++) { if (numneigh[i] == 0) continue; firstneigh[i] = ipage->get(numneigh[i]); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } // second loop over atoms in other list to store neighbors diff --git a/src/npair_trim.cpp b/src/npair_trim.cpp index c89445cea0..b48c200f16 100644 --- a/src/npair_trim.cpp +++ b/src/npair_trim.cpp @@ -95,6 +95,6 @@ void NPairTrim::build(NeighList *list) firstneigh[i] = neighptr; numneigh[i] = n; ipage->vgot(n); - if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one"); + if (ipage->status()) error->one(FLERR, Error::NOLASTLINE, "Neighbor list overflow, boost neigh_modify one" + utils::errorurl(36)); } } From d1f452fcb63b56293bde27e91dc3b8acceea6966 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Apr 2025 17:40:56 -0400 Subject: [PATCH 109/396] fix whitespace issues --- doc/src/Errors_details.rst | 6 ++++-- src/INTERLAYER/pair_ilp_graphene_hbn.cpp | 2 +- src/INTERLAYER/pair_ilp_tmd.cpp | 4 ++-- src/INTERLAYER/pair_kolmogorov_crespi_full.cpp | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/src/Errors_details.rst b/doc/src/Errors_details.rst index 442bceebf5..8e12b52114 100644 --- a/doc/src/Errors_details.rst +++ b/doc/src/Errors_details.rst @@ -1018,13 +1018,15 @@ list storage is typically the largest amount of RAM required by a LAMMPS calculation. Even though the LAMMPS error message recommends to increase the "one" -parameter, this may not be the correct solution since the neighbor list +parameter, this may not be the correct solution. The neighbor list overflow can be a symptom of some other error that cannot be easily detected. For example, a frequent reason for an (unexpected) high density are incorrect box boundaries or coordinates provided as fractional coordinates. In both cases, LAMMPS cannot easily know whether the input geometry has such a high density (and thus requiring -more neighbor list storage) intentionally. +more neighbor list storage) intentionally. Rather than blindly +increasing the "one" parameter, it is worth checking if this is +justified by the combination of density and cutoff. When boosting (= increasing) the "one" parameter, it is recommended to also increase the value for the "page" parameter to maintain the ratio diff --git a/src/INTERLAYER/pair_ilp_graphene_hbn.cpp b/src/INTERLAYER/pair_ilp_graphene_hbn.cpp index af3b9ce36a..fe7b4990b4 100644 --- a/src/INTERLAYER/pair_ilp_graphene_hbn.cpp +++ b/src/INTERLAYER/pair_ilp_graphene_hbn.cpp @@ -692,7 +692,7 @@ void PairILPGrapheneHBN::ILP_neigh() ILP_firstneigh[i] = neighptr; ILP_numneigh[i] = n; if (n > 3) - error->one(FLERR, Error::NOLASTLINE, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); diff --git a/src/INTERLAYER/pair_ilp_tmd.cpp b/src/INTERLAYER/pair_ilp_tmd.cpp index 5ac2d867de..4d058e889c 100644 --- a/src/INTERLAYER/pair_ilp_tmd.cpp +++ b/src/INTERLAYER/pair_ilp_tmd.cpp @@ -717,7 +717,7 @@ void PairILPTMD::calc_normal() } } else if (cont >= 3) { - error->one(FLERR, Error::NOLASTLINE, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of water molecules"); } } @@ -911,7 +911,7 @@ void PairILPTMD::calc_normal() } } // end of cont == 3 else - error->one(FLERR, Error::NOLASTLINE, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for calculating normals of B/N/C/H atoms"); } // for B/N/C/H } // end of if(cont 3) - error->one(FLERR, Error::NOLASTLINE, + error->one(FLERR, Error::NOLASTLINE, "There are too many neighbors for some atoms, please check your configuration"); ipage->vgot(n); From 2f861b83d774fb79780819153eb98b5df9e6cba6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 00:01:40 -0400 Subject: [PATCH 110/396] correct embedded documentation --- src/lmptype.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lmptype.h b/src/lmptype.h index 8927de429c..5796d4d18c 100644 --- a/src/lmptype.h +++ b/src/lmptype.h @@ -234,13 +234,13 @@ union ubuf { std::string str; for (int i = 0; i < 5; ++i) { switch (m[i].type) { - case multitype::DOUBLE: + case multitype::LAMMPS_DOUBLE: str += std::to_string(m[i].data.d) + ' '; break; - case multitype::INT: + case multitype::LAMMPS_INT: str += std::to_string(m[i].data.i) + ' '; break; - case multitype::BIGINT: + case multitype::LAMMPS_INT64: str += std::to_string(m[i].data.b) + ' '; break; default: From 32592e666037c438a91235aa20538819de7460e3 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 01:13:44 -0400 Subject: [PATCH 111/396] add feature idea for LAMMPS-GUI --- tools/lammps-gui/TODO.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index 996ab43a93..a917a4cf62 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -2,6 +2,8 @@ LAMMPS-GUI TODO list: # Short term goals (v1.x) +- add feature to visualize "molecules" from the molecule command. + this could use the image viewer, but create an empty system and then just one molecule - implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences. - add a "Filter data" checkbox to the "Charts" window to select whether data should be dropped. - add a "Charts tab" to the preferences with the following (default) settings: From 227b4ed12d4a282ea7954f0b440ae196e3c953ab Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 04:39:56 -0400 Subject: [PATCH 112/396] remove unused class members and plug memory leaks --- src/create_atoms.cpp | 14 ++++++++++++++ src/create_atoms.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 7be67f4c49..5310d5f49c 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -66,6 +66,20 @@ enum { BISECTION, QUASIRANDOM }; static constexpr const char *mesh_name[] = {"recursive bisection", "quasi-random"}; /* ---------------------------------------------------------------------- */ +CreateAtoms::~CreateAtoms() +{ + delete[] basistype; + memory->destroy(xmol); + + delete[] vstr; + delete[] xstr; + delete[] ystr; + delete[] zstr; + delete[] groupname; + + delete ranmol; + delete ranlat; +} CreateAtoms::CreateAtoms(LAMMPS *lmp) : Command(lmp), basistype(nullptr) {} /* ---------------------------------------------------------------------- */ diff --git a/src/create_atoms.h b/src/create_atoms.h index f839e3f0df..ca2a8779a9 100644 --- a/src/create_atoms.h +++ b/src/create_atoms.h @@ -27,6 +27,7 @@ namespace LAMMPS_NS { class CreateAtoms : public Command { public: CreateAtoms(class LAMMPS *); + ~CreateAtoms() override; void command(int, char **) override; private: @@ -45,7 +46,6 @@ class CreateAtoms : public Command { int varflag, vvar, xvar, yvar, zvar; char *vstr, *xstr, *ystr, *zstr; - char *xstr_copy, *ystr_copy, *zstr_copy; int ilo, ihi, jlo, jhi, klo, khi; From 980bf703103806dded06e8b63463d63ac0d671cd Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 05:00:41 -0400 Subject: [PATCH 113/396] improve error messages --- src/create_atoms.cpp | 141 +++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 58 deletions(-) diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 5310d5f49c..bac3a556eb 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -78,7 +78,7 @@ CreateAtoms::~CreateAtoms() delete[] groupname; delete ranmol; - delete ranlat; + delete ranlatt; } CreateAtoms::CreateAtoms(LAMMPS *lmp) : Command(lmp), basistype(nullptr) {} @@ -87,9 +87,11 @@ CreateAtoms::CreateAtoms(LAMMPS *lmp) : Command(lmp), basistype(nullptr) {} void CreateAtoms::command(int narg, char **arg) { if (domain->box_exist == 0) - error->all(FLERR, "Create_atoms command before simulation box is defined" + utils::errorurl(33)); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms command before simulation box is defined" + utils::errorurl(33)); if (modify->nfix_restart_peratom) - error->all(FLERR, "Cannot create_atoms after reading restart file with per-atom info"); + error->all(FLERR, Error::NOLASTLINE, + "Cannot create_atoms after reading restart file with per-atom info"); // check for compatible lattice @@ -97,10 +99,10 @@ void CreateAtoms::command(int narg, char **arg) if (domain->dimension == 2) { if (latsty == Lattice::SC || latsty == Lattice::BCC || latsty == Lattice::FCC || latsty == Lattice::HCP || latsty == Lattice::DIAMOND) - error->all(FLERR, "Lattice style incompatible with simulation dimension"); + error->all(FLERR, Error::NOLASTLINE, "Lattice style incompatible with simulation dimension"); } else { if (latsty == Lattice::SQ || latsty == Lattice::SQ2 || latsty == Lattice::HEX) - error->all(FLERR, "Lattice style incompatible with simulation dimension"); + error->all(FLERR, Error::NOLASTLINE, "Lattice style incompatible with simulation dimension"); } // parse arguments @@ -129,15 +131,16 @@ void CreateAtoms::command(int narg, char **arg) xone[1] = utils::numeric(FLERR, arg[3], false, lmp); xone[2] = utils::numeric(FLERR, arg[4], false, lmp); if (domain->dimension == 2 && xone[2] != 0.0) - error->all(FLERR, "Create_atoms single for 2d simulation requires z coord = 0.0"); + error->all(FLERR, 4, "Create_atoms single for 2d simulation requires z coord = 0.0"); iarg = 5; } else if (strcmp(arg[1], "random") == 0) { style = RANDOM; if (narg < 5) utils::missing_cmd_args(FLERR, "create_atoms random", error); nrandom = utils::inumeric(FLERR, arg[2], false, lmp); - if (nrandom < 0) error->all(FLERR, "Illegal create_atoms number of random atoms {}", nrandom); + if (nrandom < 0) + error->all(FLERR, 2, "Illegal create_atoms number of random atoms {}", nrandom); seed = utils::inumeric(FLERR, arg[3], false, lmp); - if (seed <= 0) error->all(FLERR, "Illegal create_atoms random seed {}", seed); + if (seed <= 0) error->all(FLERR, 3, "Illegal create_atoms random seed {}", seed); if (strcmp(arg[4], "NULL") == 0) region = nullptr; else { @@ -185,8 +188,8 @@ void CreateAtoms::command(int narg, char **arg) int ibasis = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); int itype = utils::expand_type_int(FLERR, arg[iarg + 2], Atom::ATOM, lmp); if (ibasis <= 0 || ibasis > nbasis || itype <= 0 || itype > atom->ntypes) - error->all(FLERR, "Out of range basis setting '{} {}' in create_atoms command", ibasis, - itype); + error->all(FLERR, iarg + 1, "Out of range basis setting '{} {}' in create_atoms command", + ibasis, itype); basistype[ibasis - 1] = itype; iarg += 3; } else if (strcmp(arg[iarg], "remap") == 0) { @@ -197,7 +200,8 @@ void CreateAtoms::command(int narg, char **arg) if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "create_atoms mol", error); int imol = atom->find_molecule(arg[iarg + 1]); if (imol == -1) - error->all(FLERR, "Molecule template ID {} for create_atoms does not exist", arg[iarg + 1]); + error->all(FLERR, iarg + 1, "Molecule template ID {} for create_atoms does not exist", + arg[iarg + 1]); if ((atom->molecules[imol]->nset > 1) && (comm->me == 0)) error->warning(FLERR, "Molecule template for create_atoms has multiple molecule sets. " @@ -213,11 +217,11 @@ void CreateAtoms::command(int narg, char **arg) else if (strcmp(arg[iarg + 1], "lattice") == 0) scaleflag = 1; else - error->all(FLERR, "Unknown create_atoms units option {}", arg[iarg + 1]); + error->all(FLERR, iarg + 1, "Unknown create_atoms units option {}", arg[iarg + 1]); iarg += 2; } else if (strcmp(arg[iarg], "var") == 0) { if (style == SINGLE) - error->all(FLERR, "Cannot use 'var' keyword with 'single' style for create_atoms"); + error->all(FLERR, iarg, "Cannot use 'var' keyword with 'single' style for create_atoms"); if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms var", error); delete[] vstr; vstr = utils::strdup(arg[iarg + 1]); @@ -235,7 +239,7 @@ void CreateAtoms::command(int narg, char **arg) delete[] zstr; zstr = utils::strdup(arg[iarg + 2]); } else - error->all(FLERR, "Unknown create_atoms set option {}", arg[iarg + 2]); + error->all(FLERR, iarg + 2, "Unknown create_atoms set option {}", arg[iarg + 2]); iarg += 3; } else if (strcmp(arg[iarg], "rotate") == 0) { if (iarg + 5 > narg) utils::missing_cmd_args(FLERR, "create_atoms rotate", error); @@ -247,9 +251,9 @@ void CreateAtoms::command(int narg, char **arg) axisone[1] = utils::numeric(FLERR, arg[iarg + 3], false, lmp); axisone[2] = utils::numeric(FLERR, arg[iarg + 4], false, lmp); if (axisone[0] == 0.0 && axisone[1] == 0.0 && axisone[2] == 0.0) - error->all(FLERR, "Illegal create_atoms rotate arguments"); + error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms rotate arguments"); if (domain->dimension == 2 && (axisone[0] != 0.0 || axisone[1] != 0.0)) - error->all(FLERR, "Invalid create_atoms rotation vector for 2d model"); + error->all(FLERR, Error::NOPOINTER, "Invalid create_atoms rotation vector for 2d model"); MathExtra::norm3(axisone); MathExtra::axisangle_to_quat(axisone, thetaone, quatone); iarg += 5; @@ -259,7 +263,7 @@ void CreateAtoms::command(int narg, char **arg) subsetfrac = utils::numeric(FLERR, arg[iarg + 1], false, lmp); subsetseed = utils::inumeric(FLERR, arg[iarg + 2], false, lmp); if (subsetfrac <= 0.0 || subsetfrac > 1.0 || subsetseed <= 0) - error->all(FLERR, "Illegal create_atoms ratio settings"); + error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms ratio settings"); iarg += 3; } else if (strcmp(arg[iarg], "subset") == 0) { if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "create_atoms subset", error); @@ -267,26 +271,27 @@ void CreateAtoms::command(int narg, char **arg) nsubset = utils::bnumeric(FLERR, arg[iarg + 1], false, lmp); subsetseed = utils::inumeric(FLERR, arg[iarg + 2], false, lmp); if ((nsubset <= 0) || (subsetseed <= 0)) - error->all(FLERR, "Illegal create_atoms subset settings"); + error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms subset settings"); iarg += 3; } else if (strcmp(arg[iarg], "overlap") == 0) { if (style != RANDOM) - error->all(FLERR, "Create_atoms overlap can only be used with random style"); - if (iarg + 2 > narg) error->all(FLERR, "Illegal create_atoms command"); + error->all(FLERR, iarg, "Create_atoms overlap can only be used with random style"); + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms overlap", error); overlap = utils::numeric(FLERR, arg[iarg + 1], false, lmp); - if (overlap <= 0) error->all(FLERR, "Illegal create_atoms overlap value: {}", overlap); + if (overlap <= 0) + error->all(FLERR, iarg + 1, "Illegal create_atoms overlap value: {}", overlap); overlapflag = 1; iarg += 2; } else if (strcmp(arg[iarg], "maxtry") == 0) { if (style != RANDOM) - error->all(FLERR, "Create_atoms maxtry can only be used with random style"); - if (iarg + 2 > narg) error->all(FLERR, "Illegal create_atoms command"); + error->all(FLERR, iarg, "Create_atoms maxtry can only be used with random style"); + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms maxtry", error); maxtry = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); - if (maxtry <= 0) error->all(FLERR, "Illegal create_atoms command"); + if (maxtry <= 0) error->all(FLERR, iarg + 1, "Illegal create_atoms maxtry value {}", maxtry); iarg += 2; } else if (strcmp(arg[iarg], "meshmode") == 0) { if (style != MESH) - error->all(FLERR, "Create_atoms meshmode can only be used with mesh style"); + error->all(FLERR, iarg, "Create_atoms meshmode can only be used with mesh style"); if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "create_atoms meshmode", error); if (strcmp(arg[iarg + 1], "bisect") == 0) { mesh_style = BISECTION; @@ -295,16 +300,17 @@ void CreateAtoms::command(int narg, char **arg) mesh_style = QUASIRANDOM; mesh_density = utils::numeric(FLERR, arg[iarg + 2], false, lmp); } else - error->all(FLERR, "Unknown create_atoms meshmode {}", arg[iarg + 2]); + error->all(FLERR, iarg + 2, "Unknown create_atoms meshmode {}", arg[iarg + 2]); iarg += 3; } else if (strcmp(arg[iarg], "radscale") == 0) { if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms radscale", error); if (style != MESH) - error->all(FLERR, "Create_atoms radscale can only be used with mesh style"); + error->all(FLERR, iarg, "Create_atoms radscale can only be used with mesh style"); if (!atom->radius_flag) - error->all(FLERR, "Must have atom attribute radius to set radscale factor"); + error->all(FLERR, iarg, "Must have atom attribute radius to set radscale factor"); radscale = utils::numeric(FLERR, arg[iarg + 1], false, lmp); - if (radscale <= 0.0) error->all(FLERR, "Illegal create_atoms radscale value: {}", radscale); + if (radscale <= 0.0) + error->all(FLERR, iarg + 1, "Illegal create_atoms radscale value: {}", radscale); iarg += 2; } else error->all(FLERR, "Illegal create_atoms command option {}", arg[iarg]); @@ -314,16 +320,20 @@ void CreateAtoms::command(int narg, char **arg) if (mode == ATOM) { if ((ntype <= 0) || (ntype > atom->ntypes)) - error->all(FLERR, "Invalid atom type in create_atoms command"); + error->all(FLERR, Error::NOLASTLINE, "Invalid atom type in create_atoms command"); } else if (mode == MOLECULE) { - if (onemol->xflag == 0) error->all(FLERR, "Create_atoms molecule must have coordinates"); - if (onemol->typeflag == 0) error->all(FLERR, "Create_atoms molecule must have atom types"); + if (onemol->xflag == 0) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms molecule must have coordinates"); + if (onemol->typeflag == 0) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms molecule must have atom types"); if (ntype + onemol->ntypes <= 0 || ntype + onemol->ntypes > atom->ntypes) - error->all(FLERR, "Invalid atom type in create_atoms mol command"); + error->all(FLERR, Error::NOLASTLINE, "Invalid atom type in create_atoms mol command"); if (onemol->tag_require && !atom->tag_enable) - error->all(FLERR, "Create_atoms molecule has atom IDs, but system does not"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms molecule has atom IDs, but system does not"); if (atom->molecular == Atom::TEMPLATE && onemol != atom->avec->onemols[0]) - error->all(FLERR, "Create_atoms molecule template ID must be same as atom style template ID"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms molecule template ID must be same as atom style template ID"); onemol->check_attributes(); @@ -337,8 +347,10 @@ void CreateAtoms::command(int narg, char **arg) if (style == MESH) { if (mode == MOLECULE) - error->all(FLERR, "Create_atoms mesh is not compatible with the 'mol' option"); - if (scaleflag) error->all(FLERR, "Create_atoms mesh must use 'units box' option"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms mesh is not compatible with the 'mol' option"); + if (scaleflag) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms mesh must use 'units box' option"); } ranlatt = nullptr; @@ -347,40 +359,44 @@ void CreateAtoms::command(int narg, char **arg) // error check and further setup for variable test if (!vstr && (xstr || ystr || zstr)) - error->all(FLERR, "Incomplete use of variables in create_atoms command"); + error->all(FLERR, Error::NOLASTLINE, "Incomplete use of variables in create_atoms command"); if (vstr && (!xstr && !ystr && !zstr)) - error->all(FLERR, "Incomplete use of variables in create_atoms command"); + error->all(FLERR, Error::NOLASTLINE, "Incomplete use of variables in create_atoms command"); if (varflag) { vvar = input->variable->find(vstr); if (vvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", vstr); if (!input->variable->equalstyle(vvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", vstr); if (xstr) { xvar = input->variable->find(xstr); - if (xvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", xstr); + if (xvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", xstr); if (!input->variable->internalstyle(xvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", xstr); } if (ystr) { yvar = input->variable->find(ystr); - if (yvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", ystr); + if (yvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", ystr); if (!input->variable->internalstyle(yvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", ystr); } if (zstr) { zvar = input->variable->find(zstr); - if (zvar < 0) error->all(FLERR, "Variable {} for create_atoms does not exist", zstr); + if (zvar < 0) + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", zstr); if (!input->variable->internalstyle(zvar)) - error->all(FLERR, "Variable for create_atoms is invalid style"); + error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", zstr); } } // require non-none lattice be defined for BOX or REGION styles if ((style == BOX) || (style == REGION)) { - if (nbasis == 0) error->all(FLERR, "Cannot create atoms with undefined lattice"); + if (nbasis == 0) + error->all(FLERR, Error::NOLASTLINE, "Cannot create atoms with undefined lattice"); } // apply scaling factor for styles that use distance-dependent factors @@ -506,7 +522,8 @@ void CreateAtoms::command(int narg, char **arg) bigint nblocal = atom->nlocal; MPI_Allreduce(&nblocal, &atom->natoms, 1, MPI_LMP_BIGINT, MPI_SUM, world); - if (atom->natoms < 0 || atom->natoms >= MAXBIGINT) error->all(FLERR, "Too many total atoms"); + if ((atom->natoms < 0) || (atom->natoms >= MAXBIGINT)) + error->all(FLERR, Error::NOLASTLINE, "Too many total atoms"); // add IDs for newly created atoms // check that atom IDs are valid @@ -792,7 +809,7 @@ void CreateAtoms::add_random() } if (xlo > xhi || ylo > yhi || zlo > zhi) - error->all(FLERR, "No overlap of box and region for create_atoms"); + error->all(FLERR, Error::NOLASTLINE, "No overlap of box and region for create_atoms"); // insert Nrandom new atom/molecule into simulation box @@ -1099,7 +1116,8 @@ void CreateAtoms::add_mesh(const char *filename) SafeFilePtr fp = fopen(filename, "rb"); if (fp == nullptr) - error->one(FLERR, "Cannot open STL mesh file {}: {}", filename, utils::getsyserror()); + error->one(FLERR, Error::NOLASTLINE, "Cannot open STL mesh file {}: {}", filename, + utils::getsyserror()); // first try reading the file in ASCII format @@ -1173,7 +1191,8 @@ void CreateAtoms::add_mesh(const char *filename) title[79] = '\0'; count = fread(&ntri, sizeof(ntri), 1, fp); if (count <= 0) { - error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror()); + error->all(FLERR, Error::NOLASTLINE, "Error reading STL file {}: {}", filename, + utils::getsyserror()); } else { if (comm->me == 0) utils::logmesg(lmp, "Reading STL object {} from binary file {}\n", utils::trim(title), @@ -1183,7 +1202,8 @@ void CreateAtoms::add_mesh(const char *filename) for (uint32_t i = 0U; i < ntri; ++i) { count = fread(triangle, sizeof(float), 12, fp); if (count != 12) - error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror()); + error->all(FLERR, Error::NOLASTLINE, "Error reading STL file {}: {}", filename, + utils::getsyserror()); count = fread(&attr, sizeof(attr), 1, fp); for (int j = 0; j < 3; ++j) @@ -1200,7 +1220,8 @@ void CreateAtoms::add_mesh(const char *filename) } } } else { - error->all(FLERR, "Error reading triangles from STL mesh file {}: {}", filename, e.what()); + error->all(FLERR, Error::NOLASTLINE, "Error reading triangles from STL mesh file {}: {}", + filename, e.what()); } } @@ -1223,10 +1244,11 @@ void CreateAtoms::add_lattice() // verify lattice was defined with triclinic/general option if (!domain->triclinic_general && domain->lattice->is_general_triclinic()) - error->all(FLERR, + error->all(FLERR, Error::NOLASTLINE, "Create_atoms for non general triclinic box cannot use triclinic/general lattice"); if (domain->triclinic_general && !domain->lattice->is_general_triclinic()) - error->all(FLERR, "Create_atoms for general triclinic box requires triclinic/general lattice"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms for general triclinic box requires triclinic/general lattice"); // convert 8 corners of my subdomain from box coords to lattice coords // for orthogonal, use corner pts of my subbox @@ -1367,7 +1389,8 @@ void CreateAtoms::add_lattice() int overflow; MPI_Allreduce(&nlatt_overflow, &overflow, 1, MPI_INT, MPI_SUM, world); - if (overflow) error->all(FLERR, "Create_atoms lattice size overflow on 1 or more procs"); + if (overflow) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms lattice size overflow on 1 or more procs"); bigint nadd; @@ -1381,7 +1404,8 @@ void CreateAtoms::add_lattice() bigint bnlattall; MPI_Allreduce(&bnlatt, &bnlattall, 1, MPI_LMP_BIGINT, MPI_SUM, world); if (subsetflag == RATIO) nsubset = static_cast(subsetfrac * bnlattall); - if (nsubset > bnlattall) error->all(FLERR, "Create_atoms subset size > # of lattice sites"); + if (nsubset > bnlattall) + error->all(FLERR, Error::NOLASTLINE, "Create_atoms subset size > # of lattice sites"); if (comm->nprocs == 1) nadd = nsubset; else @@ -1452,7 +1476,8 @@ void CreateAtoms::loop_lattice(int action) domain->general_to_restricted_coords(x); if (dimension == 2) { if (fabs(x[2]) > EPS_ZCOORD) - error->all(FLERR, "Create_atoms atom z coord is non-zero for 2d simulation"); + error->all(FLERR, Error::NOLASTLINE, + "Create_atoms atom z coord is non-zero for 2d simulation"); x[2] = 0.0; } } From f2bf0d0a8b275edbc953cf6f1c440451d41582f1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 05:36:26 -0400 Subject: [PATCH 114/396] add optional create_atoms group keyword to add new atoms to a custom group --- doc/src/create_atoms.rst | 11 ++++++++-- src/create_atoms.cpp | 46 +++++++++++++++++++++++++++------------- src/create_atoms.h | 1 + 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/doc/src/create_atoms.rst b/doc/src/create_atoms.rst index 2addd89fcb..2037c15518 100644 --- a/doc/src/create_atoms.rst +++ b/doc/src/create_atoms.rst @@ -28,7 +28,7 @@ Syntax region-ID = create atoms within this region, use NULL for entire simulation box * zero or more keyword/value pairs may be appended -* keyword = *mol* or *basis* or *ratio* or *subset* or *remap* or *var* or *set* or *radscale* or *meshmode* or *rotate* or *overlap* or *maxtry* or *units* +* keyword = *mol* or *basis* or *ratio* or *subset* or *group* or *remap* or *var* or *set* or *radscale* or *meshmode* or *rotate* or *overlap* or *maxtry* or *units* .. parsed-literal:: @@ -44,6 +44,7 @@ Syntax *subset* values = Nsubset seed Nsubset = # of lattice sites to populate randomly seed = random # seed (positive integer) + *group* value = group name *remap* value = *yes* or *no* *var* value = name = variable name to evaluate for test of atom creation *set* values = dim name @@ -83,7 +84,7 @@ Examples create_atoms 3 region regsphere basis 2 3 create_atoms 3 region regsphere basis 2 3 ratio 0.5 74637 - create_atoms 3 single 0 0 5 + create_atoms 3 single 0 0 5 group newatom create_atoms 1 box var v set x xpos set y ypos create_atoms 2 random 50 12345 NULL overlap 2.0 maxtry 50 create_atoms 1 mesh open_box.stl meshmode qrand 0.1 units box @@ -395,6 +396,12 @@ correct number of particles are inserted, in a perfectly random fashion. Which lattice sites are selected will change with the number of processors used. +.. versionadded:: TBD + +The *group* keyword adds the newly created atoms to the named +:doc:`group `. If the group does not yet exist it will be +created. All created atoms are always added to the group "all". + The *remap* keyword only applies to the *single* style. If it is set to *yes*, then if the specified position is outside the simulation box, it will mapped back into the box, assuming the relevant diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index bac3a556eb..93f4519d3c 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -23,6 +23,7 @@ #include "comm.h" #include "domain.h" #include "error.h" +#include "group.h" #include "input.h" #include "irregular.h" #include "lattice.h" @@ -64,6 +65,16 @@ enum { NONE, RATIO, SUBSET }; enum { BISECTION, QUASIRANDOM }; static constexpr const char *mesh_name[] = {"recursive bisection", "quasi-random"}; + +/* ---------------------------------------------------------------------- */ + +CreateAtoms::CreateAtoms(LAMMPS *lmp) : + Command(lmp), basistype(nullptr), xmol(nullptr), vstr(nullptr), xstr(nullptr), ystr(nullptr), + zstr(nullptr), groupname(nullptr), region(nullptr), onemol(nullptr), ranmol(nullptr), + ranlatt(nullptr) +{ +} + /* ---------------------------------------------------------------------- */ CreateAtoms::~CreateAtoms() @@ -80,7 +91,6 @@ CreateAtoms::~CreateAtoms() delete ranmol; delete ranlatt; } -CreateAtoms::CreateAtoms(LAMMPS *lmp) : Command(lmp), basistype(nullptr) {} /* ---------------------------------------------------------------------- */ @@ -179,8 +189,10 @@ void CreateAtoms::command(int narg, char **arg) mesh_density = 1.0; nbasis = domain->lattice->nbasis; - basistype = new int[nbasis]; - for (int i = 0; i < nbasis; i++) basistype[i] = ntype; + if (nbasis > 0) { + basistype = new int[nbasis]; + for (int i = 0; i < nbasis; i++) basistype[i] = ntype; + } while (iarg < narg) { if (strcmp(arg[iarg], "basis") == 0) { @@ -273,6 +285,15 @@ void CreateAtoms::command(int narg, char **arg) if ((nsubset <= 0) || (subsetseed <= 0)) error->all(FLERR, Error::NOPOINTER, "Illegal create_atoms subset settings"); iarg += 3; + } else if (strcmp(arg[iarg], "group") == 0) { + if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "create_atoms group", error); + if (strcmp(arg[iarg + 1], "none") == 0) { + delete[] groupname; + groupname = nullptr; + } else { + groupname = utils::strdup(arg[iarg + 1]); + } + iarg += 2; } else if (strcmp(arg[iarg], "overlap") == 0) { if (style != RANDOM) error->all(FLERR, iarg, "Create_atoms overlap can only be used with random style"); @@ -675,18 +696,6 @@ void CreateAtoms::command(int narg, char **arg) if (domain->triclinic) domain->lamda2x(atom->nlocal); } - // clean up - - delete ranmol; - delete ranlatt; - - delete[] basistype; - delete[] vstr; - delete[] xstr; - delete[] ystr; - delete[] zstr; - if (mode == MOLECULE) memory->destroy(xmol); - // for MOLECULE mode: // create special bond lists for molecular systems, // but not for atom style template @@ -699,6 +708,13 @@ void CreateAtoms::command(int narg, char **arg) } } + // add atoms to group + + if (groupname) { + int groupbit = group->bitmask[group->find_or_create(groupname)]; + for (int i = nlocal_previous; i < atom->nlocal; ++i) atom->mask[i] |= groupbit; + } + // print status MPI_Barrier(world); diff --git a/src/create_atoms.h b/src/create_atoms.h index ca2a8779a9..a1881f38b9 100644 --- a/src/create_atoms.h +++ b/src/create_atoms.h @@ -46,6 +46,7 @@ class CreateAtoms : public Command { int varflag, vvar, xvar, yvar, zvar; char *vstr, *xstr, *ystr, *zstr; + char *groupname; int ilo, ihi, jlo, jhi, klo, khi; From bc031bdd7aff9ed7d02d2a9ef64f471a8057d958 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 08:23:04 -0400 Subject: [PATCH 115/396] initial attempt to allow viewing molecules. --- tools/lammps-gui/imageviewer.cpp | 80 ++++++++++++++++++++++++++++---- tools/lammps-gui/imageviewer.h | 2 + 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index 94405e04ff..f796699938 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -139,8 +139,8 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge QDialog(parent), menuBar(new QMenuBar), imageLabel(new QLabel), scrollArea(new QScrollArea), buttonBox(nullptr), scaleFactor(1.0), atomSize(1.0), saveAsAct(nullptr), copyAct(nullptr), cmdAct(nullptr), zoomInAct(nullptr), zoomOutAct(nullptr), normalSizeAct(nullptr), - lammps(_lammps), group("all"), filename(fileName), useelements(false), usediameter(false), - usesigma(false) + lammps(_lammps), group("all"), molecule("none"), filename(fileName), useelements(false), + usediameter(false), usesigma(false) { imageLabel->setBackgroundRole(QPalette::Base); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); @@ -239,19 +239,30 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge recenter->setToolTip("Recenter on group"); auto *reset = new QPushButton(QIcon(":/icons/gtk-zoom-fit.png"), ""); reset->setToolTip("Reset view to defaults"); - auto *combo = new QComboBox; - combo->setObjectName("group"); - combo->setToolTip("Select group to display"); - combo->setObjectName("group"); - int ngroup = lammps->id_count("group"); + constexpr int BUFLEN = 256; char gname[BUFLEN]; + auto *combo = new QComboBox; + combo->setToolTip("Select group to display"); + combo->setObjectName("group"); + int ngroup = lammps->id_count("group"); for (int i = 0; i < ngroup; ++i) { memset(gname, 0, BUFLEN); lammps->id_name("group", i, gname, BUFLEN); combo->addItem(gname); } + auto *molbox = new QComboBox; + molbox->setToolTip("Select molecule to display"); + molbox->setObjectName("molecule"); + molbox->addItem("none"); + int nmols = lammps->id_count("molecule"); + for (int i = 0; i < nmols; ++i) { + memset(gname, 0, BUFLEN); + lammps->id_name("molecule", i, gname, BUFLEN); + molbox->addItem(gname); + } + auto *menuLayout = new QHBoxLayout; auto *buttonLayout = new QHBoxLayout; auto *topLayout = new QVBoxLayout; @@ -272,6 +283,8 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge menuLayout->addWidget(dummy1); menuLayout->addWidget(new QLabel(" Group: ")); menuLayout->addWidget(combo); + menuLayout->addWidget(new QLabel(" Molecule: ")); + menuLayout->addWidget(molbox); buttonLayout->addWidget(dummy2); buttonLayout->addWidget(dossao); buttonLayout->addWidget(doanti); @@ -304,6 +317,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge connect(recenter, &QPushButton::released, this, &ImageViewer::do_recenter); connect(reset, &QPushButton::released, this, &ImageViewer::reset_view); connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(change_group(int))); + connect(molbox, SIGNAL(currentIndexChanged(int)), this, SLOT(change_molecule(int))); mainLayout->addLayout(topLayout); mainLayout->addWidget(scrollArea); @@ -529,16 +543,60 @@ void ImageViewer::cmd_to_clipboard() void ImageViewer::change_group(int) { auto *box = findChild("group"); - if (box) group = box->currentText(); + group = box ? box->currentText() : "all"; + + // reset molecule to "none" when changing group + box = findChild("molecule"); + if (box && (box->currentIndex() > 0)) { + box->setCurrentIndex(0); // triggers call to createImage() + } else { + createImage(); + } +} + +void ImageViewer::change_molecule(int) +{ + auto *box = findChild("molecule"); + molecule = box ? box->currentText() : "none"; + createImage(); } +// This function creates a visualization of the current system using the +// "dump image" command and reads and displays the renderd image. +// To visualize molecules we create new atoms with create_atoms and +// put them into a new, temporary group and then visualize that group. +// After rendering the image, the atoms and group are deleted. +// to update bond data, we also need to issue a "run 0" command. + void ImageViewer::createImage() { auto *renderstatus = findChild("renderstatus"); if (renderstatus) renderstatus->setEnabled(true); repaint(); + QString oldgroup = group; + + if (molecule != "none") { + + // get center of box + double *boxlo, *boxhi, xmid, ymid, zmid; + boxlo = (double *)lammps->extract_global("boxlo"); + boxhi = (double *)lammps->extract_global("boxhi"); + if (boxlo && boxhi) { + xmid = 0.5 * (boxhi[0] + boxlo[0]); + ymid = 0.5 * (boxhi[1] + boxlo[1]); + zmid = 0.5 * (boxhi[2] + boxlo[2]); + } else { + xmid = ymid = zmid = 0.0; + } + + QString molcreate = "create_atoms 0 single %1 %2 %3 mol %4 312944 group %5 units box"; + group = "imgviewer_tmp_mol"; + lammps->command(molcreate.arg(xmid).arg(ymid).arg(zmid).arg(molecule).arg(group)); + lammps->command("run 0 post no"); + } + QSettings settings; QString dumpcmd = QString("write_dump ") + group + " image "; QDir dumpdir(QDir::tempPath()); @@ -683,6 +741,12 @@ void ImageViewer::createImage() imageLabel->adjustSize(); if (renderstatus) renderstatus->setEnabled(false); repaint(); + + if (molecule != "none") { + lammps->command(QString("delete_atoms group %1 compress no").arg(group)); + lammps->command(QString("group %1 delete").arg(group)); + group = oldgroup; + } } void ImageViewer::saveAs() diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index 0c175bd03f..3a44c7fa1c 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -60,6 +60,7 @@ private slots: void do_recenter(); void cmd_to_clipboard(); void change_group(int); + void change_molecule(int); public: void createImage(); @@ -89,6 +90,7 @@ private: LammpsWrapper *lammps; QString group; + QString molecule; QString filename; QString last_dump_cmd; int xsize, ysize; From dfc10e5b59674c764530be95923c7d69a993788a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 08:56:57 -0400 Subject: [PATCH 116/396] small improvements of molecule visualization. --- tools/lammps-gui/TODO.md | 2 -- tools/lammps-gui/imageviewer.cpp | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index a917a4cf62..996ab43a93 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -2,8 +2,6 @@ LAMMPS-GUI TODO list: # Short term goals (v1.x) -- add feature to visualize "molecules" from the molecule command. - this could use the image viewer, but create an empty system and then just one molecule - implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences. - add a "Filter data" checkbox to the "Charts" window to select whether data should be dropped. - add a "Charts tab" to the preferences with the following (default) settings: diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index f796699938..5f519ca9a7 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -559,6 +559,13 @@ void ImageViewer::change_molecule(int) auto *box = findChild("molecule"); molecule = box ? box->currentText() : "none"; + box = findChild("group"); + if (molecule == "none") { + box->setEnabled(true); + } else { + box->setEnabled(false); + } + createImage(); } @@ -594,6 +601,7 @@ void ImageViewer::createImage() QString molcreate = "create_atoms 0 single %1 %2 %3 mol %4 312944 group %5 units box"; group = "imgviewer_tmp_mol"; lammps->command(molcreate.arg(xmid).arg(ymid).arg(zmid).arg(molecule).arg(group)); + lammps->command(QString("neigh_modify exclude group all %1").arg(group)); lammps->command("run 0 post no"); } @@ -743,6 +751,7 @@ void ImageViewer::createImage() repaint(); if (molecule != "none") { + lammps->command("neigh_modify exclude none"); lammps->command(QString("delete_atoms group %1 compress no").arg(group)); lammps->command(QString("group %1 delete").arg(group)); group = oldgroup; From 83c785740bc16137169b4c42e09248c0b231162f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 10:49:27 -0400 Subject: [PATCH 117/396] improve phrasing --- doc/src/Python_launch.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/Python_launch.rst b/doc/src/Python_launch.rst index f9bd9c1c98..046edccfbc 100644 --- a/doc/src/Python_launch.rst +++ b/doc/src/Python_launch.rst @@ -1,7 +1,7 @@ Running LAMMPS and Python in serial ----------------------------------- -To run a LAMMPS in serial, type these lines into Python +To run a LAMMPS input in serial, type these lines into Python interactively from the ``bench`` directory: .. code-block:: python From 90797c7b62b6e9223fa0296604f58c7d8da018aa Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 10 Apr 2025 11:51:13 -0400 Subject: [PATCH 118/396] document that also molecules from the molecule command can be visualized --- doc/src/Howto_lammps_gui.rst | 41 +++++++++++++++---------- tools/lammps-gui/lammps-gui.appdata.xml | 1 + 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index adf0c836fb..53d890ea7e 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -481,22 +481,31 @@ types. |gui-image1| |gui-image2| The default image size, some default image quality settings, the view -style and some colors can be changed in the *Preferences* dialog -window. From the image viewer window further adjustments can be made: -actual image size, high-quality (SSAO) rendering, anti-aliasing, view -style, display of box or axes, zoom factor. The view of the system can -be rotated horizontally and vertically. It is also possible to only -display the atoms within a group defined in the input script (default is -"all"). The image can also be re-centered on the center of mass of the -selected group. After each change, the image is rendered again and the -display updated. The small palette icon on the top left is colored -while LAMMPS is running to render the new image; it is grayed out when -LAMMPS is finished. When there are many atoms to render and high -quality images with anti-aliasing are requested, re-rendering may take -several seconds. From the *File* menu of the image window, the -current image can be saved to a file (keyboard shortcut `Ctrl-S`) or -copied to the clipboard (keyboard shortcut `Ctrl-C`) for pasting the -image into another application. +style and some colors can be changed in the *Preferences* dialog window. +From the image viewer window further adjustments can be made: actual +image size, high-quality (SSAO) rendering, anti-aliasing, view style, +display of box or axes, zoom factor. The view of the system can be +rotated horizontally and vertically. + +It is also possible to display only the atoms within a :doc:`group +defined in the input script ` (default is "all"). The available +groups can be selected from the drop down list next to the "Group:" +label. Similarly, if there are :doc:`molecules defined in the input +`, it is possible to select one of them (default is "none") +and visualize it (it will be shown at the center of the simulation box). +While a molecule is selected, the group selection is disabled. It can +be restored by selecting the molecule "none". + +The image can also be re-centered on the center of mass of the selected +group. After each change, the image is rendered again and the display +updated. The small palette icon on the top left is colored while LAMMPS +is running to render the new image; it is grayed out when LAMMPS is +finished. When there are many atoms to render and high quality images +with anti-aliasing are requested, re-rendering may take several seconds. +From the *File* menu of the image window, the current image can be saved +to a file (keyboard shortcut `Ctrl-S`) or copied to the clipboard +(keyboard shortcut `Ctrl-C`) for pasting the image into another +application. From the *File* menu it is also possible to copy the current :doc:`dump image ` and :doc:`dump_modify ` diff --git a/tools/lammps-gui/lammps-gui.appdata.xml b/tools/lammps-gui/lammps-gui.appdata.xml index 1b34b0c7bd..898966dccc 100644 --- a/tools/lammps-gui/lammps-gui.appdata.xml +++ b/tools/lammps-gui/lammps-gui.appdata.xml @@ -59,6 +59,7 @@ Change working directory to user's home dir if initial directory is "/" or the Application folder Add preferences option to set https proxy, if not already set via environment variable + Add option to visualize molecules defined through the molecule command From 4dd8c66390a723accb315d96f5e84bfbdadc4e44 Mon Sep 17 00:00:00 2001 From: talinke Date: Thu, 10 Apr 2025 10:33:08 -0700 Subject: [PATCH 119/396] Updated documentation --- doc/src/Commands_fix.rst | 1 + doc/src/Howto_thermostat.rst | 3 +- doc/src/fix.rst | 1 + doc/src/fix_langevin_gjf.rst | 211 +++++++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 doc/src/fix_langevin_gjf.rst diff --git a/doc/src/Commands_fix.rst b/doc/src/Commands_fix.rst index 35c3804969..58397d7c7e 100644 --- a/doc/src/Commands_fix.rst +++ b/doc/src/Commands_fix.rst @@ -92,6 +92,7 @@ OPT. * :doc:`langevin (k) ` * :doc:`langevin/drude ` * :doc:`langevin/eff ` + * :doc:`langevin/gjf ` * :doc:`langevin/spin ` * :doc:`lb/fluid ` * :doc:`lb/momentum ` diff --git a/doc/src/Howto_thermostat.rst b/doc/src/Howto_thermostat.rst index fe53fff540..6719abfc82 100644 --- a/doc/src/Howto_thermostat.rst +++ b/doc/src/Howto_thermostat.rst @@ -22,6 +22,7 @@ can be invoked via the *dpd/tstat* pair style: * :doc:`fix temp/berendsen ` * :doc:`fix temp/csvr ` * :doc:`fix langevin ` +* :doc:`fix langevin/gjf ` * :doc:`fix temp/rescale ` * :doc:`pair_style dpd/tstat ` @@ -82,7 +83,7 @@ that: .. note:: - Only the nvt fixes perform time integration, meaning they update + Only the nvt and langevin/gjf fixes perform time integration, meaning they update the velocities and positions of particles due to forces and velocities respectively. The other thermostat fixes only adjust velocities; they do NOT perform time integration updates. Thus they should be used in diff --git a/doc/src/fix.rst b/doc/src/fix.rst index 3b1bc4a75c..13a6ad166d 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -271,6 +271,7 @@ accelerated styles exist. * :doc:`langevin ` - Langevin temperature control * :doc:`langevin/drude ` - Langevin temperature control of Drude oscillators * :doc:`langevin/eff ` - Langevin temperature control for the electron force field model +* :doc:`langevin/gjf ` - statistically correct Langevin temperature control using the GJ methods * :doc:`langevin/spin ` - Langevin temperature control for a spin or spin-lattice system * :doc:`lb/fluid ` - lattice-Boltzmann fluid on a uniform mesh * :doc:`lb/momentum ` - :doc:`fix momentum ` replacement for use with a lattice-Boltzmann fluid diff --git a/doc/src/fix_langevin_gjf.rst b/doc/src/fix_langevin_gjf.rst new file mode 100644 index 0000000000..08e6c1c87b --- /dev/null +++ b/doc/src/fix_langevin_gjf.rst @@ -0,0 +1,211 @@ +.. index:: fix langevin/gjf + +fix langevin/gjf command +======================== + +Syntax +"""""" + +.. code-block:: LAMMPS + + fix ID group-ID langevin/gjf Tstart Tstop damp seed keyword values ... + +* ID, group-ID are documented in :doc:`fix ` command +* langevin/gjf = style name of this fix command +* Tstart,Tstop = desired temperature at start/end of run (temperature units) +* Tstart can be a variable (see below) +* damp = damping parameter (time units) +* seed = random number seed to use for white noise (positive integer) +* zero or more keyword/value pairs may be appended +* keyword = *vel* or *method* + + .. parsed-literal:: + + *vel* value = *vfull* or *vhalf* + *vfull* = use on-site velocity + *vhalf* = use half-step velocity + *method* value = *1-8* + *1-8* = choose one of the many GJ formulations + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix 3 boundary langevin/gjf 10.0 10.0 1.0 699483 + fix 1 all langevin/gjf 10.0 100.0 100.0 48279 vel vfull method 4 + +Description +""""""""""" + +Apply a Langevin thermostat as described in :ref:`(Gronbech-Jensen-2024) ` +to a group of atoms which models an interaction with a background +implicit solvent. As described in the papers cited below, the purpose of this method is to +enable longer timesteps to be used (up to the numerical stability +limit of the integrator), while still producing the correct Boltzmann +distribution of atom positions. + +The current implementation provides the user with the option to output +the velocity in one of two forms: *vfull* or *vhalf*. The option *vfull* outputs the +on-site velocity given in :ref:`Gronbech-Jensen/Farago +`; this velocity is shown to be systematically lower +than the target temperature by a small amount, which grows +quadratically with the timestep. The option *vhalf* outputs the +2GJ half-step velocity given in :ref:`Gronbech Jensen/Gronbech-Jensen +`; for linear systems, this velocity is shown to not +have any statistical errors for any stable time step. An overview of +statistically correct Boltzmann and Maxwell-Boltzmann sampling of true +on-site and true half-step velocities is given in +:ref:`Gronbech-Jensen-2020 `. + +This fix allows the use of any of the GJ methods as listed in :ref:`Gronbech-Jensen-2020 `. +The GJ-VII method is described in :ref:`Finkelstein `. +The implementation follows the splitting form provided in Eqs. (24) and (25) +in :ref:`Gronbech-Jensen-2024 `, including the application +of Gaussian noise values, per the description in +:ref:`Gronbech-Jensen-2023 `. + + +.. note:: + + Unlike the :doc:`fix langevin ` command which performs force + modifications only, this fix performs thermostatting and time integration. + Thus you no longer need a separate time integration fix, like :doc:`fix nve `. + +See the :doc:`Howto thermostat ` page for +a discussion of different ways to compute temperature and perform +thermostatting. + +The desired temperature at each timestep is a ramped value during the +run from *Tstart* to *Tstop*\ . + +*Tstart* can be specified as an equal-style or atom-style +:doc:`variable `. In this case, the *Tstop* setting is +ignored. 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 each timestep, and its value used to determine the +target temperature. + +Equal-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. Thus it is easy to specify a time-dependent temperature. + +Atom-style variables can specify the same formulas as equal-style +variables but can also include per-atom values, such as atom +coordinates. Thus it is easy to specify a spatially-dependent +temperature with optional time-dependence as well. + +Like other fixes that perform thermostatting, this fix can be used +with :doc:`compute commands ` that remove a "bias" from the +atom velocities. E.g. to apply the thermostat only to atoms within a +spatial :doc:`region `, or to remove the center-of-mass +velocity from a group of atoms, or to remove the x-component of +velocity from the calculation. + +This is not done by default, but only if the :doc:`fix_modify +` command is used to assign a temperature compute to this +fix that includes such a bias term. See the doc pages for individual +:doc:`compute temp commands ` to determine which ones include +a bias. In this case, the thermostat works in the following manner: +bias is removed from each atom, thermostatting is performed on the +remaining thermal degrees of freedom, and the bias is added back in. + +The *damp* parameter is specified in time units and determines how +rapidly the temperature is relaxed. For example, a value of 100.0 means +to relax the temperature in a timespan of (roughly) 100 time units +(:math:`\tau` or fs or ps - see the :doc:`units ` command). The +damp factor can be thought of as inversely related to the viscosity of +the solvent. I.e. a small relaxation time implies a high-viscosity +solvent and vice versa. See the discussion about :math:`\gamma` and +viscosity in the documentation for the :doc:`fix viscous ` +command for more details. + +The random # *seed* must be a positive integer. A Marsaglia random +number generator is used. Each processor uses the input seed to +generate its own unique seed and its own stream of random numbers. +Thus the dynamics of the system will not be identical on two runs on +different numbers of processors. + +---------- + +The keyword/value option pairs are used in the following ways. + +The keyword *vel* determine which velocity is used to determine +quantities of interest in the simulation. + +The keyword *method* selects one of the eight GJ-methods implemented in LAMMPS. + +*Insert brief explanation for each method* + +---------- + +.. include:: accel_styles.rst + +---------- + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files `. +For the Bruenger thermostat: Because the state of the random number generator +is not saved in restart files, this means you cannot do "exact" +restarts with this fix, where the simulation continues on the same as +if no restart had taken place. However, in a statistical sense, a +restarted simulation should produce the same behavior. The "exact" restart is +done with either vfull or vhalf velocity output for as long as the choice of +vfull/vhalf is the same for the simulation as it is in the restart file. + +The :doc:`fix_modify ` *temp* option is supported by this +fix. You can use it to assign a temperature :doc:`compute ` +you have defined to this fix which will be used in its thermostatting +procedure, as described above. For consistency, the group used by +this fix and by the compute should be the same. + +This fix can ramp its target temperature over multiple runs, using the +*start* and *stop* keywords of the :doc:`run ` command. See the +:doc:`run ` command for details of how to do this. + +This fix is not invoked during :doc:`energy minimization `. + +Restrictions +"""""""""""" + +This fix is not compatible with run_style respa. + +Related commands +"""""""""""""""" + +:doc:`fix langevin `, :doc:`fix nvt ` + +Default +""""""" + +The option defaults are vel = vhalf, method = 1. + +---------- + +.. _Gronbech-Jensen-2024: + +**(Gronbech-Jensen-2024)** Gronbech-Jensen, J. Stat. Phys. 191, 137 (2024). + +.. _Gronbech-Jensen-Farago: + +**(Gronbech-Jensen/Farago)** Gronbech-Jensen and Farago, Mol Phys, 111, 983 +(2013). + +.. _Gronbech-Jensen-2019: + +**(Gronbech Jensen/Gronbech-Jensen)** Gronbech Jensen and Gronbech-Jensen, Mol Phys, 117, 2511 (2019) + +.. _Gronbech-Jensen-2020: + +**(Gronbech-Jensen-2020)** Gronbech-Jensen, Mol Phys 118, e1662506 (2020). + +.. _Finkelstein: + +**(Finkelstein)** Finkelstein, Cheng, Florin, Seibold, Gronbech-Jensen, J. Chem. Phys., 155, 18 (2021) + +.. _Gronbech-Jensen-2023: + +**(Gronbech-Jensen-2023)** Gronbech-Jensen, J. Stat. Phys. 190, 96 (2023). From 43a7b14b7ceebaaadb01366bf030d711e0ab3003 Mon Sep 17 00:00:00 2001 From: talinke Date: Thu, 10 Apr 2025 12:01:02 -0700 Subject: [PATCH 120/396] New example structure --- doc/src/fix_langevin_gjf.rst | 18 ++- examples/gjf/README | 46 +++++++ examples/gjf/README.md | 13 -- examples/gjf/in.gjf.vfull | 5 +- examples/gjf/in.gjf.vhalf | 5 +- examples/gjf/log.15Oct19.gjf.vfull.g++.1 | 125 ------------------- examples/gjf/log.15Oct19.gjf.vfull.g++.4 | 125 ------------------- examples/gjf/log.15Oct19.gjf.vhalf.g++.1 | 125 ------------------- examples/gjf/log.15Oct19.gjf.vhalf.g++.4 | 125 ------------------- examples/gjf/log.2Apr25.gjf.vfull.g++.1 | 152 +++++++++++++++++++++++ examples/gjf/log.2Apr25.gjf.vfull.g++.4 | 152 +++++++++++++++++++++++ examples/gjf/log.2Apr25.gjf.vhalf.g++.1 | 152 +++++++++++++++++++++++ examples/gjf/log.2Apr25.gjf.vhalf.g++.4 | 152 +++++++++++++++++++++++ src/EXTRA-FIX/fix_langevin_gjf.cpp | 87 +++++++------ src/EXTRA-FIX/fix_langevin_gjf.h | 14 +-- 15 files changed, 713 insertions(+), 583 deletions(-) create mode 100644 examples/gjf/README delete mode 100644 examples/gjf/README.md delete mode 100644 examples/gjf/log.15Oct19.gjf.vfull.g++.1 delete mode 100644 examples/gjf/log.15Oct19.gjf.vfull.g++.4 delete mode 100644 examples/gjf/log.15Oct19.gjf.vhalf.g++.1 delete mode 100644 examples/gjf/log.15Oct19.gjf.vhalf.g++.4 create mode 100644 examples/gjf/log.2Apr25.gjf.vfull.g++.1 create mode 100644 examples/gjf/log.2Apr25.gjf.vfull.g++.4 create mode 100644 examples/gjf/log.2Apr25.gjf.vhalf.g++.1 create mode 100644 examples/gjf/log.2Apr25.gjf.vhalf.g++.4 diff --git a/doc/src/fix_langevin_gjf.rst b/doc/src/fix_langevin_gjf.rst index 08e6c1c87b..e58b4305bd 100644 --- a/doc/src/fix_langevin_gjf.rst +++ b/doc/src/fix_langevin_gjf.rst @@ -107,9 +107,7 @@ This is not done by default, but only if the :doc:`fix_modify ` command is used to assign a temperature compute to this fix that includes such a bias term. See the doc pages for individual :doc:`compute temp commands ` to determine which ones include -a bias. In this case, the thermostat works in the following manner: -bias is removed from each atom, thermostatting is performed on the -remaining thermal degrees of freedom, and the bias is added back in. +a bias. The *damp* parameter is specified in time units and determines how rapidly the temperature is relaxed. For example, a value of 100.0 means @@ -148,13 +146,13 @@ Restart, fix_modify, output, run start/stop, minimize info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" No information about this fix is written to :doc:`binary restart files `. -For the Bruenger thermostat: Because the state of the random number generator -is not saved in restart files, this means you cannot do "exact" -restarts with this fix, where the simulation continues on the same as -if no restart had taken place. However, in a statistical sense, a -restarted simulation should produce the same behavior. The "exact" restart is -done with either vfull or vhalf velocity output for as long as the choice of -vfull/vhalf is the same for the simulation as it is in the restart file. +Because the state of the random number generator is not saved in restart files, +this means you cannot do "exact" restarts with this fix, where the simulation +continues on the same as if no restart had taken place. However, in a +statistical sense, a restarted simulation should produce the same behavior. +The "exact" restart is done with either vfull or vhalf velocity output for as +long as the choice of vfull/vhalf is the same for the simulation as it is in +the restart file. The :doc:`fix_modify ` *temp* option is supported by this fix. You can use it to assign a temperature :doc:`compute ` diff --git a/examples/gjf/README b/examples/gjf/README new file mode 100644 index 0000000000..fdbc843522 --- /dev/null +++ b/examples/gjf/README @@ -0,0 +1,46 @@ +LAMMPS GJ THERMOSTAT EXAMPLE + +Required LAMMPS packages: EXTRA-FIX, MOLECULE, EXTRA-PAIR + +This directory contains the ingredients to run an NVT simulation using the +GJ thermostats. + +Example: + +NP=4 #number of processors +mpirun -np $NP lmp_mpi -in.gjf.vhalf + +Compared to other thermostats, the GJ thermostat allows for larger timesteps +with the correct Boltzmann statistics. A comparison using averaged properties +from this example's input file is shown below. 'X' denotes a failed simulation. + +KINETIC ENERGY (eV) +| Δt || 0.01 | 0.05 | 0.10 | 0.11 | 0.12 | 0.13 | 0.14 | +|==============||========|========|========|========|========|========|========| +| langevin/gjf || 1.112 | 1.108 | 1.114 | 1.118 | 1.111 | 1.133 | 1.168 | +| langevin || 1.113 | 1.125 | 1.121 | 1.135 | 1.152 | X | X | +| nvt || 1.094 | 1.114 | 1.117 | 1.113 | 1.121 | X | X | +|--------------||--------|--------|--------|--------|--------|--------|--------| + +POTENTIAL ENERGY (eV) +| Δt || 0.01 | 0.05 | 0.10 | 0.11 | 0.12 | 0.13 | 0.14 | +|==============||========|========|========|========|========|========|========| +| langevin/gjf || -55.16 | -55.16 | -55.15 | -55.15 | -55.15 | -55.14 | -55.12 | +| langevin || -55.16 | -55.12 | -54.93 | -54.85 | -54.71 | X | X | +| nvt || -55.17 | -55.10 | -54.95 | -54.88 | -54.82 | X | X | +|--------------||--------|--------|--------|--------|--------|--------|--------| + + +Script Commands: +-- +fix nve all nve +fix lang all langevin 10 10 1 26488 +-- +vs +-- +fix noho all nvt temp 10 10 1 +-- +vs +-- +fix lang all langevin/gjf 10 10 1 26488 +-- \ No newline at end of file diff --git a/examples/gjf/README.md b/examples/gjf/README.md deleted file mode 100644 index e6886cb2dd..0000000000 --- a/examples/gjf/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# LAMMPS GJF-2GJ THERMOSTAT EXAMPLE - -## GJF-2GJ THERMOSTAT - -This directory contains the ingredients to run an NVT simulation using the GJF-2GJ thermostat. - -Example: -``` -NP=4 #number of processors -mpirun -np $NP lmp_mpi -in.gjf.vhalf -``` - -## Required LAMMPS packages: MOLECULE package diff --git a/examples/gjf/in.gjf.vfull b/examples/gjf/in.gjf.vfull index 40512ac37a..8512dad837 100644 --- a/examples/gjf/in.gjf.vfull +++ b/examples/gjf/in.gjf.vfull @@ -1,4 +1,4 @@ -# GJF-2GJ thermostat +# GJ thermostat units metal atom_style full @@ -14,8 +14,7 @@ neighbor 1 bin timestep 0.1 -fix lang all langevin 10 10 1 26488 gjf vfull -fix nve all nve +fix lang all langevin/gjf 10 10 1 26488 vel vfull method 4 thermo 200 run 5000 diff --git a/examples/gjf/in.gjf.vhalf b/examples/gjf/in.gjf.vhalf index 63fb8bd467..08b0b45c8c 100644 --- a/examples/gjf/in.gjf.vhalf +++ b/examples/gjf/in.gjf.vhalf @@ -1,4 +1,4 @@ -# GJF-2GJ thermostat +# GJ thermostat units metal atom_style full @@ -14,8 +14,7 @@ neighbor 1 bin timestep 0.1 -fix lang all langevin 10 10 1 26488 gjf vhalf -fix nve all nve +fix lang all langevin/gjf 10 10 1 26488 thermo 200 run 5000 diff --git a/examples/gjf/log.15Oct19.gjf.vfull.g++.1 b/examples/gjf/log.15Oct19.gjf.vfull.g++.1 deleted file mode 100644 index e3e9cce124..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vfull.g++.1 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 1 by 1 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000150019 secs - read_data CPU = 0.001946 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vfull -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.875 | 6.875 | 6.875 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080223 -56.207655 0 -54.97164 37.215524 - 200 8.2588471 -55.073602 0 -54.152316 339.80416 - 400 8.1427292 -55.072244 0 -54.16391 338.91883 - 600 8.7595618 -55.066739 0 -54.089596 344.25426 - 800 8.550633 -55.148315 0 -54.194479 318.9385 - 1000 8.5394337 -55.125709 0 -54.173122 326.59471 - 1200 8.565973 -55.114892 0 -54.159345 328.5193 - 1400 8.2092914 -55.109233 0 -54.193475 329.56161 - 1600 8.209495 -55.138161 0 -54.22238 321.39971 - 1800 8.4039924 -55.13355 0 -54.196072 322.64214 - 2000 8.4548937 -55.062994 0 -54.119838 343.29888 - 2200 8.3775139 -55.13364 0 -54.199116 323.63744 - 2400 8.537332 -55.163702 0 -54.21135 315.62864 - 2600 8.672488 -55.112054 0 -54.144625 330.1106 - 2800 8.3000218 -55.147275 0 -54.221396 318.73112 - 3000 8.3552421 -55.135164 0 -54.203124 323.53075 - 3200 8.4126798 -55.135753 0 -54.197306 321.48817 - 3400 8.4986413 -55.135408 0 -54.187372 323.42951 - 3600 8.38431 -55.103932 0 -54.16865 330.68929 - 3800 8.8262454 -55.103648 0 -54.119067 332.97779 - 4000 7.9658136 -55.120402 0 -54.231803 324.9595 - 4200 8.2265544 -55.129011 0 -54.211327 323.87069 - 4400 8.1253738 -55.153089 0 -54.246691 316.304 - 4600 8.2010823 -55.124053 0 -54.20921 325.98402 - 4800 8.5512149 -55.075877 0 -54.121976 338.30137 - 5000 8.4737659 -55.158604 0 -54.213343 316.22418 -Loop time of 2.73236 on 1 procs for 5000 steps with 864 atoms - -Performance: 15810.507 ns/day, 0.002 hours/ns, 1829.920 timesteps/s -99.7% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 1.4262 | 1.4262 | 1.4262 | 0.0 | 52.20 -Bond | 0.00042836 | 0.00042836 | 0.00042836 | 0.0 | 0.02 -Neigh | 0.12819 | 0.12819 | 0.12819 | 0.0 | 4.69 -Comm | 0.058611 | 0.058611 | 0.058611 | 0.0 | 2.15 -Output | 0.00047283 | 0.00047283 | 0.00047283 | 0.0 | 0.02 -Modify | 1.0924 | 1.0924 | 1.0924 | 0.0 | 39.98 -Other | | 0.02605 | | | 0.95 - -Nlocal: 864 ave 864 max 864 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 1593 ave 1593 max 1593 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 18143 ave 18143 max 18143 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 18143 -Ave neighs/atom = 20.9988 -Ave special neighs/atom = 0 -Neighbor list builds = 158 -Dangerous builds = 5 - - -Total wall time: 0:00:02 diff --git a/examples/gjf/log.15Oct19.gjf.vfull.g++.4 b/examples/gjf/log.15Oct19.gjf.vfull.g++.4 deleted file mode 100644 index 95caed5dc9..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vfull.g++.4 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 2 by 2 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000556268 secs - read_data CPU = 0.003817 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vfull -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.808 | 6.808 | 6.808 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080228 -56.207655 0 -54.971639 37.215541 - 200 8.4818184 -55.127334 0 -54.181174 324.96159 - 400 8.5960916 -55.09236 0 -54.133453 334.83136 - 600 8.1607556 -55.073136 0 -54.162791 339.035 - 800 8.8350489 -55.133382 0 -54.147819 324.48149 - 1000 8.5692704 -55.118463 0 -54.162548 327.26328 - 1200 8.4174147 -55.126297 0 -54.187322 324.4248 - 1400 8.6362603 -55.123075 0 -54.159688 326.7798 - 1600 8.222512 -55.153799 0 -54.236565 317.8147 - 1800 8.324523 -55.116698 0 -54.188085 327.35373 - 2000 7.9615959 -55.155825 0 -54.267697 315.37215 - 2200 8.495968 -55.083943 0 -54.136205 336.67775 - 2400 7.7926986 -55.044816 0 -54.175529 344.87758 - 2600 8.1551351 -55.069404 0 -54.159687 339.60901 - 2800 8.2593599 -55.084151 0 -54.162807 336.54935 - 3000 8.2860869 -55.110296 0 -54.185971 328.99074 - 3200 8.4074534 -55.123576 0 -54.185712 326.06823 - 3400 8.6694364 -55.128925 0 -54.161836 324.67512 - 3600 8.5718984 -55.129861 0 -54.173653 325.20586 - 3800 8.508102 -55.099093 0 -54.150001 333.91437 - 4000 8.2966658 -55.117782 0 -54.192276 327.13516 - 4200 8.7641728 -55.135792 0 -54.158136 324.00844 - 4400 8.8827909 -55.096369 0 -54.10548 335.08467 - 4600 8.7666577 -55.127213 0 -54.149279 326.15539 - 4800 8.6670762 -55.163395 0 -54.19657 316.48383 - 5000 8.1893094 -55.073756 0 -54.160226 337.95271 -Loop time of 0.870594 on 4 procs for 5000 steps with 864 atoms - -Performance: 49621.267 ns/day, 0.000 hours/ns, 5743.202 timesteps/s -96.5% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.33582 | 0.35125 | 0.3724 | 2.3 | 40.35 -Bond | 0.00030267 | 0.00031316 | 0.00033538 | 0.0 | 0.04 -Neigh | 0.034246 | 0.03479 | 0.035904 | 0.4 | 4.00 -Comm | 0.15068 | 0.17419 | 0.19191 | 3.6 | 20.01 -Output | 0.00044776 | 0.00054703 | 0.00083177 | 0.0 | 0.06 -Modify | 0.27679 | 0.28079 | 0.28849 | 0.9 | 32.25 -Other | | 0.02871 | | | 3.30 - -Nlocal: 216 ave 216 max 216 min -Histogram: 4 0 0 0 0 0 0 0 0 0 -Nghost: 888.75 ave 899 max 876 min -Histogram: 1 0 1 0 0 0 0 0 0 2 -Neighs: 4536 ave 4737 max 4335 min -Histogram: 2 0 0 0 0 0 0 0 0 2 - -Total # of neighbors = 18144 -Ave neighs/atom = 21 -Ave special neighs/atom = 0 -Neighbor list builds = 178 -Dangerous builds = 11 - - -Total wall time: 0:00:00 diff --git a/examples/gjf/log.15Oct19.gjf.vhalf.g++.1 b/examples/gjf/log.15Oct19.gjf.vhalf.g++.1 deleted file mode 100644 index a87b20a887..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vhalf.g++.1 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 1 by 1 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000147804 secs - read_data CPU = 0.00194898 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vhalf -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.5 | 6.5 | 6.5 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080223 -56.207655 0 -54.97164 37.215524 - 200 9.8808568 -55.073602 0 -53.971378 345.62207 - 400 9.8712816 -55.072244 0 -53.971088 345.11889 - 600 10.528988 -55.066739 0 -53.892214 350.60093 - 800 10.167171 -55.148315 0 -54.014152 324.73679 - 1000 10.029026 -55.125709 0 -54.006956 331.93766 - 1200 10.194424 -55.114892 0 -53.977688 334.36032 - 1400 9.3473846 -55.109233 0 -54.066518 333.64378 - 1600 9.7774071 -55.138161 0 -54.047477 327.02358 - 1800 9.9814275 -55.13355 0 -54.020107 328.30017 - 2000 10.2515 -55.062994 0 -53.919424 349.74304 - 2200 9.8126922 -55.13364 0 -54.039019 328.78521 - 2400 10.044314 -55.163702 0 -54.043244 321.03397 - 2600 10.543316 -55.112054 0 -53.935932 336.82099 - 2800 9.7874375 -55.147275 0 -54.055472 324.06626 - 3000 9.7703821 -55.135164 0 -54.045263 328.60665 - 3200 10.141958 -55.135753 0 -54.004402 327.69084 - 3400 10.160576 -55.135408 0 -54.00198 329.39063 - 3600 10.044652 -55.103932 0 -53.983436 336.64469 - 3800 10.662403 -55.103648 0 -53.914241 339.56382 - 4000 9.2921047 -55.120402 0 -54.083853 329.71671 - 4200 9.8744553 -55.129011 0 -54.027501 329.78147 - 4400 9.4085964 -55.153089 0 -54.103546 320.90673 - 4600 9.5463801 -55.124053 0 -54.05914 330.80941 - 4800 10.223884 -55.075877 0 -53.935387 344.30099 - 5000 9.6243338 -55.158604 0 -54.084996 320.3511 -Loop time of 2.29551 on 1 procs for 5000 steps with 864 atoms - -Performance: 18819.358 ns/day, 0.001 hours/ns, 2178.166 timesteps/s -99.7% CPU use with 1 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 1.4393 | 1.4393 | 1.4393 | 0.0 | 62.70 -Bond | 0.0004441 | 0.0004441 | 0.0004441 | 0.0 | 0.02 -Neigh | 0.12136 | 0.12136 | 0.12136 | 0.0 | 5.29 -Comm | 0.059342 | 0.059342 | 0.059342 | 0.0 | 2.59 -Output | 0.00046968 | 0.00046968 | 0.00046968 | 0.0 | 0.02 -Modify | 0.64937 | 0.64937 | 0.64937 | 0.0 | 28.29 -Other | | 0.02522 | | | 1.10 - -Nlocal: 864 ave 864 max 864 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Nghost: 1593 ave 1593 max 1593 min -Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 18143 ave 18143 max 18143 min -Histogram: 1 0 0 0 0 0 0 0 0 0 - -Total # of neighbors = 18143 -Ave neighs/atom = 20.9988 -Ave special neighs/atom = 0 -Neighbor list builds = 158 -Dangerous builds = 5 - - -Total wall time: 0:00:02 diff --git a/examples/gjf/log.15Oct19.gjf.vhalf.g++.4 b/examples/gjf/log.15Oct19.gjf.vhalf.g++.4 deleted file mode 100644 index a70a67a89c..0000000000 --- a/examples/gjf/log.15Oct19.gjf.vhalf.g++.4 +++ /dev/null @@ -1,125 +0,0 @@ -LAMMPS (19 Sep 2019) - using 1 OpenMP thread(s) per MPI task -# GJF-2GJ thermostat - -units metal -atom_style full - -boundary p p p -read_data argon.lmp - orthogonal box = (0 0 0) to (32.146 32.146 32.146) - 1 by 2 by 2 MPI processor grid - reading atoms ... - 864 atoms - 0 = max # of 1-2 neighbors - 0 = max # of 1-3 neighbors - 0 = max # of 1-4 neighbors - 1 = max # of special neighbors - special bonds CPU = 0.000315903 secs - read_data CPU = 0.0653752 secs - -include ff-argon.lmp -############################# -#Atoms types - mass - charge# -############################# -#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# - -variable Ar equal 1 - -############# -#Atom Masses# -############# - -mass ${Ar} 39.903 -mass 1 39.903 - -########################### -#Pair Potentials - Tersoff# -########################### - -pair_style lj/cubic -pair_coeff * * 0.0102701 3.42 - - -velocity all create 10 2357 mom yes dist gaussian - -neighbor 1 bin - -timestep 0.1 - -fix lang all langevin 10 10 1 26488 gjf vhalf -fix nve all nve - -thermo 200 -run 5000 -Neighbor list info ... - update every 1 steps, delay 10 steps, check yes - max neighbors/atom: 2000, page size: 100000 - master list distance cutoff = 6.94072 - ghost atom cutoff = 6.94072 - binsize = 3.47036, bins = 10 10 10 - 1 neighbor lists, perpetual/occasional/extra = 1 0 0 - (1) pair lj/cubic, perpetual - attributes: half, newton on - pair build: half/bin/newton - stencil: half/bin/3d/newton - bin: standard -Per MPI rank memory allocation (min/avg/max) = 6.433 | 6.433 | 6.433 Mbytes -Step Temp E_pair E_mol TotEng Press - 0 11.080228 -56.207655 0 -54.971639 37.215541 - 200 9.8046716 -55.127334 0 -54.033608 329.70647 - 400 10.174622 -55.09236 0 -53.957366 340.49331 - 600 9.9812299 -55.073136 0 -53.959714 345.56477 - 800 10.512874 -55.133382 0 -53.960655 330.4996 - 1000 9.9587885 -55.118463 0 -54.007545 332.24728 - 1200 10.236607 -55.126297 0 -53.984388 330.94998 - 1400 10.134679 -55.123075 0 -53.992537 332.15441 - 1600 9.8934078 -55.153799 0 -54.050174 323.80795 - 1800 10.064966 -55.116698 0 -53.993936 333.59644 - 2000 9.6736107 -55.155825 0 -54.076719 321.5129 - 2200 10.264537 -55.083943 0 -53.938918 343.02135 - 2400 9.5640032 -55.044816 0 -53.977937 351.23099 - 2600 9.6581077 -55.069404 0 -53.992028 344.99996 - 2800 9.9622575 -55.084151 0 -53.972846 342.6574 - 3000 9.8724909 -55.110296 0 -54.009005 334.68094 - 3200 10.032027 -55.123576 0 -54.004488 331.89534 - 3400 10.221132 -55.128925 0 -53.988742 330.24082 - 3600 10.085802 -55.129861 0 -54.004774 330.63601 - 3800 10.098545 -55.099093 0 -53.972585 339.61905 - 4000 10.000257 -55.117782 0 -54.002238 333.24569 - 4200 10.20477 -55.135792 0 -53.997435 329.17565 - 4400 10.545132 -55.096369 0 -53.920044 341.04725 - 4600 10.376108 -55.127213 0 -53.969743 331.92825 - 4800 10.247392 -55.163395 0 -54.020283 322.15219 - 5000 9.7753102 -55.073756 0 -53.983305 343.64146 -Loop time of 1.19785 on 4 procs for 5000 steps with 864 atoms - -Performance: 36064.674 ns/day, 0.001 hours/ns, 4174.152 timesteps/s -88.6% CPU use with 4 MPI tasks x 1 OpenMP threads - -MPI task timing breakdown: -Section | min time | avg time | max time |%varavg| %total ---------------------------------------------------------------- -Pair | 0.36387 | 0.38652 | 0.44086 | 5.1 | 32.27 -Bond | 0.00028847 | 0.00030833 | 0.000338 | 0.0 | 0.03 -Neigh | 0.033934 | 0.034959 | 0.036917 | 0.6 | 2.92 -Comm | 0.39292 | 0.47821 | 0.52198 | 7.3 | 39.92 -Output | 0.00050343 | 0.0012343 | 0.0023338 | 1.9 | 0.10 -Modify | 0.1605 | 0.17963 | 0.19457 | 2.9 | 15.00 -Other | | 0.117 | | | 9.77 - -Nlocal: 216 ave 216 max 216 min -Histogram: 4 0 0 0 0 0 0 0 0 0 -Nghost: 888.75 ave 899 max 876 min -Histogram: 1 0 1 0 0 0 0 0 0 2 -Neighs: 4536 ave 4737 max 4335 min -Histogram: 2 0 0 0 0 0 0 0 0 2 - -Total # of neighbors = 18144 -Ave neighs/atom = 21 -Ave special neighs/atom = 0 -Neighbor list builds = 178 -Dangerous builds = 11 - - -Total wall time: 0:00:01 diff --git a/examples/gjf/log.2Apr25.gjf.vfull.g++.1 b/examples/gjf/log.2Apr25.gjf.vfull.g++.1 new file mode 100644 index 0000000000..a1cb4de702 --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vfull.g++.1 @@ -0,0 +1,152 @@ +LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.000 seconds + read_data CPU = 0.007 seconds + +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian + +neighbor 1 bin + +timestep 0.1 + +fix lang all langevin/gjf 10 10 1 26488 vel vfull method 4 + +thermo 200 +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 + +@Article{gronbech_jensen_2024, +title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, +volume = {191}, +number = {10}, +url = {https://doi.org/10.1007/s10955-024-03345-1}, +doi = {10.1007/s10955-024-03345-1}, +urldate = {2024-10-22}, +journal = {J. Stat. Phys.}, +author = {Gronbech-Jensen, Niels}, +year = {2024}, +pages = {137} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 200 8.3566091 -55.074758 0 -54.142565 340.34804 + 400 8.5550582 -55.098903 0 -54.144573 333.63174 + 600 8.7873675 -55.044559 0 -54.064315 350.7384 + 800 8.7258741 -55.149735 0 -54.17635 318.83613 + 1000 8.3748307 -55.059754 0 -54.125529 343.7989 + 1200 8.6082188 -55.156326 0 -54.196066 316.8728 + 1400 8.9291902 -55.11836 0 -54.122295 328.12488 + 1600 8.3386383 -55.119788 0 -54.189601 325.81369 + 1800 8.0698034 -55.076285 0 -54.176086 338.69767 + 2000 8.5103978 -55.084479 0 -54.135131 338.12197 + 2200 8.3201517 -55.104858 0 -54.176733 329.95905 + 2400 8.7070407 -55.120649 0 -54.149366 328.06488 + 2600 8.4244379 -55.147583 0 -54.207824 321.45013 + 2800 8.7911907 -55.127309 0 -54.146638 325.76049 + 3000 8.250829 -55.1039 0 -54.183508 332.05048 + 3200 8.693979 -55.155552 0 -54.185726 318.29736 + 3400 8.9806023 -55.127303 0 -54.125504 327.48861 + 3600 8.8313967 -55.081076 0 -54.09592 339.16793 + 3800 8.8008688 -55.176748 0 -54.194998 313.08151 + 4000 8.1780418 -55.105368 0 -54.193096 330.04164 + 4200 8.3772045 -55.128813 0 -54.194323 324.29069 + 4400 8.3580983 -55.086979 0 -54.154621 335.63911 + 4600 8.1493124 -55.096648 0 -54.18758 332.51502 + 4800 9.0189389 -55.126828 0 -54.120752 326.36041 + 5000 8.7587383 -55.084993 0 -54.107943 337.17399 +Loop time of 2.34344 on 1 procs for 5000 steps with 864 atoms + +Performance: 18434.456 ns/day, 0.001 hours/ns, 2133.618 timesteps/s, 1.843 Matom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.3044 | 1.3044 | 1.3044 | 0.0 | 55.66 +Bond | 0.00055276 | 0.00055276 | 0.00055276 | 0.0 | 0.02 +Neigh | 0.27376 | 0.27376 | 0.27376 | 0.0 | 11.68 +Comm | 0.055077 | 0.055077 | 0.055077 | 0.0 | 2.35 +Output | 0.00055401 | 0.00055401 | 0.00055401 | 0.0 | 0.02 +Modify | 0.68502 | 0.68502 | 0.68502 | 0.0 | 29.23 +Other | | 0.02412 | | | 1.03 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1593 ave 1593 max 1593 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18143 ave 18143 max 18143 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 257 +Dangerous builds = 0 + + +Total wall time: 0:00:02 diff --git a/examples/gjf/log.2Apr25.gjf.vfull.g++.4 b/examples/gjf/log.2Apr25.gjf.vfull.g++.4 new file mode 100644 index 0000000000..6d9543c087 --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vfull.g++.4 @@ -0,0 +1,152 @@ +LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 2 by 2 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.002 seconds + read_data CPU = 0.014 seconds + +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian + +neighbor 1 bin + +timestep 0.1 + +fix lang all langevin/gjf 10 10 1 26488 vel vfull method 4 + +thermo 200 +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 + +@Article{gronbech_jensen_2024, +title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, +volume = {191}, +number = {10}, +url = {https://doi.org/10.1007/s10955-024-03345-1}, +doi = {10.1007/s10955-024-03345-1}, +urldate = {2024-10-22}, +journal = {J. Stat. Phys.}, +author = {Gronbech-Jensen, Niels}, +year = {2024}, +pages = {137} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.427 | 6.427 | 6.427 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 200 8.3950866 -55.088994 0 -54.15251 334.90536 + 400 8.6408464 -55.090811 0 -54.126912 335.23135 + 600 8.3101447 -55.121286 0 -54.194277 325.43222 + 800 8.5045003 -55.090513 0 -54.141824 335.05857 + 1000 8.7236378 -55.101455 0 -54.12832 331.96596 + 1200 8.7063561 -55.109371 0 -54.138164 331.62683 + 1400 8.7935957 -55.089763 0 -54.108824 336.89842 + 1600 8.454418 -55.105207 0 -54.162104 330.18927 + 1800 8.7989267 -55.142078 0 -54.160544 322.47021 + 2000 8.7823094 -55.153625 0 -54.173945 318.95028 + 2200 8.6201117 -55.11511 0 -54.153524 329.13488 + 2400 9.1165215 -55.161069 0 -54.144107 318.48524 + 2600 8.7636341 -55.142401 0 -54.164805 322.46493 + 2800 8.4876731 -55.111528 0 -54.164715 329.66127 + 3000 8.7005957 -55.149445 0 -54.178881 319.92878 + 3200 8.1711364 -55.137611 0 -54.226108 322.83713 + 3400 8.7172512 -55.143449 0 -54.171026 322.68918 + 3600 8.6262526 -55.1002 0 -54.137928 333.02737 + 3800 8.1680259 -55.166423 0 -54.255267 313.66684 + 4000 8.8340067 -55.121759 0 -54.136312 328.58235 + 4200 8.427926 -55.126903 0 -54.186755 324.95528 + 4400 8.6352614 -55.193826 0 -54.23055 307.14392 + 4600 8.7381405 -55.120503 0 -54.14575 327.73985 + 4800 8.3857194 -55.081944 0 -54.146505 337.38629 + 5000 8.1179517 -55.162247 0 -54.256677 314.50176 +Loop time of 2.08834 on 4 procs for 5000 steps with 864 atoms + +Performance: 20686.324 ns/day, 0.001 hours/ns, 2394.250 timesteps/s, 2.069 Matom-step/s +63.4% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.53532 | 0.5439 | 0.54781 | 0.7 | 26.04 +Bond | 0.0006347 | 0.00066042 | 0.00068198 | 0.0 | 0.03 +Neigh | 0.10879 | 0.11194 | 0.118 | 1.1 | 5.36 +Comm | 0.94935 | 0.96017 | 0.97155 | 0.8 | 45.98 +Output | 0.0060135 | 0.006061 | 0.0061217 | 0.1 | 0.29 +Modify | 0.2483 | 0.24911 | 0.25049 | 0.2 | 11.93 +Other | | 0.2165 | | | 10.37 + +Nlocal: 216 ave 216 max 216 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 884.25 ave 892 max 875 min +Histogram: 1 1 0 0 0 0 0 0 0 2 +Neighs: 4535.5 ave 4737 max 4333 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 18142 +Ave neighs/atom = 20.997685 +Ave special neighs/atom = 0 +Neighbor list builds = 280 +Dangerous builds = 0 + + +Total wall time: 0:00:02 diff --git a/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 b/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 new file mode 100644 index 0000000000..fed8f271e5 --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 @@ -0,0 +1,152 @@ +LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 1 by 1 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.000 seconds + read_data CPU = 0.008 seconds + +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian + +neighbor 1 bin + +timestep 0.1 + +fix lang all langevin/gjf 10 10 1 26488 + +thermo 200 +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 + +@Article{gronbech_jensen_2024, +title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, +volume = {191}, +number = {10}, +url = {https://doi.org/10.1007/s10955-024-03345-1}, +doi = {10.1007/s10955-024-03345-1}, +urldate = {2024-10-22}, +journal = {J. Stat. Phys.}, +author = {Gronbech-Jensen, Niels}, +year = {2024}, +pages = {137} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 200 9.8808461 -55.073599 0 -53.971376 345.62224 + 400 9.8712816 -55.072241 0 -53.971084 345.11909 + 600 10.528988 -55.066736 0 -53.892211 350.60112 + 800 10.167171 -55.148312 0 -54.014149 324.73698 + 1000 10.029026 -55.125705 0 -54.006952 331.93785 + 1200 9.8898479 -55.086642 0 -53.983414 342.04309 + 1400 10.610014 -55.076793 0 -53.89323 346.34338 + 1600 9.9402137 -55.111688 0 -54.002842 335.04779 + 1800 9.8078801 -55.140475 0 -54.046391 325.88652 + 2000 10.472791 -55.06102 0 -53.892765 349.97306 + 2200 9.877248 -55.191201 0 -54.089379 312.77421 + 2400 9.9739487 -55.108904 0 -53.996295 335.9089 + 2600 10.131803 -55.149444 0 -54.019226 325.44115 + 2800 9.6980127 -55.118395 0 -54.036568 331.2097 + 3000 9.7193425 -55.149785 0 -54.065577 323.32384 + 3200 10.27638 -55.083302 0 -53.936957 342.56458 + 3400 9.9253941 -55.082368 0 -53.975175 342.28594 + 3600 10.665862 -55.056774 0 -53.866981 352.03551 + 3800 10.011077 -55.084664 0 -53.967913 341.45122 + 4000 9.4182671 -55.128803 0 -54.078181 327.81846 + 4200 10.02466 -55.106046 0 -53.98778 336.56944 + 4400 9.3721033 -55.146068 0 -54.100596 322.38199 + 4600 9.5485537 -55.118577 0 -54.053421 332.04274 + 4800 10.039726 -55.074068 0 -53.954122 344.76817 + 5000 9.7731898 -55.150518 0 -54.060304 322.94195 +Loop time of 2.28614 on 1 procs for 5000 steps with 864 atoms + +Performance: 18896.448 ns/day, 0.001 hours/ns, 2187.089 timesteps/s, 1.890 Matom-step/s +100.0% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.2918 | 1.2918 | 1.2918 | 0.0 | 56.51 +Bond | 0.00048345 | 0.00048345 | 0.00048345 | 0.0 | 0.02 +Neigh | 0.2776 | 0.2776 | 0.2776 | 0.0 | 12.14 +Comm | 0.055375 | 0.055375 | 0.055375 | 0.0 | 2.42 +Output | 0.00054609 | 0.00054609 | 0.00054609 | 0.0 | 0.02 +Modify | 0.63625 | 0.63625 | 0.63625 | 0.0 | 27.83 +Other | | 0.02408 | | | 1.05 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1593 ave 1593 max 1593 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18143 ave 18143 max 18143 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 258 +Dangerous builds = 0 + + +Total wall time: 0:00:02 diff --git a/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 b/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 new file mode 100644 index 0000000000..aa90fb779b --- /dev/null +++ b/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 @@ -0,0 +1,152 @@ +LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) + using 1 OpenMP thread(s) per MPI task +# GJ thermostat + +units metal +atom_style full + +boundary p p p +read_data argon.lmp +Reading data file ... + orthogonal box = (0 0 0) to (32.146 32.146 32.146) + 1 by 2 by 2 MPI processor grid + reading atoms ... + 864 atoms +Finding 1-2 1-3 1-4 neighbors ... + special bond factors lj: 0 0 0 + special bond factors coul: 0 0 0 + 0 = max # of 1-2 neighbors + 0 = max # of 1-3 neighbors + 0 = max # of 1-4 neighbors + 1 = max # of special neighbors + special bonds CPU = 0.002 seconds + read_data CPU = 0.014 seconds + +include ff-argon.lmp +############################# +#Atoms types - mass - charge# +############################# +#@ 1 atom types #!THIS LINE IS NECESSARY DON'T SPEND HOURS FINDING THAT OUT!# + +variable Ar equal 1 + +############# +#Atom Masses# +############# + +mass ${Ar} 39.903 +mass 1 39.903 + +########################### +#Pair Potentials - Tersoff# +########################### + +pair_style lj/cubic +pair_coeff * * 0.0102701 3.42 + + +velocity all create 10 2357 mom yes dist gaussian + +neighbor 1 bin + +timestep 0.1 + +fix lang all langevin/gjf 10 10 1 26488 + +thermo 200 +run 5000 + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Your simulation uses code contributions which should be cited: + +- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 + +@Article{gronbech_jensen_2024, +title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, +volume = {191}, +number = {10}, +url = {https://doi.org/10.1007/s10955-024-03345-1}, +doi = {10.1007/s10955-024-03345-1}, +urldate = {2024-10-22}, +journal = {J. Stat. Phys.}, +author = {Gronbech-Jensen, Niels}, +year = {2024}, +pages = {137} +} + +CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE + +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Neighbor list info ... + update: every = 1 steps, delay = 0 steps, check = yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.9407173 + ghost atom cutoff = 6.9407173 + binsize = 3.4703587, bins = 10 10 10 + 1 neighbor lists, perpetual/occasional/extra = 1 0 0 + (1) pair lj/cubic, perpetual + attributes: half, newton on + pair build: half/bin/newton + stencil: half/bin/3d + bin: standard +Per MPI rank memory allocation (min/avg/max) = 6.427 | 6.427 | 6.427 Mbytes + Step Temp E_pair E_mol TotEng Press + 0 10 -56.207652 0 -55.092137 33.341103 + 200 9.8046819 -55.12733 0 -54.033603 329.70683 + 400 10.174622 -55.092357 0 -53.957363 340.4935 + 600 9.6157634 -55.174205 0 -54.101552 316.68047 + 800 9.9617862 -55.097525 0 -53.986273 339.257 + 1000 10.373198 -55.116484 0 -53.959338 335.09796 + 1200 10.064779 -55.17366 0 -54.050919 318.66487 + 1400 10.562182 -55.067856 0 -53.889628 349.23452 + 1600 9.7696935 -55.081542 0 -53.991718 342.92593 + 1800 10.454466 -55.130637 0 -53.964426 330.88658 + 2000 10.253701 -55.154093 0 -54.010277 323.15259 + 2200 9.6688957 -55.143479 0 -54.064899 325.16815 + 2400 10.059787 -55.134941 0 -54.012756 329.83534 + 2600 9.9050905 -55.096231 0 -53.991303 338.94947 + 2800 9.663551 -55.130202 0 -54.052218 328.77571 + 3000 9.950484 -55.123447 0 -54.013455 332.00143 + 3200 9.7210637 -55.120005 0 -54.035606 331.39812 + 3400 9.6457139 -55.080953 0 -54.004959 341.95838 + 3600 10.42249 -55.102379 0 -53.939734 339.66808 + 3800 10.276893 -55.126271 0 -53.979868 332.40943 + 4000 10.135481 -55.091551 0 -53.960922 340.60675 + 4200 10.129209 -55.084189 0 -53.95426 343.39315 + 4400 10.006953 -55.120704 0 -54.004413 331.57121 + 4600 10.497483 -55.144898 0 -53.973888 327.22996 + 4800 9.9230954 -55.126028 0 -54.019091 330.70489 + 5000 9.3726166 -55.076514 0 -54.030985 342.43571 +Loop time of 2.0887 on 4 procs for 5000 steps with 864 atoms + +Performance: 20682.713 ns/day, 0.001 hours/ns, 2393.833 timesteps/s, 2.068 Matom-step/s +62.5% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.53905 | 0.54518 | 0.5484 | 0.5 | 26.10 +Bond | 0.00062355 | 0.00066183 | 0.0007207 | 0.0 | 0.03 +Neigh | 0.10715 | 0.10937 | 0.11212 | 0.5 | 5.24 +Comm | 0.94637 | 0.95041 | 0.95905 | 0.5 | 45.50 +Output | 0.0061059 | 0.0061286 | 0.0061661 | 0.0 | 0.29 +Modify | 0.26086 | 0.26355 | 0.26979 | 0.7 | 12.62 +Other | | 0.2134 | | | 10.22 + +Nlocal: 216 ave 216 max 216 min +Histogram: 4 0 0 0 0 0 0 0 0 0 +Nghost: 884.75 ave 885 max 884 min +Histogram: 1 0 0 0 0 0 0 0 0 3 +Neighs: 4536 ave 4737 max 4335 min +Histogram: 2 0 0 0 0 0 0 0 0 2 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 273 +Dangerous builds = 0 + + +Total wall time: 0:00:02 diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp index 59d5cff1c5..95d67fb15f 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.cpp +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -15,17 +15,16 @@ Contributing authors: Tim Linke & Niels Gronbech-Jensen (UC Davis) ------------------------------------------------------------------------- */ -#include "fix_langevin.h" +#include "fix_langevin_gjf.h" #include "atom.h" -#include "atom_vec_ellipsoid.h" +#include "citeme.h" #include "comm.h" #include "compute.h" #include "error.h" #include "force.h" #include "group.h" #include "input.h" -#include "math_extra.h" #include "memory.h" #include "modify.h" #include "random_mars.h" @@ -42,21 +41,33 @@ using namespace FixConst; enum { NOBIAS, BIAS }; enum { CONSTANT, EQUAL, ATOM }; +static const char cite_langevin_gjf[] = + "Langevin GJF methods: doi:10.1007/s10955-024-03345-1\n\n" + "@Article{gronbech_jensen_2024,\n" + "title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations},\n" + "volume = {191},\n" + "number = {10},\n" + "url = {https://doi.org/10.1007/s10955-024-03345-1},\n" + "doi = {10.1007/s10955-024-03345-1},\n" + "urldate = {2024-10-22},\n" + "journal = {J. Stat. Phys.},\n" + "author = {Gronbech-Jensen, Niels},\n" + "year = {2024},\n" + "pages = {137}\n" + "}\n\n"; + + /* ---------------------------------------------------------------------- */ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg), gjfflag(0), - tstr(nullptr), flangevin(nullptr), tforce(nullptr), lv(nullptr), id_temp(nullptr), random(nullptr) + Fix(lmp, narg, arg), tstr(nullptr), tforce(nullptr), lv(nullptr), id_temp(nullptr), random(nullptr) { - if (narg < 8) error->all(FLERR, "Illegal fix langevin/gjf command"); + if (lmp->citeme) lmp->citeme->add(cite_langevin_gjf); + if (narg < 7) error->all(FLERR, "Illegal fix langevin/gjf command"); time_integrate = 1; restart_peratom = 1; - // dynamic_group_allow = 1; - // scalar_flag = 1; - // global_freq = 1; - // extscalar = 1; - // ecouple_flag = 1; + global_freq = 1; nevery = 1; if (utils::strmatch(arg[3], "^v_")) { @@ -75,15 +86,17 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : if (seed <= 0) error->all(FLERR, "Illegal fix langevin/gjf command"); // initialize Marsaglia RNG with processor-unique seed - random = new RanMars(lmp, seed + comm->me); - int GJmethods = 8 // number of currently implemented GJ methods + int GJmethods = 8; // number of currently implemented GJ methods + maxatom = 0; // optional args + // per default, use half step and GJ-I osflag = 0; - GJmethod = 0; + GJmethod = 1; + lv_allocated = 0; int iarg = 7; while (iarg < narg) { @@ -120,7 +133,7 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : FixLangevinGJF::grow_arrays(atom->nmax); atom->add_callback(Atom::GROW); - // initialize lv to zero + // initialize lv to onsite velocity int nlocal = atom->nlocal; for (int i = 0; i < nlocal; i++) { lv[i][0] = 0.0; @@ -181,14 +194,8 @@ void FixLangevinGJF::init() error->all(FLERR, "Variable {} for fix langevin/gjf is invalid style", tstr); } - if (temperature && temperature->tempbias) - tbiasflag = BIAS; - else - tbiasflag = NOBIAS; - if (utils::strmatch(update->integrate_style, "^respa")) { - nlevels_respa = (static_cast(update->integrate))->nlevels; - error->all(FLERR, "Fix langevin gjf and run style respa are not compatible"); + error->all(FLERR, "Fix langevin/gjf and run style respa are not compatible"); } // Complete set of thermostats is given in Gronbech-Jensen, Molecular Physics, 118 (2020) @@ -215,7 +222,7 @@ void FixLangevinGJF::init() gjfc2 = 1; // TODO: correct this break; case 8: // provided in Gronbech-Jensen (2024) - gjfc2 = sqrt( (update->dt / t_period)*(update->dt / t_period) + 1.0 ) - update->dt / t_period; + gjfc2 = sqrt( (update->dt / t_period) * (update->dt / t_period) + 1.0 ) - update->dt / t_period; break; case 0: gjfc2 = 0.0; @@ -239,7 +246,7 @@ void FixLangevinGJF::init() void FixLangevinGJF::initial_integrate(int /* vflag */) { - // This function provides the integration of the GJ formulation 24a-e + // This function provides the integration of the GJ formulation 24 a-e double **x = atom->x; double **v = atom->v; double **f = atom->f; @@ -258,13 +265,13 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) double dtf = 0.5 * dt * ftm2v; double dtfm; - double c1sq = sqrt(gjfc1); - double c3sq = sqrt(gjfc3); + double c1sqrt = sqrt(gjfc1); + double c3sqrt = sqrt(gjfc3); double csq = sqrt(gjfc3 / gjfc1); double m, beta; // If user elected vhalf, v needs to be reassigned to onsite velocity for integration - if (!osflag) { + if (!osflag && lv_allocated) { for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { // lv is Eq. 24f from previous time step @@ -275,8 +282,6 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) } compute_target(); - - if (tbiasflag == BIAS) temperature->compute_scalar(); for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { @@ -284,10 +289,10 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) if (tstyle == ATOM) tsqrt = sqrt(tforce[i]); if (rmass) { m = rmass[i]; - beta = tsqrt * sqrt(2.0*dt*rmass[i]*boltz/t_period/mvv2e) / ftm2v; + beta = tsqrt * sqrt(2.0*dt*m*boltz/t_period/mvv2e) / ftm2v; } else { m = mass[type[i]]; - beta = tsqrt * sqrt(2.0*dt*atom->mass[i]*boltz/t_period/mvv2e) / ftm2v; + beta = tsqrt * sqrt(2.0*dt*m*boltz/t_period/mvv2e) / ftm2v; } fran[0] = beta*random->gaussian(); @@ -304,24 +309,14 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) x[i][2] += 0.5 * csq * dt * v[i][2]; // Calculate Eq. 24c: - if (tbiasflag == BIAS) - temperature->remove_bias(i,v[i]); lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c3sqrt / (2.0 * m)) * fran[0]; lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c3sqrt / (2.0 * m)) * fran[1]; lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c3sqrt / (2.0 * m)) * fran[2]; - if (tbiasflag == BIAS) - temperature->restore_bias(i,v[i]); - if (tbiasflag == BIAS) - temperature->restore_bias(i,lv[i]); - // Calculate Eq. 24d - if (tbiasflag == BIAS) temperature->remove_bias(i, v[i]); - v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * csq * (0.5 / m) * fran[0]; v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * csq * (0.5 / m) * fran[1]; v[i][2] = (gjfc2 / c1sqrt) * lv[i][2] + ftm2v * csq * (0.5 / m) * fran[2]; - if (tbiasflag == BIAS) temperature->restore_bias(i, v[i]); // Calculate Eq. 24e. Final integrator then calculates Eq. 24f after force update. x[i][0] += 0.5 * csq * dt * v[i][0]; @@ -337,9 +332,9 @@ void FixLangevinGJF::final_integrate() double dt = update->dt; double ftm2v = force->ftm2v; double dtf = 0.5 * dt * ftm2v; + double csq = sqrt(gjfc3 / gjfc1); // update v of atoms in group - double **v = atom->v; double **f = atom->f; double *rmass = atom->rmass; @@ -367,6 +362,8 @@ void FixLangevinGJF::final_integrate() v[i][2] += csq * dtfm * f[i][2]; } } + + lv_allocated = 1; } /* ---------------------------------------------------------------------- @@ -395,10 +392,10 @@ void FixLangevinGJF::compute_target() error->one(FLERR, "Fix langevin/gjf variable returned negative temperature"); tsqrt = sqrt(t_target); } else { - if (atom->nmax > maxatom2) { - maxatom2 = atom->nmax; + if (atom->nmax > maxatom) { + maxatom = atom->nmax; memory->destroy(tforce); - memory->create(tforce,maxatom2,"langevin:tforce"); + memory->create(tforce,maxatom,"langevin_gjf:tforce"); } input->variable->compute_atom(tvar,igroup,tforce,1,0); for (int i = 0; i < nlocal; i++) diff --git a/src/EXTRA-FIX/fix_langevin_gjf.h b/src/EXTRA-FIX/fix_langevin_gjf.h index df6b80e1b7..4b65051cf5 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.h +++ b/src/EXTRA-FIX/fix_langevin_gjf.h @@ -13,12 +13,12 @@ #ifdef FIX_CLASS // clang-format off -FixStyle(langevin,FixLangevin); +FixStyle(langevin/gjf,FixLangevinGJF); // clang-format on #else -#ifndef LMP_FIX_LANGEVIN_H -#define LMP_FIX_LANGEVIN_H +#ifndef LMP_FIX_LANGEVINGJF_H +#define LMP_FIX_LANGEVINGJF_H #include "fix.h" @@ -30,7 +30,6 @@ class FixLangevinGJF : public Fix { ~FixLangevinGJF() override; int setmask() override; void init() override; - void setup(int) override; void initial_integrate(int) override; void final_integrate() override; void end_of_step() override; @@ -45,10 +44,8 @@ class FixLangevinGJF : public Fix { int unpack_exchange(int, double *) override; protected: - int osflag, GJmethod; - double t_start, t_stop, t_period, t_target; - double *gfactor2; - double tsqrt; + int osflag, GJmethod, maxatom, lv_allocated; + double t_start, t_stop, t_period, t_target, tsqrt; double gjfc1, gjfc2, gjfc3; int tstyle, tvar; char *tstr; @@ -59,7 +56,6 @@ class FixLangevinGJF : public Fix { char *id_temp; class Compute *temperature; - int nlevels_respa; class RanMars *random; int seed; From 2bb945419012724480e4773e98e191ee53f2d9a2 Mon Sep 17 00:00:00 2001 From: talinke Date: Thu, 10 Apr 2025 13:15:30 -0700 Subject: [PATCH 121/396] Correct style --- doc/src/fix_langevin_gjf.rst | 32 +++++++++++++----------------- src/EXTRA-FIX/fix_langevin_gjf.cpp | 12 +++++------ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/doc/src/fix_langevin_gjf.rst b/doc/src/fix_langevin_gjf.rst index e58b4305bd..a1fcea9c9a 100644 --- a/doc/src/fix_langevin_gjf.rst +++ b/doc/src/fix_langevin_gjf.rst @@ -56,20 +56,20 @@ quadratically with the timestep. The option *vhalf* outputs the have any statistical errors for any stable time step. An overview of statistically correct Boltzmann and Maxwell-Boltzmann sampling of true on-site and true half-step velocities is given in -:ref:`Gronbech-Jensen-2020 `. +:ref:`Gronbech-Jensen-2020 `. -This fix allows the use of any of the GJ methods as listed in :ref:`Gronbech-Jensen-2020 `. -The GJ-VII method is described in :ref:`Finkelstein `. -The implementation follows the splitting form provided in Eqs. (24) and (25) -in :ref:`Gronbech-Jensen-2024 `, including the application -of Gaussian noise values, per the description in +This fix allows the use of any of the GJ methods as listed in :ref:`Gronbech-Jensen-2020 `. +The GJ-VII method is described in :ref:`Finkelstein `. +The implementation follows the splitting form provided in Eqs. (24) and (25) +in :ref:`Gronbech-Jensen-2024 `, including the application +of Gaussian noise values, per the description in :ref:`Gronbech-Jensen-2023 `. .. note:: Unlike the :doc:`fix langevin ` command which performs force - modifications only, this fix performs thermostatting and time integration. + modifications only, this fix performs thermostatting and time integration. Thus you no longer need a separate time integration fix, like :doc:`fix nve `. See the :doc:`Howto thermostat ` page for @@ -138,20 +138,16 @@ The keyword *method* selects one of the eight GJ-methods implemented in LAMMPS. ---------- -.. include:: accel_styles.rst - ----------- - Restart, fix_modify, output, run start/stop, minimize info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" -No information about this fix is written to :doc:`binary restart files `. -Because the state of the random number generator is not saved in restart files, -this means you cannot do "exact" restarts with this fix, where the simulation -continues on the same as if no restart had taken place. However, in a -statistical sense, a restarted simulation should produce the same behavior. -The "exact" restart is done with either vfull or vhalf velocity output for as -long as the choice of vfull/vhalf is the same for the simulation as it is in +No information about this fix is written to :doc:`binary restart files `. +Because the state of the random number generator is not saved in restart files, +this means you cannot do "exact" restarts with this fix, where the simulation +continues on the same as if no restart had taken place. However, in a +statistical sense, a restarted simulation should produce the same behavior. +The "exact" restart is done with either vfull or vhalf velocity output for as +long as the choice of vfull/vhalf is the same for the simulation as it is in the restart file. The :doc:`fix_modify ` *temp* option is supported by this diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp index 95d67fb15f..c1aa3dfac7 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.cpp +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -129,7 +129,7 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : // register with Atom class // no need to set peratom_flag, b/c data is for internal use only - + FixLangevinGJF::grow_arrays(atom->nmax); atom->add_callback(Atom::GROW); @@ -282,12 +282,12 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) } compute_target(); - + for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { if (tstyle == ATOM) tsqrt = sqrt(tforce[i]); - if (rmass) { + if (rmass) { m = rmass[i]; beta = tsqrt * sqrt(2.0*dt*m*boltz/t_period/mvv2e) / ftm2v; } else { @@ -298,7 +298,7 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) fran[0] = beta*random->gaussian(); fran[1] = beta*random->gaussian(); fran[2] = beta*random->gaussian(); - + // First integration delivers Eq. 24a and 24b: dtfm = dtf / m; v[i][0] += csq * dtfm * f[i][0]; @@ -307,12 +307,12 @@ void FixLangevinGJF::initial_integrate(int /* vflag */) x[i][0] += 0.5 * csq * dt * v[i][0]; x[i][1] += 0.5 * csq * dt * v[i][1]; x[i][2] += 0.5 * csq * dt * v[i][2]; - + // Calculate Eq. 24c: lv[i][0] = c1sqrt*v[i][0] + ftm2v * (c3sqrt / (2.0 * m)) * fran[0]; lv[i][1] = c1sqrt*v[i][1] + ftm2v * (c3sqrt / (2.0 * m)) * fran[1]; lv[i][2] = c1sqrt*v[i][2] + ftm2v * (c3sqrt / (2.0 * m)) * fran[2]; - + // Calculate Eq. 24d v[i][0] = (gjfc2 / c1sqrt) * lv[i][0] + ftm2v * csq * (0.5 / m) * fran[0]; v[i][1] = (gjfc2 / c1sqrt) * lv[i][1] + ftm2v * csq * (0.5 / m) * fran[1]; From a5b83224e4a01062ec841d9b5a0b82576824fccf Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 Apr 2025 12:29:03 -0400 Subject: [PATCH 122/396] rephrase to be less ambiguous and provide a couple more details --- doc/src/Errors_details.rst | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/doc/src/Errors_details.rst b/doc/src/Errors_details.rst index 8e12b52114..264e0e2fbb 100644 --- a/doc/src/Errors_details.rst +++ b/doc/src/Errors_details.rst @@ -1007,15 +1007,20 @@ two main advantages: This is controlled by the two parameters "one" and "page", respectively, that can be set via the :doc:`neigh_modify command `. The -parameter "one" is the estimate for the number of entries in a single -neighbor list. The parameter "page" is the size of the page. The -default settings are suitable for most systems. They need to be changed -when simulating a system with a very high density or when setting a very -long cutoff (e.g. :math:`\gtrapprox 15 \AA` with :doc:`units real -`). The value of "page" must be at least 10x the value of "one", -but 50x or 100x are recommended to avoid wasting memory. The neighbor -list storage is typically the largest amount of RAM required by a -LAMMPS calculation. +parameter "one" is the estimate for the maximum number of entries in a +list of neighbors for a single atom. The parameter "page" is the size +of the page. Before determining the neighbors for the next atom, the +neighbor list code checks, if there are "one" entries left in the +current page; if not, a new page is allocated. The error is triggered +when there is not enough space left in the page when adding neighbors. + +The default settings are suitable for most systems. They need to be +changed, for instance, when simulating a system with a very high density +or when setting a very long cutoff (e.g. :math:`\gtrapprox 15 \AA` with +:doc:`units real `). The value of "page" **must** be at least +10x the value of "one", but 50x to 100x are recommended to avoid wasting +memory. The neighbor list storage is typically the largest amount of +RAM required by a LAMMPS calculation. Even though the LAMMPS error message recommends to increase the "one" parameter, this may not be the correct solution. The neighbor list From 190ecd2666cd217e4de7aa63aff4dd6dab0d7bc9 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 Apr 2025 12:34:31 -0400 Subject: [PATCH 123/396] clarify --- doc/src/create_atoms.rst | 4 +++- src/OPENMP/npair_bin_omp.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/src/create_atoms.rst b/doc/src/create_atoms.rst index 2037c15518..6d3604215c 100644 --- a/doc/src/create_atoms.rst +++ b/doc/src/create_atoms.rst @@ -400,7 +400,9 @@ of processors used. The *group* keyword adds the newly created atoms to the named :doc:`group `. If the group does not yet exist it will be -created. All created atoms are always added to the group "all". +created. There can be only one such group, thus if the *group* keyword +is used multiple times, only the last one will be used. All created +atoms are always added to the group "all". The *remap* keyword only applies to the *single* style. If it is set to *yes*, then if the specified position is outside the simulation diff --git a/src/OPENMP/npair_bin_omp.cpp b/src/OPENMP/npair_bin_omp.cpp index 47f9992de0..abc2aafed0 100644 --- a/src/OPENMP/npair_bin_omp.cpp +++ b/src/OPENMP/npair_bin_omp.cpp @@ -209,7 +209,7 @@ void NPairBinOmp::build(NeighList *list) which = find_special(special[i], nspecial[i], tag[j]); else if ((imol >= 0) && onemols[imol]->special) which = find_special(onemols[imol]->special[iatom], - onemols[imol] ->nspecial[iatom], tag[j] - tagprev); + onemols[imol]->nspecial[iatom], tag[j] - tagprev); else which = 0; if (which == 0) From 3810be6c8b57b1685b66ddab1b723c8480d2699f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 Apr 2025 13:59:54 -0400 Subject: [PATCH 124/396] correct / clarify embedded docs --- src/my_page.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/my_page.cpp b/src/my_page.cpp index 88bc522f29..2f55f4f08c 100644 --- a/src/my_page.cpp +++ b/src/my_page.cpp @@ -33,18 +33,17 @@ using namespace LAMMPS_NS; * * The settings *maxchunk*, *pagesize*, and *pagedelta* control * the memory allocation strategy. The *maxchunk* value represents - * the expected largest number of items per chunk. If there is - * less space left on the current page, a new page is allocated - * for the next chunk. The *pagesize* value represents how many - * items can fit on a single page. It should have space for multiple - * chunks of size *maxchunk*. The combination of these two - * parameters determines how much memory is wasted by either switching - * to the next page too soon or allocating too large pages that never - * get properly used. An error is issued if a requested chunk is larger - * than *maxchunk*. The *pagedelta* parameter determines how many - * pages are allocated in one go. In combination with the *pagesize* - * setting, this determines how often blocks of memory get allocated - * (fewer allocations will result in faster execution). + * the largest number of items per chunk allowed; using more will + * trigger an error. If there is less space than *maxchunk* left + * on the current page, a new page is allocated for the next chunk. + * The *pagesize* value represents how many items can fit on a single + * page. It should have space for multiple chunks of size *maxchunk*. + * The combination of these two parameters determines how much memory + * is wasted by either switching to the next page too soon or allocating + * too large pages that never get fully used. The *pagedelta* parameter + * determines how many pages are allocated in one go. In combination + * with the *pagesize* setting, this determines how often blocks of memory + * get allocated (fewer allocations will result in faster execution). * * \note * This is a template class with explicit instantiation. If the class @@ -71,7 +70,7 @@ template MyPage::~MyPage() * This also frees all previously allocated storage and allocates * the first page(s). * - * \param user_maxchunk Expected maximum number of items for one chunk + * \param user_maxchunk Maximum allowed number of items for one chunk * \param user_pagesize Number of items on a single memory page * \param user_pagedelta Number of pages to allocate with one malloc * \return 1 if there were invalid parameters, 2 if there was an allocation error or 0 if successful */ From b8e14cd0c975df07346389e51be153f305105b1c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 Apr 2025 14:00:07 -0400 Subject: [PATCH 125/396] correct and rephrase one more time --- doc/src/Errors_details.rst | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/src/Errors_details.rst b/doc/src/Errors_details.rst index 264e0e2fbb..eba240aef7 100644 --- a/doc/src/Errors_details.rst +++ b/doc/src/Errors_details.rst @@ -1007,12 +1007,11 @@ two main advantages: This is controlled by the two parameters "one" and "page", respectively, that can be set via the :doc:`neigh_modify command `. The -parameter "one" is the estimate for the maximum number of entries in a -list of neighbors for a single atom. The parameter "page" is the size -of the page. Before determining the neighbors for the next atom, the -neighbor list code checks, if there are "one" entries left in the -current page; if not, a new page is allocated. The error is triggered -when there is not enough space left in the page when adding neighbors. +parameter "one" is the maximum number of entries in a list of neighbors +for a single atom. If an atom has more neighbors as the "one" parameter +allows, the "overflow" error message is triggered. The parameter "page" +sets the size of the page. The neighbor list code checks, if there are +"one" entries left in the current page. If not, a new page is allocated. The default settings are suitable for most systems. They need to be changed, for instance, when simulating a system with a very high density @@ -1023,16 +1022,19 @@ memory. The neighbor list storage is typically the largest amount of RAM required by a LAMMPS calculation. Even though the LAMMPS error message recommends to increase the "one" -parameter, this may not be the correct solution. The neighbor list -overflow can be a symptom of some other error that cannot be easily -detected. For example, a frequent reason for an (unexpected) high -density are incorrect box boundaries or coordinates provided as -fractional coordinates. In both cases, LAMMPS cannot easily know +parameter, this may not always be the correct solution. The neighbor +list overflow can also be a symptom for some other error that cannot be +easily detected. For example, a frequent reason for an (unexpected) +high density are incorrect box boundaries (since LAMMPS wraps atoms back +into the principal box with periodic boundaries) or coordinates provided +as fractional coordinates. In both cases, LAMMPS cannot easily know whether the input geometry has such a high density (and thus requiring -more neighbor list storage) intentionally. Rather than blindly -increasing the "one" parameter, it is worth checking if this is +more neighbor list storage per atom) by intention. Rather than blindly +increasing the "one" parameter, it is thus worth checking if this is justified by the combination of density and cutoff. When boosting (= increasing) the "one" parameter, it is recommended to also increase the value for the "page" parameter to maintain the ratio -between "one" and "page". +between "one" and "page" to reduce waste of memory. For some more +details, please check out the documentation for the :doc:`neigh_modify +command `. From a30daec3483d749489e387284186c275fc1b32d3 Mon Sep 17 00:00:00 2001 From: talinke Date: Fri, 11 Apr 2025 13:40:35 -0700 Subject: [PATCH 126/396] Addition of GJ-VII --- src/EXTRA-FIX/fix_langevin_gjf.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp index c1aa3dfac7..f9e523548f 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.cpp +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -66,7 +66,6 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : if (narg < 7) error->all(FLERR, "Illegal fix langevin/gjf command"); time_integrate = 1; - restart_peratom = 1; global_freq = 1; nevery = 1; @@ -219,7 +218,10 @@ void FixLangevinGJF::init() gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); break; case 7: // provided in Finkelstein (2021) - gjfc2 = 1; // TODO: correct this + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); //using GJ-I + gjfc1 = (1.0 + gjfc2) / 2.0; + gjfc3 = (1.0 - gjfc2) * t_period / update->dt; + gjfc2 = exp(-sqrt(gjfc3/gjfc1)*update->dt / t_period); break; case 8: // provided in Gronbech-Jensen (2024) gjfc2 = sqrt( (update->dt / t_period) * (update->dt / t_period) + 1.0 ) - update->dt / t_period; @@ -470,7 +472,10 @@ void FixLangevinGJF::reset_dt() gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); break; case 7: // provided in Finkelstein (2021) - gjfc2 = 1; // TODO: correct this + gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); //using GJ-I + gjfc1 = (1.0 + gjfc2) / 2.0; + gjfc3 = (1.0 - gjfc2) * t_period / update->dt; + gjfc2 = exp(-sqrt(gjfc3/gjfc1)*update->dt / t_period); break; case 8: // provided in Gronbech-Jensen (2024) gjfc2 = sqrt( (update->dt / t_period)*(update->dt / t_period) + 1.0 ) - update->dt / t_period; From 09d3ac0a1bdfa1656329400a72598ece7a008fc6 Mon Sep 17 00:00:00 2001 From: talinke Date: Fri, 11 Apr 2025 20:07:25 -0700 Subject: [PATCH 127/396] Updated GJ-VII, GJ-VIII --- examples/gjf/README | 7 ++- src/EXTRA-FIX/fix_langevin_gjf.cpp | 69 ++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/examples/gjf/README b/examples/gjf/README index fdbc843522..c22df903e7 100644 --- a/examples/gjf/README +++ b/examples/gjf/README @@ -33,14 +33,13 @@ POTENTIAL ENERGY (eV) Script Commands: -- +fix lang all langevin/gjf 10 10 1 26488 +vs +-- fix nve all nve fix lang all langevin 10 10 1 26488 -- vs -- fix noho all nvt temp 10 10 1 --- -vs --- -fix lang all langevin/gjf 10 10 1 26488 -- \ No newline at end of file diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp index f9e523548f..c00fbb9ee5 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.cpp +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -41,8 +41,37 @@ using namespace FixConst; enum { NOBIAS, BIAS }; enum { CONSTANT, EQUAL, ATOM }; + static const char cite_langevin_gjf[] = - "Langevin GJF methods: doi:10.1007/s10955-024-03345-1\n\n" + "Langevin GJ methods: doi:10.1080/00268976.2019.1662506\n\n" + "@Article{gronbech-jensen_complete_2020,\n" + "title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations},\n" + "volume = {118},\n" + "number = {8},\n" + "url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506},\n" + "doi = {10.1080/00268976.2019.1662506},\n" + "journal = {Molecular Physics},\n" + "author = {Grønbech-Jensen, Niels},\n" + "year = {2020},\n" + "}\n\n"; + +static const char cite_langevin_gjf_7[] = + "Langevin GJ-VII method: doi:10.1063/5.0066008\n\n" + "@Article{finkelstein_2021,\n" + "title = {Bringing discrete-time Langevin splitting methods into agreement with thermodynamics},\n" + "volume = {155},\n" + "number = {18},\n" + "url = {https://doi.org/10.1063/5.0066008},\n" + "doi = {10.1063/5.0066008},\n" + "urldate = {2021-11-14},\n" + "journal = {J. Chem. Phys.},\n" + "author = {Finkelstein, Joshua and Cheng, Chungho and Fiorin, Giacomo and Seibold, Benjamin and Grønbech-Jensen, Niels},\n" + "year = {2021},\n" + "pages = {184104}\n" + "}\n\n"; + +static const char cite_langevin_gjf_8[] = + "Langevin GJ-VIII method: doi:10.1007/s10955-024-03345-1\n\n" "@Article{gronbech_jensen_2024,\n" "title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations},\n" "volume = {191},\n" @@ -55,7 +84,7 @@ static const char cite_langevin_gjf[] = "year = {2024},\n" "pages = {137}\n" "}\n\n"; - + /* ---------------------------------------------------------------------- */ @@ -109,10 +138,20 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR, "Illegal fix langevin/gjf command"); iarg += 2; } else if (strcmp(arg[iarg], "method") == 0) { - if (iarg + 2 > narg) error->all(FLERR, "Illegal fix langevin/gjf command"); GJmethod = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); - if (GJmethod < 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in langevin/gjf command"); - iarg += 2; + if (GJmethod = 7) { + if (iarg + 3 > narg) error->all(FLERR, "Illegal fix langevin/gjf command for GJ-VII"); + gjfc2 = utils::numeric(FLERR, arg[iarg + 2], false, lmp); + if (gjfc2 < 0 || gjfc2 > 1) error->all(FLERR, "Choice of c2 in GJ-VII must be 0≤c2≤1"); + iarg += 3; + if (lmp->citeme) lmp->citeme->add(cite_langevin_gjf_7); + } + else { + if (iarg + 2 > narg) error->all(FLERR, "Illegal fix langevin/gjf command"); + if (GJmethod < 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in langevin/gjf command"); + if (GJmethod = 8) if (lmp->citeme) lmp->citeme->add(cite_langevin_gjf_8); + iarg += 2; + } } else error->all(FLERR, "Illegal fix langevin/gjf command"); } @@ -218,10 +257,7 @@ void FixLangevinGJF::init() gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); break; case 7: // provided in Finkelstein (2021) - gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); //using GJ-I - gjfc1 = (1.0 + gjfc2) / 2.0; - gjfc3 = (1.0 - gjfc2) * t_period / update->dt; - gjfc2 = exp(-sqrt(gjfc3/gjfc1)*update->dt / t_period); + update->dt = (1.0 + gjfc2) / (1.0 - gjfc2) * log(gjfc2) * log(gjfc2) * 0.5 * t_period; break; case 8: // provided in Gronbech-Jensen (2024) gjfc2 = sqrt( (update->dt / t_period) * (update->dt / t_period) + 1.0 ) - update->dt / t_period; @@ -238,11 +274,11 @@ void FixLangevinGJF::init() } /* ---------------------------------------------------------------------- - integrate position and velocity according to the GJF method + integrate position and velocity according to the GJ methods in Grønbech-Jensen, J Stat Phys 191, 137 (2024). The general workflow is - 1. Langevin GJF Initial Integration + 1. Langevin GJ Initial Integration 2. Force Update - 3. Langevin GJF Final Integration + 3. Langevin GJ Final Integration 4. Velocity Choice in end_of_step() ------------------------------------------------------------------------- */ @@ -336,7 +372,6 @@ void FixLangevinGJF::final_integrate() double dtf = 0.5 * dt * ftm2v; double csq = sqrt(gjfc3 / gjfc1); - // update v of atoms in group double **v = atom->v; double **f = atom->f; double *rmass = atom->rmass; @@ -346,6 +381,7 @@ void FixLangevinGJF::final_integrate() int nlocal = atom->nlocal; if (igroup == atom->firstgroup) nlocal = atom->nfirst; + // Calculate Eq. 24f. if (rmass) { for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { @@ -410,7 +446,7 @@ void FixLangevinGJF::compute_target() } /* ---------------------------------------------------------------------- - select velocity for GJF + select velocity for GJ ------------------------------------------------------------------------- */ void FixLangevinGJF::end_of_step() @@ -472,10 +508,7 @@ void FixLangevinGJF::reset_dt() gjfc2 = (1.0 / (1.0 + update->dt / 2.0 / t_period)) * (1.0 / (1.0 + update->dt / 2.0 / t_period)); break; case 7: // provided in Finkelstein (2021) - gjfc2 = (1.0 - update->dt / 2.0 / t_period) / (1.0 + update->dt / 2.0 / t_period); //using GJ-I - gjfc1 = (1.0 + gjfc2) / 2.0; - gjfc3 = (1.0 - gjfc2) * t_period / update->dt; - gjfc2 = exp(-sqrt(gjfc3/gjfc1)*update->dt / t_period); + update->dt = (1.0 + gjfc2) / (1.0 - gjfc2) * log(gjfc2) * log(gjfc2) * 0.5 * t_period; break; case 8: // provided in Gronbech-Jensen (2024) gjfc2 = sqrt( (update->dt / t_period)*(update->dt / t_period) + 1.0 ) - update->dt / t_period; From ed1f4cc3812b0e64346b1d4722c7085f027279f4 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 Apr 2025 23:25:56 -0400 Subject: [PATCH 128/396] add functionality to edit the plot title and x- and y-axis labels --- doc/src/Howto_lammps_gui.rst | 9 ++++- doc/src/JPG/lammps-gui-chart.png | Bin 108113 -> 117336 bytes tools/lammps-gui/TODO.md | 1 - tools/lammps-gui/chartviewer.cpp | 65 +++++++++++++++++++++++++++++-- tools/lammps-gui/chartviewer.h | 9 +++++ 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index 53d890ea7e..25478069c7 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -350,8 +350,13 @@ data or both. The smoothing uses a `Savitzky-Golay convolution filter window width (left) and order (right) parameters can be set in the boxes next to the drop down menu. Default settings are 10 and 4 which means that the smoothing window includes 10 points each to the left and the -right of the current data point and a fourth order polynomial is fit to -the data in the window. +right of the current data point for a total of 21 points and a fourth +order polynomial is fitted to the data in the window. + +With the "Title:", "X:", and "Y:" boxes you can edit the text shown as +the plot title and the x- or y-axis labels, respectively. The "Title:" +and "X:" text is applied to *all* charts, while the "Y:" text *only* to +the y-axis of the currently selected plot. You can use the mouse to zoom into the graph (hold the left button and drag to mark an area) or zoom out (right click) and you can reset the diff --git a/doc/src/JPG/lammps-gui-chart.png b/doc/src/JPG/lammps-gui-chart.png index 5a926a721b6c465417f3fe386fa284a1bf382ce1..db9b6ca636f419dc41d7cf32e26bb1f0ee5c5394 100644 GIT binary patch literal 117336 zcmXtf1ymbdv~{3Rthl=sr?|UAae@_hcXxMM+`YKFyA`+MF2y}SaQ*YW_x`oAR+70h zlQZ|8dt~pOC}l-yWJCf)004meT}A>30KhN+0G|-xp&>_#tr?mjZ!i|33Zei&eH_xO z5iI08g{$NbS5*gdR}Uj+Gr$iGGIuj)7b^#QGA zR8q8vyZAw0T*)ErtktYXnCZaTDs4ZJtfzNG+S!NS%)lO*I;e|yDy{oiy)$XDN@P>A`u?*BE=PvMD`RkVL$nf&AQ zur!3(*-9{%NEPZ1+Uk~$Bk}k5cW&=$+C%#vD*(say}d4IV%dXn-yM7n7PZ9S)p^CB z0JKnIQ1Hs}EOf(e^?33SeTm=#7I>xTDPv_ zhpW(H2?+^#cW;f1l>V6yQ^(%mg-_rSHq9Wa+2%cOx#g&&En=@y#QGJg0(}60M@t3r z50**x_to{NO~RMy%TWwz;lK-Gz(bJ%77o}`LIUETYVmEyXxytlY?gCF;80PBciJ>C~&F;fhyx+!P*YSPRMflBS;u0QJ` zge@C_o~D`d8oC7V`2k_Cl!%DQXwV!-iSP^-q<`|d-CaxR1naft)B8i%S_FZUe<8YK%12UPpzYslapm>4 zFT3yKl}5ETHamQNGR_?~#MV&RpU_j2qw+E`STM2VUl|xCZ0pO^=*!il$}QP4AX9tG zm!nb2j`u}`oagHg>LkIh{d(UK75mw=*f8zy5a8d01pg6Ne}FN5bo);YwY5>2P~WDE z+vxoAS$xh9-{QMKv@+IBDoG zzD!&{9azg`vf24O>hM5XPQqmbubjw_`V*l1yGCj96M#kB^rz8SE6Rw0P@CgFvC2gP zLc+77BTdUt9%xa>lXQ)mHx`$cvVTE`kx`IawB(2(;MS;IWSqEx2GyI5O_wGSB4~BSD z7QOkmRwi7wOOL`?8LufWXvPh(clBz_UD1PE@p4-^26bbG{S=|oKv_qTB%Zk2}5=^Y`Mn}#6zl7H;=Q-@pGDg{teoF)Z**50kC zG%MCt7<@!rzeA0wFr{e_V^4;z^wH(fuhmn;b{*NJy<Crf+)5gPXQ zMmO98GaO4fIlAMP}yOHWZsub1I`#zyClx>)9F#Qt!QIm`$V(4Gkd^aFqQOg^v~aFD5$VC!3p@ zsnBDH&CRn12U~O4EXgyasmjt7i@=LV_6Bfv>j%8QJ~b`e{{Bq{2|D#Z)acby;5;ay z0F9gm+$+}X#Z+CTm0XMIJ-~nS*Yh)%g2J=c=joWLitY)cVs@#jvI?52hf*=ykCVx@ zZ^1$hE>ZTZ`$jMkGEk9*a)LSLHN}aY?n{yMbqYh^@^4P>BKt7SZ2) zzYrGki`ega3a33|ztpe*0Lv2cciB`21urMFT?D)CWA2d!#H1f64niz%eIZ|$N))QiT~gZ6h`NmEB1hTL;JKXFYVgyzad&o4ty-^thrZ!jI4sJTD{5w0B+9_P*a-U!N@3 z=EcRu>1hAoHXZus=!l|7os_}G23fu&Y6W<5$ToE&PBpVxsKJkB)KhNPNUUV&my;Xom(CCOzKW zZGocl;K<>H3HRRccTqo+jLl9S>@j3XcJ^vny~jumT>Y(Y9R30Y3BTmVU;?_a03v9U zsle*bfIb%M?c_Jl(SDE$QXYWJF0^0b6kM-D*_|%4CS}4lkl?#=*b#=3qu};~ zOg>A7PFTJ6e5!rVAZxHT2>;IO@{*;Bf@!9;lS7H7E|YUYOdzbHL)DBIXD2KeU{I1` z8Q!((=8E?TOCo4Sc0$1G>gGn!Dg!I9`u=s~;^lePrIU$DQljN&yn!xw=FXlt7r_ib zR;B|g+!W#1@cwvXFkT)u;rqNa*BC3mw0yA9zw(*Cz4PN|{o8k6+m2$A2 zl=x))iEZtlgNM`h96sur?@ppP%0A}+^{=vRUNNSk;)|E{(Zl^wqdobeV^_I}15cw! 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 z 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 zΜ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 Q{}{2dl1dU~;;#b!4;5$0a{vGU literal 108113 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≤G4H6kEP`OMhez@9V7y^TYk!$&HEmlc?EKAHxQef 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 N0m%e?`2D4jKLLDD;1&P? diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index 996ab43a93..fdfded613b 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -9,7 +9,6 @@ LAMMPS-GUI TODO list: - default smooth parameters - default plot colors - enable "raw" or "smooth" or "both" -- add QLineEdit fields to enter plot title, axis labels and units - add a "Colors" menu to the image viewer to adjust color settings for the current image (unlike the defaults in the perferences) including assigning colors to individual atom types. diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index 8543da166a..ac8266bbbe 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -46,7 +46,8 @@ using namespace QtCharts; ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), saveAsAct(nullptr), exportCsvAct(nullptr), exportDatAct(nullptr), exportYamlAct(nullptr), closeAct(nullptr), - stopAct(nullptr), quitAct(nullptr), filename(_filename) + stopAct(nullptr), quitAct(nullptr), smooth(nullptr), window(nullptr), order(nullptr), + chartTitle(nullptr), chartXlabel(nullptr), chartYlabel(nullptr), filename(_filename) { auto *top = new QHBoxLayout; menu->addMenu(file); @@ -56,6 +57,13 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : auto *dummy = new QPushButton(QIcon(), ""); dummy->hide(); + // plot title and axis labels + + chartTitle = new QLineEdit(QString("Thermo: %1").arg(filename)); + chartXlabel = new QLineEdit("Time step"); + chartYlabel = new QLineEdit(""); + + // plot smoothing do_raw = true; do_smooth = true; smooth = new QComboBox; @@ -82,6 +90,12 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : top->addWidget(menu); top->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum)); top->addWidget(dummy); + top->addWidget(new QLabel("Title:")); + top->addWidget(chartTitle); + top->addWidget(new QLabel("X:")); + top->addWidget(chartXlabel); + top->addWidget(new QLabel("Y:")); + top->addWidget(chartYlabel); top->addWidget(new QLabel("Plot:")); top->addWidget(smooth); top->addWidget(new QLabel(" Smooth:")); @@ -113,6 +127,9 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : layout->addLayout(top); setLayout(layout); + connect(chartTitle, &QLineEdit::editingFinished, this, &ChartWindow::update_labels); + connect(chartXlabel, &QLineEdit::editingFinished, this, &ChartWindow::update_labels); + connect(chartYlabel, &QLineEdit::editingFinished, this, &ChartWindow::update_ylabel); connect(smooth, SIGNAL(currentIndexChanged(int)), this, SLOT(select_smooth(int))); connect(window, &QAbstractSpinBox::editingFinished, this, &ChartWindow::update_smooth); connect(order, &QAbstractSpinBox::editingFinished, this, &ChartWindow::update_smooth); @@ -160,8 +177,15 @@ void ChartWindow::add_chart(const QString &title, int index) columns->addItem(title, index); columns->show(); // hide all but the first chart added - if (charts.size() > 0) chart->hide(); + if (charts.size() > 0) { + chart->hide(); + } else { + // must initialize QLineEdit with first title + // will be automatically updated when changing charts. + chartYlabel->setText(title); + } charts.append(chart); + update_labels(); } void ChartWindow::add_data(int step, double data, int index) @@ -226,6 +250,19 @@ void ChartWindow::update_smooth() c->smooth_param(do_raw, do_smooth, wval, oval); } +void ChartWindow::update_labels() +{ + for (auto &c : charts) + c->set_labels(chartTitle->text(), chartXlabel->text()); +} + +void ChartWindow::update_ylabel() +{ + for (auto &c : charts) { + if (c->isVisible()) c->set_ylabel(chartYlabel->text()); + } +} + void ChartWindow::saveAs() { if (charts.empty()) return; @@ -343,10 +380,14 @@ void ChartWindow::change_chart(int) { int choice = columns->currentData().toInt(); for (auto &c : charts) { - if (choice == c->get_index()) + if (choice == c->get_index()) { c->show(); - else + chartTitle->setText(c->get_tlabel()); + chartXlabel->setText(c->get_xlabel()); + chartYlabel->setText(c->get_ylabel()); + } else { c->hide(); + } } } @@ -390,6 +431,7 @@ ChartViewer::ChartViewer(const QString &title, int _index, QWidget *parent) : chart->legend()->hide(); chart->addAxis(xaxis, Qt::AlignBottom); chart->addAxis(yaxis, Qt::AlignLeft); + chart->setTitle("Thermo Output"); xaxis->setTitleText("Time step"); xaxis->setTickCount(5); xaxis->setLabelFormat("%d"); @@ -516,6 +558,21 @@ void ChartViewer::smooth_param(bool _do_raw, bool _do_smooth, int _window, int _ /* -------------------------------------------------------------------- */ +void ChartViewer::set_labels(const QString &tlabel, const QString &xlabel) +{ + chart->setTitle(tlabel); + xaxis->setTitleText(xlabel); +} + +/* -------------------------------------------------------------------- */ + +void ChartViewer::set_ylabel(const QString &ylabel) +{ + yaxis->setTitleText(ylabel); +} + +/* -------------------------------------------------------------------- */ + // update smooth plot data static QList calc_sgsmooth(const QList &input, const int window, const int order); diff --git a/tools/lammps-gui/chartviewer.h b/tools/lammps-gui/chartviewer.h index 28915d24e3..6e7274fdc4 100644 --- a/tools/lammps-gui/chartviewer.h +++ b/tools/lammps-gui/chartviewer.h @@ -15,6 +15,7 @@ #define CHARTVIEWER_H #include +#include #include #include #include @@ -52,6 +53,8 @@ private slots: void stop_run(); void select_smooth(int selection); void update_smooth(); + void update_labels(); + void update_ylabel(); void saveAs(); void exportDat(); @@ -73,6 +76,7 @@ private: QAction *closeAct, *stopAct, *quitAct; QComboBox *smooth; QSpinBox *window, *order; + QLineEdit *chartTitle, *chartXlabel, *chartYlabel; QString filename; QList charts; @@ -103,6 +107,11 @@ public: QString get_title() const { return series->name(); } double get_step(int index) const { return (index < 0) ? 0.0 : series->at(index).x(); } double get_data(int index) const { return (index < 0) ? 0.0 : series->at(index).y(); } + void set_labels(const QString &tlabel, const QString &xlabel); + void set_ylabel(const QString &ylabel); + QString get_tlabel() const { return chart->title(); } + QString get_xlabel() const { return xaxis->titleText(); } + QString get_ylabel() const { return yaxis->titleText(); } private: int last_step, index; From 2dd53c440eb74dfe2b37e9794d8fa739f7b13105 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 11 Apr 2025 23:26:43 -0400 Subject: [PATCH 129/396] Add mini ToC for HowTo only and reorganize the introduction --- doc/src/Howto_github.rst | 4 ++ doc/src/Howto_lammps_gui.rst | 90 +++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 37 deletions(-) diff --git a/doc/src/Howto_github.rst b/doc/src/Howto_github.rst index b53a2edbc7..e95e1cca9d 100644 --- a/doc/src/Howto_github.rst +++ b/doc/src/Howto_github.rst @@ -498,3 +498,7 @@ systems. Some unit and regression testing is applied as well. A detailed discussion of the LAMMPS developer GitHub workflow can be found in the file `doc/github-development-workflow.md `_ + +.. raw:: latex + + \clearpage diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index 25478069c7..456c6bf3f1 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -1,36 +1,25 @@ Using LAMMPS-GUI ================ +LAMMPS-GUI is a graphical text editor programmed using the `Qt Framework +`_ and customized for editing LAMMPS input files. It +is linked to the :ref:`LAMMPS library ` and thus can run +LAMMPS directly using the contents of the editor's text buffer as input. + +It *differs* from other known interfaces to LAMMPS in that it can +retrieve and display information from LAMMPS *while it is running*, +display visualizations created with the :doc:`dump image command +`, can launch the online LAMMPS documentation for known +LAMMPS commands and styles, and directly integrates with a collection +of LAMMPS tutorials (:ref:`Gravelle1 `). + This document describes **LAMMPS-GUI version 1.6**. ----- -LAMMPS-GUI is a graphical text editor customized for editing LAMMPS -input files that is linked to the :ref:`LAMMPS library ` -and thus can run LAMMPS directly using the contents of the editor's text -buffer as input. It can retrieve and display information from LAMMPS -while it is running, display visualizations created with the :doc:`dump -image command `, and is adapted specifically for editing -LAMMPS input files through text completion and reformatting, and linking -to the online LAMMPS documentation for known LAMMPS commands and styles. +.. contents:: -.. note:: - - Pre-compiled, ready-to-use LAMMPS-GUI executables for Linux x86\_64 - (Ubuntu 20.04LTS or later and compatible), macOS (version 11 aka Big - Sur or later), and Windows (version 10 or later) :ref:`are available - ` for download. Non-MPI LAMMPS executables (as - ``lmp``) for running LAMMPS from the command-line and :doc:`some - LAMMPS tools ` compiled executables are also included. Also, - the pre-compiled LAMMPS-GUI packages include the WHAM executables - from http://membrane.urmc.rochester.edu/content/wham/ for use with - LAMMPS tutorials documented in this paper (:ref:`Gravelle1 - `). - - The source code for LAMMPS-GUI is included in the LAMMPS source code - distribution and can be found in the ``tools/lammps-gui`` folder. It - can be compiled alongside LAMMPS when :doc:`compiling with CMake - `. +---- LAMMPS-GUI tries to provide an experience similar to what people traditionally would have running LAMMPS using a command-line window and @@ -65,8 +54,8 @@ simple LAMMPS simulations. It is very suitable for tutorials on LAMMPS since you only need to learn how to use a single program for most tasks and thus time can be saved and people can focus on learning LAMMPS. The tutorials at https://lammpstutorials.github.io/ are specifically -updated for use with LAMMPS-GUI and can their tutorial materials can -be downloaded and loaded directly from the GUI. +updated for use with LAMMPS-GUI and their tutorial materials can +be downloaded and edited directly from the GUI. Another design goal is to keep the barrier low when replacing part of the functionality of LAMMPS-GUI with external tools. That said, LAMMPS-GUI @@ -79,10 +68,31 @@ has some unique functionality that is not found elsewhere: - monitoring of simulation progress - interactive visualization using the :doc:`dump image ` command with the option to copy-paste the resulting settings -- automatic slide show generation from dump image out at runtime -- automatic plotting of thermodynamics data at runtime +- automatic slide show generation from dump image output at runtime +- automatic plotting of thermodynamic data at runtime - inspection of binary restart files +.. admonition:: Download LAMMPS-GUI for your platform + :class: Hint + + Pre-compiled, ready-to-use LAMMPS-GUI executables for Linux x86\_64 + (Ubuntu 20.04LTS or later and compatible), macOS (version 11 aka Big + Sur or later), and Windows (version 10 or later) :ref:`are available + ` for download. Non-MPI LAMMPS executables (as + ``lmp``) for running LAMMPS from the command-line and :doc:`some + LAMMPS tools ` compiled executables are also included. Also, + the pre-compiled LAMMPS-GUI packages include the WHAM executables + from http://membrane.urmc.rochester.edu/content/wham/ for use with + LAMMPS tutorials documented in this paper (:ref:`Gravelle1 + `). + + The source code for LAMMPS-GUI is included in the LAMMPS source code + distribution and can be found in the ``tools/lammps-gui`` folder. It + can be compiled alongside LAMMPS when :doc:`compiling with CMake + `. + +----- + The following text provides a detailed tour of the features and functionality of LAMMPS-GUI. Suggestions for new features and reports of bugs are always welcome. You can use the :doc:`the same @@ -93,9 +103,11 @@ channels as for LAMMPS itself ` for that purpose. Installing Pre-compiled LAMMPS-GUI Packages ------------------------------------------- -LAMMPS-GUI is available as pre-compiled binary packages for Linux -x86\_64, macOS 11 and later, and Windows 10 and later. Alternately, it -can be compiled from source. +LAMMPS-GUI is available for download as pre-compiled binary packages for +Linux x86\_64, macOS 11 and later, and Windows 10 and later from the +`LAMMPS release pages on GitHub `_. +A backup download location is at https://download.lammps.org/static/ +Alternately, LAMMPS-GUI can be compiled from source when building LAMMPS. Windows 10 and later ^^^^^^^^^^^^^^^^^^^^ @@ -467,11 +479,11 @@ correspond to (via their mass) and then colorize them in the image and set their atom diameters accordingly. If this is not possible, for instance when using reduced (= 'lj') :doc:`units `, then LAMMPS-GUI will check the current pair style and if it is a -Lennard-Jones type potential, it will extract the *sigma* parameter -for each atom type and assign atom diameters from those numbers. -For cases where atom diameters are not auto-detected, the *Atom size* field -can be edited and a suitable value set manually. The default value -is inferred from the x-direction lattice spacing. +Lennard-Jones type potential, it will extract the *sigma* parameter for +each atom type and assign atom diameters from those numbers. For cases +where atom diameters are not auto-detected, the *Atom size* field can be +edited and a suitable value set manually. The default value is inferred +from the x-direction lattice spacing. If elements cannot be detected the default sequence of colors of the :doc:`dump image ` command is assigned to the different atom @@ -1027,3 +1039,7 @@ Window), and `Ctrl-Q` (Quit Application) are supported. .. _Gravelle2: **(Gravelle2)** Gravelle https://lammpstutorials.github.io/ + +.. raw:: latex + + \clearpage From d0c356421651fa601571013267937641526b541d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 12 Apr 2025 00:53:45 -0400 Subject: [PATCH 130/396] update TODO list --- tools/lammps-gui/TODO.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index fdfded613b..e4218646d6 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -2,8 +2,6 @@ LAMMPS-GUI TODO list: # Short term goals (v1.x) -- implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences. -- add a "Filter data" checkbox to the "Charts" window to select whether data should be dropped. - add a "Charts tab" to the preferences with the following (default) settings: - default filter data yes/no - default smooth parameters @@ -14,10 +12,7 @@ LAMMPS-GUI TODO list: colors to individual atom types. - Support color by property (e.g. scan computes or fixes with per-atom data), define colormaps etc. - Add a "Diameters" dialog where diamaters can by specified by atom type -- figure out how widgets can be resized to fraction of available screen size. -- figure out stacking order of frames and whether it can be more flexible -- implement indenting regions for (nested) loops? - implement data file manager GUI with the following features: - import coordinates and topology via VMD molfile plugins - import coordinates and topology from intermol From 1ad2df84d86dbd804794360dafbd700338dae79f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 12 Apr 2025 06:49:44 -0400 Subject: [PATCH 131/396] add checkbox to automatically open tutorial website, if available --- doc/src/Howto_lammps_gui.rst | 17 ++++---- tools/lammps-gui/lammps-gui.appdata.xml | 2 + tools/lammps-gui/lammpsgui.cpp | 54 +++++++++++++++++++++++-- tools/lammps-gui/lammpsgui.h | 3 +- 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index 456c6bf3f1..3e56bd4756 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -752,13 +752,16 @@ Tutorials The *Tutorials* menu is to support the set of LAMMPS tutorials for beginners and intermediate LAMMPS users documented in (:ref:`Gravelle1 -`). From the drop down menu you can select which of the eight -currently available tutorial sessions you want to start and then will be -taken to a 'wizard' dialog where you can choose in which folder you want -to work, whether you want that folder to be cleared, and also whether -you want to download the solutions files (can be large). The dialog -will then start downloading the files requested and load the first input -file for the selected session into LAMMPS-GUI. +`). From the drop down menu you can select which of the +eight currently available tutorial sessions you want to start and then +will be taken to a 'wizard' dialog where you can choose in which folder +you want to work, whether you want that folder to be wiped from *any* +files, whether you want to download the solutions files (which can be +large) to a ``solution`` sub-folder, and whether you want the +corresponding tutorial's online version opened in your web browser. The +dialog will then start downloading the files requested (download +progress is reported in the status line) and load the first input file +for the selected session into LAMMPS-GUI. About ^^^^^ diff --git a/tools/lammps-gui/lammps-gui.appdata.xml b/tools/lammps-gui/lammps-gui.appdata.xml index 898966dccc..c1e54880b0 100644 --- a/tools/lammps-gui/lammps-gui.appdata.xml +++ b/tools/lammps-gui/lammps-gui.appdata.xml @@ -60,6 +60,8 @@ Change working directory to user's home dir if initial directory is "/" or the Application folder Add preferences option to set https proxy, if not already set via environment variable Add option to visualize molecules defined through the molecule command + Add text fields for editing plot title and axis labels for charts + Add option to automatically open tutorial websites (enabled by default) diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index 09a180683d..d515e8df78 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -1617,7 +1617,7 @@ QWizardPage *LammpsGui::tutorial_directory(const int ntutorial) "created if necessary and LAMMPS-GUI will download the files required for the " "tutorial. If selected, an existing directory may be cleared from old " "files.

\n

Available files of the tutorial solution may be downloaded to a " - "sub-folder \"solution\", if requested.

\n") + "sub-folder called \"solution\", if requested.

\n") .arg(ntutorial)); label->setWordWrap(true); @@ -1657,6 +1657,7 @@ QWizardPage *LammpsGui::tutorial_directory(const int ntutorial) auto *solval = new QCheckBox; auto *purgelabel = new QLabel("Remove existing files from directory"); auto *sollabel = new QLabel("Download solutions"); + purgeval->setCheckState(Qt::Unchecked); purgeval->setObjectName("t_dirpurge"); solval->setCheckState(Qt::Unchecked); @@ -1668,6 +1669,18 @@ QWizardPage *LammpsGui::tutorial_directory(const int ntutorial) grid->setColumnStretch(0, 0); grid->setColumnStretch(1, 100); + // we have tutorials 1 to 7 currently available online + + QCheckBox *webval = nullptr; + if ((ntutorial > 0) && (ntutorial < 8)) { + grid->addWidget(new QLabel, 2, 0, 1, 2, Qt::AlignVCenter); + webval = new QCheckBox; + webval->setCheckState(Qt::Checked); + webval->setObjectName("t_webopen"); + grid->addWidget(webval, 3, 0, Qt::AlignVCenter); + grid->addWidget(new QLabel("Open tutorial webpage in web browser"), 3, 1, Qt::AlignVCenter); + } + auto *label2 = new QLabel( QString("
\n

Click on " "the \"Finish\" button to complete the setup and start the download.

")); @@ -2008,7 +2021,8 @@ static const QString geturl = "geturl https://raw.githubusercontent.com/lammpstutorials/" "lammpstutorials-article/refs/heads/main/files/tutorial%1/%2 output %2 verify no"; -void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, bool getsolution) +void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, bool getsolution, + bool openwebpage) { constexpr int BUFLEN = 1024; char errorbuf[BUFLEN]; @@ -2023,6 +2037,36 @@ void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, boo QDir directory(dir); directory.cd(dir); + if (openwebpage) { + QString weburl = "https://lammpstutorials.github.io/sphinx/build/html/tutorial%1/%2.html"; + switch (tutno) { + case 1: + weburl = weburl.arg(tutno).arg("lennard-jones-fluid"); + break; + case 2: + weburl = weburl.arg(tutno).arg("breaking-a-carbon-nanotube"); + break; + case 3: + weburl = weburl.arg(tutno).arg("polymer-in-water"); + break; + case 4: + weburl = weburl.arg(tutno).arg("nanosheard-electrolyte"); + break; + case 5: + weburl = weburl.arg(tutno).arg("reactive-silicon-dioxide"); + break; + case 6: + weburl = weburl.arg(tutno).arg("water-adsorption-in-silica"); + break; + case 7: + weburl = weburl.arg(tutno).arg("free-energy-calculation"); + break; + default: + weburl = "https://lammpstutorials.github.io/"; + } + QDesktopServices::openUrl(QUrl(weburl)); + } + if (purgedir) purge_directory(dir); if (getsolution) directory.mkpath("solution"); @@ -2138,10 +2182,14 @@ void TutorialWizard::accept() auto *dirname = findChild("t_directory"); auto *dirpurge = findChild("t_dirpurge"); auto *getsol = findChild("t_getsolution"); + auto *webopen = findChild("t_webopen"); bool purgedir = false; bool getsolution = false; + bool openwebpage = false; QString curdir; + if (webopen) openwebpage = (webopen->checkState() == Qt::Checked); + // create and populate directory. if (dirname) { QDir directory; @@ -2165,7 +2213,7 @@ void TutorialWizard::accept() LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - if (main) main->setup_tutorial(_ntutorial, curdir, purgedir, getsolution); + if (main) main->setup_tutorial(_ntutorial, curdir, purgedir, getsolution, openwebpage); } } diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index 38fe00607e..4966522cea 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -85,7 +85,8 @@ protected: void setFont(const QFont &newfont); QWizardPage *tutorial_intro(const int ntutorial, const QString &infotext); QWizardPage *tutorial_directory(const int ntutorial); - void setup_tutorial(int ntutorial, const QString &dir, bool purgedir, bool getsolution); + void setup_tutorial(int ntutorial, const QString &dir, bool purgedir, bool getsolution, + bool openwebpage); void purge_inspect_list(); bool eventFilter(QObject *watched, QEvent *event) override; From bb090887317c862497963e8de6f1fb206f334d13 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 12 Apr 2025 11:49:41 -0400 Subject: [PATCH 132/396] add new tab to preferences for charts window settings --- tools/lammps-gui/TODO.md | 5 -- tools/lammps-gui/chartviewer.cpp | 36 +++++++++---- tools/lammps-gui/preferences.cpp | 92 +++++++++++++++++++++++++++++++- tools/lammps-gui/preferences.h | 10 ++++ 4 files changed, 128 insertions(+), 15 deletions(-) diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index e4218646d6..1871c1b0aa 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -2,11 +2,6 @@ LAMMPS-GUI TODO list: # Short term goals (v1.x) -- add a "Charts tab" to the preferences with the following (default) settings: - - default filter data yes/no - - default smooth parameters - - default plot colors - - enable "raw" or "smooth" or "both" - add a "Colors" menu to the image viewer to adjust color settings for the current image (unlike the defaults in the perferences) including assigning colors to individual atom types. diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index ac8266bbbe..6c7bafc58f 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -49,6 +49,7 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : stopAct(nullptr), quitAct(nullptr), smooth(nullptr), window(nullptr), order(nullptr), chartTitle(nullptr), chartXlabel(nullptr), chartYlabel(nullptr), filename(_filename) { + QSettings settings; auto *top = new QHBoxLayout; menu->addMenu(file); menu->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); @@ -58,30 +59,47 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : dummy->hide(); // plot title and axis labels - - chartTitle = new QLineEdit(QString("Thermo: %1").arg(filename)); - chartXlabel = new QLineEdit("Time step"); + settings.beginGroup("charts"); + chartTitle = + new QLineEdit(settings.value("title", "Thermo: %f").toString().replace("%f", filename)); + chartXlabel = new QLineEdit(settings.value("xlabel", "Time step").toString()); chartYlabel = new QLineEdit(""); // plot smoothing - do_raw = true; - do_smooth = true; + int smoothchoice = settings.value("smoothchoice",2).toInt(); + switch (smoothchoice) { + case 0: + do_raw = true; + do_smooth = false; + break; + case 1: + do_raw = false; + do_smooth = true; + break; + case 2: // fallthrough + default: + do_raw = true; + do_smooth = true; + break; + } + // list of choices must be kepy in sync with list in preferences smooth = new QComboBox; smooth->addItem("Raw"); smooth->addItem("Smooth"); smooth->addItem("Both"); - smooth->setCurrentIndex(2); + smooth->setCurrentIndex(smoothchoice); smooth->show(); window = new QSpinBox; window->setRange(5, 999); - window->setValue(10); + window->setValue(settings.value("smoothwindow", 10).toInt()); window->setEnabled(true); window->setToolTip("Smoothing Window Size"); order = new QSpinBox; order->setRange(1, 20); - order->setValue(4); + order->setValue(settings.value("smoothorder", 4).toInt()); order->setEnabled(true); order->setToolTip("Smoothing Order"); + settings.endGroup(); auto *normal = new QPushButton(QIcon(":/icons/gtk-zoom-fit.png"), ""); normal->setToolTip("Reset zoom to normal"); @@ -139,7 +157,6 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : connect(columns, SIGNAL(currentIndexChanged(int)), this, SLOT(change_chart(int))); installEventFilter(this); - QSettings settings; resize(settings.value("chartx", 500).toInt(), settings.value("charty", 320).toInt()); } @@ -186,6 +203,7 @@ void ChartWindow::add_chart(const QString &title, int index) } charts.append(chart); update_labels(); + select_smooth(0); } void ChartWindow::add_data(int step, double data, int index) diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index aba3d9d61c..4b59e6c155 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -67,6 +67,7 @@ Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) : tabWidget->addTab(new AcceleratorTab(settings, lammps), "&Accelerators"); tabWidget->addTab(new SnapshotTab(settings), "&Snapshot Image"); tabWidget->addTab(new EditorTab(settings), "&Editor Settings"); + tabWidget->addTab(new ChartsTab(settings), "Cha&rts Settings"); connect(buttonBox, &QDialogButtonBox::accepted, this, &Preferences::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); @@ -77,7 +78,7 @@ Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) : setLayout(layout); setWindowIcon(QIcon(":/icons/lammps-icon-128x128.png")); setWindowTitle("LAMMPS-GUI - Preferences"); - resize(600, 450); + resize(700, 500); } Preferences::~Preferences() @@ -207,6 +208,25 @@ void Preferences::accept() if (box) settings->setValue("autosave", box->isChecked()); settings->endGroup(); + // chart window settings + + settings->beginGroup("charts"); + field = tabWidget->findChild("title"); + if (field) settings->setValue("title", field->text()); + field = tabWidget->findChild("xlabel"); + if (field) settings->setValue("xlabel", field->text()); + combo = tabWidget->findChild("smoothchoice"); + if (combo) settings->setValue("smoothchoice", combo->currentIndex()); + spin = tabWidget->findChild("smoothwindow"); + if (spin) settings->setValue("smoothwindow", spin->value()); + spin = tabWidget->findChild("smoothorder"); + if (spin) settings->setValue("smoothorder", spin->value()); + settings->endGroup(); + spin = tabWidget->findChild("chartx"); + if (spin) settings->setValue("chartx", spin->value()); + spin = tabWidget->findChild("charty"); + if (spin) settings->setValue("charty", spin->value()); + QDialog::accept(); } @@ -622,6 +642,7 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s grid->addWidget(retval, i++, 1, Qt::AlignVCenter); grid->addWidget(autolbl, i, 0, Qt::AlignTop); grid->addWidget(autoval, i++, 1, Qt::AlignVCenter); + grid->addWidget(new QLabel(" "), i++, 0); grid->addWidget(savlbl, i, 0, Qt::AlignTop); grid->addWidget(savval, i++, 1, Qt::AlignVCenter); @@ -631,6 +652,75 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s setLayout(grid); } +ChartsTab::ChartsTab(QSettings *_settings, QWidget *parent) : QWidget(parent), settings(_settings) +{ + auto *grid = new QGridLayout; + auto *chartlbl = new QLabel("Charts default settings:"); + + settings->beginGroup("charts"); + auto *titlelbl = new QLabel("Default chart title:"); + auto *titletxt = new QLineEdit(settings->value("title", "Thermo: %f").toString()); + auto *titlehlp = new QLabel("(use %f for current input file)"); + + auto *xlabellbl = new QLabel("Default x-axis label:"); + auto *xlabeltxt = new QLineEdit(settings->value("xlabel", "Time step").toString()); + + // list of choices must be kepy in sync with list in chartviewer + auto *smoothlbl = new QLabel("Default plot data choice:"); + auto *smoothval = new QComboBox; + smoothval->addItem("Raw"); + smoothval->addItem("Smooth"); + smoothval->addItem("Both"); + smoothval->setObjectName("smoothchoice"); + smoothval->setCurrentIndex(settings->value("smoothchoice", 2).toInt()); + + auto *smwindlbl = new QLabel("Default smoothing window:"); + auto *smwindval = new QSpinBox; + smwindval->setRange(5, 999); + smwindval->setValue(settings->value("smoothwindow", 10).toInt()); + smwindval->setObjectName("smoothwindow"); + + auto *smordrlbl = new QLabel("Default smoothing order:"); + auto *smordrval = new QSpinBox; + smordrval->setRange(1, 20); + smordrval->setValue(settings->value("smoothorder", 4).toInt()); + smordrval->setObjectName("smoothorder"); + settings->endGroup(); + + auto *chartxlbl = new QLabel("Chart default width:"); + auto *chartxval = new QSpinBox; + chartxval->setRange(400, 40000); + chartxval->setValue(settings->value("chartx", 500).toInt()); + chartxval->setObjectName("chartx"); + auto *chartylbl = new QLabel("Chart default height:"); + auto *chartyval = new QSpinBox; + chartyval->setRange(300, 30000); + chartyval->setValue(settings->value("charty", 320).toInt()); + chartyval->setObjectName("charty"); + + int i = 0; + grid->addWidget(chartlbl, i++, 0, 1, 2, Qt::AlignTop | Qt::AlignHCenter); + grid->addWidget(titlelbl, i, 0, Qt::AlignTop); + grid->addWidget(titletxt, i, 1, Qt::AlignTop); + grid->addWidget(titlehlp, i++, 2, Qt::AlignTop); + grid->addWidget(xlabellbl, i, 0, Qt::AlignTop); + grid->addWidget(xlabeltxt, i++, 1, Qt::AlignTop); + grid->addWidget(smoothlbl, i, 0, Qt::AlignTop); + grid->addWidget(smoothval, i++, 1, Qt::AlignTop); + grid->addWidget(smwindlbl, i, 0, Qt::AlignTop); + grid->addWidget(smwindval, i++, 1, Qt::AlignTop); + grid->addWidget(smordrlbl, i, 0, Qt::AlignTop); + grid->addWidget(smordrval, i++, 1, Qt::AlignVCenter); + grid->addWidget(chartxlbl, i, 0, Qt::AlignTop); + grid->addWidget(chartxval, i++, 1, Qt::AlignVCenter); + grid->addWidget(chartylbl, i, 0, Qt::AlignTop); + grid->addWidget(chartyval, i++, 1, Qt::AlignVCenter); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 0); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 1); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), i, 2); + setLayout(grid); +} + // Local Variables: // c-basic-offset: 4 // End: diff --git a/tools/lammps-gui/preferences.h b/tools/lammps-gui/preferences.h index 44ff5b8951..cf2fe4653f 100644 --- a/tools/lammps-gui/preferences.h +++ b/tools/lammps-gui/preferences.h @@ -93,6 +93,16 @@ private: QSettings *settings; }; +class ChartsTab : public QWidget { + Q_OBJECT + +public: + explicit ChartsTab(QSettings *settings, QWidget *parent = nullptr); + +private: + QSettings *settings; +}; + #endif // Local Variables: From 1eb61936ab716d86f7d55418c7e897f691c5e651 Mon Sep 17 00:00:00 2001 From: Jacob Gissinger Date: Sun, 13 Apr 2025 12:56:01 -0400 Subject: [PATCH 133/396] refactor reaction counting previously, the rate_limit keyword did not work when also creating atoms --- src/REACTION/fix_bond_react.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/REACTION/fix_bond_react.cpp b/src/REACTION/fix_bond_react.cpp index 0a6ed3e34a..b70092296f 100644 --- a/src/REACTION/fix_bond_react.cpp +++ b/src/REACTION/fix_bond_react.cpp @@ -1475,15 +1475,14 @@ void FixBondReact::superimpose_algorithm() int rxnflag = 0; int *delta_rxn; - memory->create(delta_rxn,nreacts,"bond/react:delta_rxn"); + memory->create(delta_rxn, nreacts, "bond/react:delta_rxn"); if (comm->me == 0) for (int i = 0; i < nreacts; i++) { delta_rxn[i] = reaction_count[i] + ghostly_rxn_count[i]; - reaction_count_total[i] += delta_rxn[i]; rxnflag += delta_rxn[i]; } - MPI_Bcast(&reaction_count_total[0], nreacts, MPI_INT, 0, world); + MPI_Bcast(&delta_rxn[0], nreacts, MPI_INT, 0, world); MPI_Bcast(&rxnflag, 1, MPI_INT, 0, world); if (!rxnflag) return; @@ -1495,12 +1494,12 @@ void FixBondReact::superimpose_algorithm() // check if we overstepped our reaction limit, via either max_rxn or rate_limit for (int i = 0; i < nreacts; i++) { int overstep = 0; - int max_rxn_overstep = reaction_count_total[i] - max_rxn[i]; + int max_rxn_overstep = reaction_count_total[i] + delta_rxn[i] - max_rxn[i]; overstep = MAX(overstep,max_rxn_overstep); if (rate_limit[0][i] == 1) { int myrxn_count = store_rxn_count[rate_limit[2][i]-1][i]; if (myrxn_count != -1) { - int nrxn_delta = reaction_count_total[i] - myrxn_count; + int nrxn_delta = reaction_count_total[i] + delta_rxn[i] - myrxn_count; int my_nrate; if (var_flag[NRATE][i] == 1) { my_nrate = input->variable->compute_equal(var_id[NRATE][i]); @@ -1540,7 +1539,6 @@ void FixBondReact::superimpose_algorithm() else all_localkeep[rxn_by_proc[j]]++; } memory->destroy(rxn_by_proc); - reaction_count_total[i] -= overstep; } MPI_Scatter(&all_localkeep[0],1,MPI_INT,&nlocalkeep[i],1,MPI_INT,0,world); MPI_Bcast(&nghostlykeep[i],1,MPI_INT,0,world); @@ -1548,7 +1546,6 @@ void FixBondReact::superimpose_algorithm() memory->destroy(all_localkeep); } } - MPI_Bcast(&reaction_count_total[0], nreacts, MPI_INT, 0, world); memory->destroy(delta_rxn); // this updates topology next step @@ -3103,18 +3100,16 @@ void FixBondReact::update_everything() if (create_atoms_flag[rxnID] == 1) { onemol = atom->molecules[unreacted_mol[rxnID]]; twomol = atom->molecules[reacted_mol[rxnID]]; - if (insert_atoms_setup(update_mega_glove,update_num_mega)) { - inserted_atoms_flag = 1; - } else { // create aborted - reaction_count_total[rxnID]--; - continue; - } + if (insert_atoms_setup(update_mega_glove,update_num_mega)) inserted_atoms_flag = 1; + else continue; } noccur[rxnID]++; if (rescale_charges_flag[rxnID]) sim_total_charges[update_num_mega] = local_mega_glove[1][i]; update_num_mega++; } + MPI_Allreduce(MPI_IN_PLACE, &noccur[0], nreacts, MPI_INT, MPI_SUM, world); + reaction_count_total[rxnID] += noccur[rxnID]; } else if (pass == 1) { for (int i = 0; i < global_megasize; i++) { rxnID = (int) global_mega_glove[0][i]; @@ -3129,17 +3124,15 @@ void FixBondReact::update_everything() // we can insert atoms here, now that reactions are finalized // can't do it any earlier, due to skipped reactions (max_rxn) // for MPI build, reactions that create atoms are always treated as 'global' + if (create_atoms_flag[rxnID] == 1) { onemol = atom->molecules[unreacted_mol[rxnID]]; twomol = atom->molecules[reacted_mol[rxnID]]; - if (insert_atoms_setup(update_mega_glove,update_num_mega)) { - inserted_atoms_flag = 1; - } else { // create aborted - reaction_count_total[rxnID]--; - continue; - } + if (insert_atoms_setup(update_mega_glove,update_num_mega)) inserted_atoms_flag = 1; + else continue; } noccur[rxnID]++; + reaction_count_total[rxnID]++; if (rescale_charges_flag[rxnID]) sim_total_charges[update_num_mega] = global_mega_glove[1][i]; update_num_mega++; From f181ca6aec0da0ea17d131fc15bf1da6488d8e63 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 13 Apr 2025 16:56:21 -0400 Subject: [PATCH 134/396] support setting graph colors in preferences --- tools/lammps-gui/chartviewer.cpp | 53 ++++++++++++++++++++++---------- tools/lammps-gui/preferences.cpp | 30 +++++++++++++++++- 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index 6c7bafc58f..15bcd5d77b 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,16 @@ using namespace QtCharts; +// brush color index must be kept in sync with preferences + +static const QList mybrushes = { + QBrush(QColor(0, 0, 0)), // black + QBrush(QColor(100, 150, 255)), // blue + QBrush(QColor(255, 125, 125)), // red + QBrush(QColor(100, 200, 100)), // green + QBrush(QColor(120, 120, 120)), // grey +}; + ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), saveAsAct(nullptr), exportCsvAct(nullptr), exportDatAct(nullptr), exportYamlAct(nullptr), closeAct(nullptr), @@ -66,24 +77,24 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : chartYlabel = new QLineEdit(""); // plot smoothing - int smoothchoice = settings.value("smoothchoice",2).toInt(); + int smoothchoice = settings.value("smoothchoice", 2).toInt(); switch (smoothchoice) { - case 0: - do_raw = true; - do_smooth = false; - break; - case 1: - do_raw = false; - do_smooth = true; - break; - case 2: // fallthrough - default: - do_raw = true; - do_smooth = true; - break; + case 0: + do_raw = true; + do_smooth = false; + break; + case 1: + do_raw = false; + do_smooth = true; + break; + case 2: // fallthrough + default: + do_raw = true; + do_smooth = true; + break; } // list of choices must be kepy in sync with list in preferences - smooth = new QComboBox; + smooth = new QComboBox; smooth->addItem("Raw"); smooth->addItem("Smooth"); smooth->addItem("Both"); @@ -597,11 +608,19 @@ static QList calc_sgsmooth(const QList &input, const int windo void ChartViewer::update_smooth() { + QSettings settings; + settings.beginGroup("charts"); + int rawidx = settings.value("rawbrush", 1).toInt(); + int smoothidx = settings.value("smoothbrush", 2).toInt(); + if ((rawidx < 0) || (rawidx >= mybrushes.size())) rawidx = 0; + if ((smoothidx < 0) || (smoothidx >= mybrushes.size())) smoothidx = 0; + settings.endGroup(); + auto allseries = chart->series(); if (do_raw) { // add raw data if not in chart if (!allseries.contains(series)) { - series->setPen(QPen(QBrush(QColor(100, 150, 255)), 3, Qt::SolidLine, Qt::RoundCap)); + series->setPen(QPen(mybrushes[rawidx], 3, Qt::SolidLine, Qt::RoundCap)); chart->addSeries(series); series->attachAxis(xaxis); series->attachAxis(yaxis); @@ -612,7 +631,7 @@ void ChartViewer::update_smooth() if (series->count() > (2 * window)) { if (!smooth) { smooth = new QLineSeries; - smooth->setPen(QPen(QBrush(QColor(255, 125, 125)), 3, Qt::SolidLine, Qt::RoundCap)); + smooth->setPen(QPen(mybrushes[smoothidx], 3, Qt::SolidLine, Qt::RoundCap)); chart->addSeries(smooth); smooth->attachAxis(xaxis); smooth->attachAxis(yaxis); diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index 4b59e6c155..6b0d3f796f 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -217,6 +217,10 @@ void Preferences::accept() if (field) settings->setValue("xlabel", field->text()); combo = tabWidget->findChild("smoothchoice"); if (combo) settings->setValue("smoothchoice", combo->currentIndex()); + combo = tabWidget->findChild("rawbrush"); + if (combo) settings->setValue("rawbrush", combo->currentIndex()); + combo = tabWidget->findChild("smoothbrush"); + if (combo) settings->setValue("smoothbrush", combo->currentIndex()); spin = tabWidget->findChild("smoothwindow"); if (spin) settings->setValue("smoothwindow", spin->value()); spin = tabWidget->findChild("smoothorder"); @@ -308,7 +312,7 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa auto https_proxy = QString::fromLocal8Bit(qgetenv("https_proxy")); if (https_proxy.isEmpty()) { - https_proxy = settings->value("https_proxy", "").toString(); + https_proxy = settings->value("https_proxy", "").toString(); auto *proxyedit = new QLineEdit(https_proxy); proxyedit->setObjectName("proxyval"); gridlayout->addWidget(proxyedit, 3, 1); @@ -674,6 +678,26 @@ ChartsTab::ChartsTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s smoothval->setObjectName("smoothchoice"); smoothval->setCurrentIndex(settings->value("smoothchoice", 2).toInt()); + auto *rawbrlbl = new QLabel("Raw plot color:"); + auto *rawbrush = new QComboBox; + rawbrush->addItem("Black"); + rawbrush->addItem("Blue"); + rawbrush->addItem("Red"); + rawbrush->addItem("Green"); + rawbrush->addItem("Gray"); + rawbrush->setObjectName("rawbrush"); + rawbrush->setCurrentIndex(settings->value("rawbrush", 1).toInt()); + + auto *smoothbrlbl = new QLabel("Smooth plot color:"); + auto *smoothbrush = new QComboBox; + smoothbrush->addItem("Black"); + smoothbrush->addItem("Blue"); + smoothbrush->addItem("Red"); + smoothbrush->addItem("Green"); + smoothbrush->addItem("Gray"); + smoothbrush->setObjectName("smoothbrush"); + smoothbrush->setCurrentIndex(settings->value("smoothbrush", 2).toInt()); + auto *smwindlbl = new QLabel("Default smoothing window:"); auto *smwindval = new QSpinBox; smwindval->setRange(5, 999); @@ -707,6 +731,10 @@ ChartsTab::ChartsTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s grid->addWidget(xlabeltxt, i++, 1, Qt::AlignTop); grid->addWidget(smoothlbl, i, 0, Qt::AlignTop); grid->addWidget(smoothval, i++, 1, Qt::AlignTop); + grid->addWidget(rawbrlbl, i, 0, Qt::AlignTop); + grid->addWidget(rawbrush, i++, 1, Qt::AlignTop); + grid->addWidget(smoothbrlbl, i, 0, Qt::AlignTop); + grid->addWidget(smoothbrush, i++, 1, Qt::AlignTop); grid->addWidget(smwindlbl, i, 0, Qt::AlignTop); grid->addWidget(smwindval, i++, 1, Qt::AlignTop); grid->addWidget(smordrlbl, i, 0, Qt::AlignTop); From 0bab80a26ef1ac44d0b6ca13611886b8541baf1f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 13 Apr 2025 19:33:07 -0400 Subject: [PATCH 135/396] not much use for editing x axis label. better give more space to other options --- tools/lammps-gui/chartviewer.cpp | 20 +++++++------------- tools/lammps-gui/chartviewer.h | 6 +++--- tools/lammps-gui/lammps-gui.appdata.xml | 1 + tools/lammps-gui/preferences.cpp | 7 ------- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index 15bcd5d77b..211371e7a6 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -58,7 +58,7 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), saveAsAct(nullptr), exportCsvAct(nullptr), exportDatAct(nullptr), exportYamlAct(nullptr), closeAct(nullptr), stopAct(nullptr), quitAct(nullptr), smooth(nullptr), window(nullptr), order(nullptr), - chartTitle(nullptr), chartXlabel(nullptr), chartYlabel(nullptr), filename(_filename) + chartTitle(nullptr), chartYlabel(nullptr), filename(_filename) { QSettings settings; auto *top = new QHBoxLayout; @@ -73,7 +73,6 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : settings.beginGroup("charts"); chartTitle = new QLineEdit(settings.value("title", "Thermo: %f").toString().replace("%f", filename)); - chartXlabel = new QLineEdit(settings.value("xlabel", "Time step").toString()); chartYlabel = new QLineEdit(""); // plot smoothing @@ -121,8 +120,6 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : top->addWidget(dummy); top->addWidget(new QLabel("Title:")); top->addWidget(chartTitle); - top->addWidget(new QLabel("X:")); - top->addWidget(chartXlabel); top->addWidget(new QLabel("Y:")); top->addWidget(chartYlabel); top->addWidget(new QLabel("Plot:")); @@ -156,8 +153,7 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : layout->addLayout(top); setLayout(layout); - connect(chartTitle, &QLineEdit::editingFinished, this, &ChartWindow::update_labels); - connect(chartXlabel, &QLineEdit::editingFinished, this, &ChartWindow::update_labels); + connect(chartTitle, &QLineEdit::editingFinished, this, &ChartWindow::update_tlabel); connect(chartYlabel, &QLineEdit::editingFinished, this, &ChartWindow::update_ylabel); connect(smooth, SIGNAL(currentIndexChanged(int)), this, SLOT(select_smooth(int))); connect(window, &QAbstractSpinBox::editingFinished, this, &ChartWindow::update_smooth); @@ -213,7 +209,7 @@ void ChartWindow::add_chart(const QString &title, int index) chartYlabel->setText(title); } charts.append(chart); - update_labels(); + update_tlabel(); select_smooth(0); } @@ -279,10 +275,10 @@ void ChartWindow::update_smooth() c->smooth_param(do_raw, do_smooth, wval, oval); } -void ChartWindow::update_labels() +void ChartWindow::update_tlabel() { for (auto &c : charts) - c->set_labels(chartTitle->text(), chartXlabel->text()); + c->set_tlabel(chartTitle->text()); } void ChartWindow::update_ylabel() @@ -412,7 +408,6 @@ void ChartWindow::change_chart(int) if (choice == c->get_index()) { c->show(); chartTitle->setText(c->get_tlabel()); - chartXlabel->setText(c->get_xlabel()); chartYlabel->setText(c->get_ylabel()); } else { c->hide(); @@ -460,7 +455,7 @@ ChartViewer::ChartViewer(const QString &title, int _index, QWidget *parent) : chart->legend()->hide(); chart->addAxis(xaxis, Qt::AlignBottom); chart->addAxis(yaxis, Qt::AlignLeft); - chart->setTitle("Thermo Output"); + chart->setTitle(""); xaxis->setTitleText("Time step"); xaxis->setTickCount(5); xaxis->setLabelFormat("%d"); @@ -587,10 +582,9 @@ void ChartViewer::smooth_param(bool _do_raw, bool _do_smooth, int _window, int _ /* -------------------------------------------------------------------- */ -void ChartViewer::set_labels(const QString &tlabel, const QString &xlabel) +void ChartViewer::set_tlabel(const QString &tlabel) { chart->setTitle(tlabel); - xaxis->setTitleText(xlabel); } /* -------------------------------------------------------------------- */ diff --git a/tools/lammps-gui/chartviewer.h b/tools/lammps-gui/chartviewer.h index 6e7274fdc4..e3be90bd3c 100644 --- a/tools/lammps-gui/chartviewer.h +++ b/tools/lammps-gui/chartviewer.h @@ -53,7 +53,7 @@ private slots: void stop_run(); void select_smooth(int selection); void update_smooth(); - void update_labels(); + void update_tlabel(); void update_ylabel(); void saveAs(); @@ -76,7 +76,7 @@ private: QAction *closeAct, *stopAct, *quitAct; QComboBox *smooth; QSpinBox *window, *order; - QLineEdit *chartTitle, *chartXlabel, *chartYlabel; + QLineEdit *chartTitle, *chartYlabel; QString filename; QList charts; @@ -107,7 +107,7 @@ public: QString get_title() const { return series->name(); } double get_step(int index) const { return (index < 0) ? 0.0 : series->at(index).x(); } double get_data(int index) const { return (index < 0) ? 0.0 : series->at(index).y(); } - void set_labels(const QString &tlabel, const QString &xlabel); + void set_tlabel(const QString &tlabel); void set_ylabel(const QString &ylabel); QString get_tlabel() const { return chart->title(); } QString get_xlabel() const { return xaxis->titleText(); } diff --git a/tools/lammps-gui/lammps-gui.appdata.xml b/tools/lammps-gui/lammps-gui.appdata.xml index c1e54880b0..460e47f509 100644 --- a/tools/lammps-gui/lammps-gui.appdata.xml +++ b/tools/lammps-gui/lammps-gui.appdata.xml @@ -62,6 +62,7 @@ Add option to visualize molecules defined through the molecule command Add text fields for editing plot title and axis labels for charts Add option to automatically open tutorial websites (enabled by default) + Add preferences tab for charts to set default for title, plot colors, smooth/raw plot, smooth params
diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index 6b0d3f796f..6eba1ed19d 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -213,8 +213,6 @@ void Preferences::accept() settings->beginGroup("charts"); field = tabWidget->findChild("title"); if (field) settings->setValue("title", field->text()); - field = tabWidget->findChild("xlabel"); - if (field) settings->setValue("xlabel", field->text()); combo = tabWidget->findChild("smoothchoice"); if (combo) settings->setValue("smoothchoice", combo->currentIndex()); combo = tabWidget->findChild("rawbrush"); @@ -666,9 +664,6 @@ ChartsTab::ChartsTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s auto *titletxt = new QLineEdit(settings->value("title", "Thermo: %f").toString()); auto *titlehlp = new QLabel("(use %f for current input file)"); - auto *xlabellbl = new QLabel("Default x-axis label:"); - auto *xlabeltxt = new QLineEdit(settings->value("xlabel", "Time step").toString()); - // list of choices must be kepy in sync with list in chartviewer auto *smoothlbl = new QLabel("Default plot data choice:"); auto *smoothval = new QComboBox; @@ -727,8 +722,6 @@ ChartsTab::ChartsTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s grid->addWidget(titlelbl, i, 0, Qt::AlignTop); grid->addWidget(titletxt, i, 1, Qt::AlignTop); grid->addWidget(titlehlp, i++, 2, Qt::AlignTop); - grid->addWidget(xlabellbl, i, 0, Qt::AlignTop); - grid->addWidget(xlabeltxt, i++, 1, Qt::AlignTop); grid->addWidget(smoothlbl, i, 0, Qt::AlignTop); grid->addWidget(smoothval, i++, 1, Qt::AlignTop); grid->addWidget(rawbrlbl, i, 0, Qt::AlignTop); From 31df721767878592f580dd94d4871467a5f09506 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 13 Apr 2025 20:01:06 -0400 Subject: [PATCH 136/396] update documentation --- doc/src/Howto_lammps_gui.rst | 38 +++++++++++++++++------ doc/src/JPG/lammps-gui-chart.png | Bin 117336 -> 119499 bytes doc/src/JPG/lammps-gui-prefs-accel.png | Bin 32436 -> 32179 bytes doc/src/JPG/lammps-gui-prefs-charts.png | Bin 0 -> 49977 bytes doc/src/JPG/lammps-gui-prefs-editor.png | Bin 39899 -> 39716 bytes doc/src/JPG/lammps-gui-prefs-general.png | Bin 60580 -> 58345 bytes doc/src/JPG/lammps-gui-prefs-image.png | Bin 44816 -> 45180 bytes 7 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 doc/src/JPG/lammps-gui-prefs-charts.png diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index 3e56bd4756..44ec9c9e16 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -365,10 +365,10 @@ that the smoothing window includes 10 points each to the left and the right of the current data point for a total of 21 points and a fourth order polynomial is fitted to the data in the window. -With the "Title:", "X:", and "Y:" boxes you can edit the text shown as -the plot title and the x- or y-axis labels, respectively. The "Title:" -and "X:" text is applied to *all* charts, while the "Y:" text *only* to -the y-axis of the currently selected plot. +With the "Title:" and "Y:" boxes you can edit the text shown as the plot +title and the y-axis label, respectively. The "Title:" text is applied +to *all* charts, while the "Y:" text is applied *only* to the y-axis of +the currently selected plot. You can use the mouse to zoom into the graph (hold the left button and drag to mark an area) or zoom out (right click) and you can reset the @@ -400,6 +400,11 @@ here you get the compounded data set starting with the last change of output fields or timestep setting, while the export from the log will contain *all* YAML output but *segmented* into individual runs. +The *Preferences* dialog has a *Charts* tab that allows to set multiple +chart related settings, like the default title, colors for the raw and +smooth graph, default choice of the raw / smooth graph selection, and +the default chart graph size. + Image Slide Show ---------------- @@ -826,18 +831,21 @@ look of LAMMPS-GUI. The settings are grouped and each group is displayed within a tab. .. |guiprefs1| image:: JPG/lammps-gui-prefs-general.png - :width: 24% + :width: 19% .. |guiprefs2| image:: JPG/lammps-gui-prefs-accel.png - :width: 24% + :width: 19% .. |guiprefs3| image:: JPG/lammps-gui-prefs-image.png - :width: 24% + :width: 19% .. |guiprefs4| image:: JPG/lammps-gui-prefs-editor.png - :width: 24% + :width: 19% -|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs4| +.. |guiprefs5| image:: JPG/lammps-gui-prefs-charts.png + :width: 19% + +|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs4| |guiprefs5| General Settings: ^^^^^^^^^^^^^^^^^ @@ -932,7 +940,7 @@ lists to select the background and box colors. Editor Settings: ^^^^^^^^^^^^^^^^ -This tab allows tweaking settings of the editor window. Specifically +This tab allows tweaking settings of the editor window. Specifically, the amount of padding to be added to LAMMPS commands, types or type ranges, IDs (e.g. for fixes), and names (e.g. for groups). The value set is the minimum width for the text element and it can be chosen in @@ -944,6 +952,16 @@ the completion pop-up window, and whether auto-save mode is enabled. In auto-save mode the editor buffer is saved before a run or before exiting LAMMPS-GUI. +Charts Settings: +---------------- + +This tab allows tweaking settings of the *Charts* window. Specifically, +one can set the default chart title (if the title contains '%f' it will +be replaced with the name of the current input file), one can select +whether by default the raw data, the smoothed data or both will be +plotted, one can set the colors for the two lines, the default smoothing +parameters, and the default size of the chart graph in pixels. + ----------- Keyboard Shortcuts diff --git a/doc/src/JPG/lammps-gui-chart.png b/doc/src/JPG/lammps-gui-chart.png index db9b6ca636f419dc41d7cf32e26bb1f0ee5c5394..ee57be6cdde42be86cc7ffc0734ad3514fe99ed1 100644 GIT binary patch literal 119499 zcmXtf1yCGauP%1T*WHn-$}*_PgvbB@098&_QXK$*y?sAL5nDsKjwGx}uMVe~@Ochf6CL~1s9N{eEOrTm zGN10pf@<<+XR_-2no;dm>f>u$@AjbycjpO#Yz+s?4F#nsjI zY^~KsFV#v<{0C7M{a1P`{L;C9Qt!*4f5K<`%|A5Lt?7Nf{&*Lks%dA6SWvm2+?n;` zWqK-__TF*crc@5`4BTjQvDy9d{JiVt>#O1a-zKzLzQZC2Tm%1&p3-(dx@$#*qF1_w z!T?lZLSfMJ$<5|al%42`yO| zW@AwM!&%LW(+KOZm?C>+;T>uZCk{Xacs}Kf_w_>Zm+zLEumqRix`7vcAqWU)r0WF| z2sPT#5)bd+ZI3TsF=jbFIXO8thT$VtOi3Y$E!7BiY}SvJE~=}m>+S88q^t-ZB9T3q z&LJa%)Z9>34e>!5@vudR=FVdvD7lGA?Yb4`)8JYx$|PBd>U|4_vu{SLydTWm)tynD z=DcS9%w}-t*+IV|3S%SFo?z2az}aqo6=Af&N}4tn?wCkVnQM?b{Zk-8MMbse=8N+& z=AERz33O3lFxbw{4mUasof0v4%6i8)S3O~@*exuZ`V;&g`{rhcWoxKo<$cyweV4MW01-a( zfgy_x{nk7TT=2sDVl=wnA4E1lG7LI7Hr)pROfn1wAXzoZsKoY9rOU!l2+_336RX|* zX(E+Oi^Fnl@^h}b{+z-)1y!5HzaKYvj*Za=|7H)}-Q7)}v}R>xto!Ki78jSW!3eR_FnXvYj4O?|O5;vdWt7J#ph-i@N+(ER~Q# zEv$#H#0+*Av-f)R0%EUuEsqbAysI)v0l+T5;cNx~6ww#0C0C~gzkZ6 zR%d4FR#45|;?czq&CHth8ygz%!x3RDEv?HJk4vXAD>NBWt$e??t~tudjV;%0{c<%t zTWy}i)zH?~R#jDfjo8#OSkJK7&1Lj(KM9e$gQ_WFzw8Ncm#mXV#KlUb%j)>-cmeau2DxMij`pQ9> zEZKqH0S$?`4DiV`Bz#X-EW&7j-@`)SqZBXsk3qeltJpn=n=HQ$EC9fONYi~a-ky~O zDJyjY00!4ub@HC#xh|1z&4cima1Dl=PuyFJ4;7RZEMLD13oP4V?P;vZFi;gvna_-K zkb+(J>(bh~~bt!XSxj~zHJ=FrP(L&^hvn-yg(vJ)33i#hS_tP)3+dE7H zTXJytFaWmFt2y%--)G086eCkTh&KYnseXFy4z3wA3T1=u&oRW`rHrnG zpPxTDDm03v-x`3hNYqGl{DI4y{{qf>0RVpwCWPf z@`BL29q(iqHGzxF7Hm`uko;wxJ=@$ASQ+n6myUEuZ|YHSFJ%${-sST zVXGw>PHg-k^fpFIz9B`3Y0wLjAn8cVX z?HW7ZC~jKRaL7G{Eu|UWEuLnXO2^L~0~ureoHmJhw*4Ac&jITF0fWzqq6z8ae#|^|ARYELCZO>7`$WY^JfMB^s z9C2O)*Ssp@aY)5k$E_{K=tUr~jQ@h1#D$soO`v3->q1IqQ-x1^cCc5>^l9%b@a^T@ zEI@)jz;<Z3$w5DN-Rm@rR{9gryiC@B%TA@o8-5G^1lIj|niu2+R_CTIIP$gZ z+^z=*ps1k%tDr02KGOYw$xEsb^u4^E>&_5B{{6A*Qm%~l`LKN>O`WPpKzf|D_7S2V zKdlnM4nSWo+L|RLKXw6K_Tkh68(ocpkL~q3r!TikI(skLJoiP0Z{59VN%cBj8ZEli zCO4p961;P1Nl(wX3|xbR+zn55evV4_;^4zZh%k$VTjBM^o8>^y)Qh<0VCe*Z zz{B_)Nrjz%1w6sjsCP#@=~2w!J(+;i==UzKhe5U24(ai*$;p5>{FSaBr`pr9@|!Nc z{4d>Xg9?81JB9oLnk9~ea!IT!0mT$9{#eUe!)K3nP{@H4rs_o%!Ib$A(B5RgiN?!D zjfAY;{f$w#sSQEcwX^-RRgZgild=WblR;^sEWXUS@-@w-;MBCM`lTQ|nbJZLOl!c& zQVmB&b>Q183j|{NKUSsS_f3~11BMSsc z?Vlj@e{FL(%$qku!b8R|%b}S5Ov_)ew&(4+luDKGVqr*kuA6)p1_~`QjdT2gEvM z!6SIl5C-#UW{;Xt6MfRFmORl)Gkyeq6iG?Y_nJrnDisir=@Ikk721oPJH{x*sbVOw zRe6UcOvojadS^+CQ*3MuWHy(_qXz`h=`!u<*N}hgOdtv)*LROuA|`@Qu|M4Xem7H^ z+necoE`J>MWftZ4XTw=Rq%WQh%{SCvnIlw6bS1-5X^Ai6z`{&)dfQXkC+GOSAU73w zK^>1UH);s{hiv8gC}d_duWy!#nAAa9+rG#E#|di@hXY3wt-8hjgJVzM%Bw3ZXiKT< zgvj%q%#tn5AS3x{NrkWsYFyHB>kOYQZFLbg*1Tqm^Z62*hN3m4{LZ|KBH4o(Q&NLB zu$OyGD5w}TQUlu`e4Y*5-IX6mGQh5X`*Np`U?yAdVcv4C4V1VVx`NaDJYOine(9X{4p}H4qyL9A&%kx5Jjh}7r%T3N?sL8#+ z+g*bjm-XGRtCa&SyvLPDfS{L$f{~u?Ax2Ak81j{dn6HitwKam?URm0h001H45*Qzn67@f!A^!`xw4{v-!Cu z9H?G_2$#GGFr8ctoED-~T%^&qh*!aEUspeXNxrXmF!6&PjV{<#(Z=9pHZ84iUY ze)&yZx0Um=B#mUv>qL9R`VJAGx;Z^NOnt#yq-t*DHO2SV{X=t}si_?gLrJbT=MPHP zy14rmbyPAku}yR2qYIo*)|zK}{HT7cBPV5cf#LmAFXkM4Ws}=r;+kM7_@Lw>jg*t!yc!!vj6AmD zr>cfEsWfIjt(5e$7{p3N|m&2U)m&QLlFJd z)20Fx>UD&3PGxCiz|-r&<=}Babo^a~7xeYK+0+WcEY;9<#no1lMV*+#zK4 zP;x&XF?CT0SaSa9t{rm7^}wL-^!2nIM}_`Jm+78-B^Ds45ZFY3Jk^YQ4Rfi1(Z`}| zv=90f7pu`dE6p6b zHy*QWqkHv&JYO_3w*kPETc29OCu3%S;`Z*>fwx+q_#VvNoE)4zG~7X4p%99h zA}$xSTBFAUBW*wR%Tlde1_1Es)LjK7(YeYyPt+2W{%J=BEacvdjE4|uAf-z&CIN3g z!ZWPES8dR@w{{vue3o2tlU!!ayVO`|02y`NKqrXPi+PmumEDisMWa0?yUN*YPniG4b(rEz|xBTkojfO*r|dAi5~rDy?nzx|~9~Yay3b zcfi8cEZ0Oss5%UJ(gZ;&27LX>KTWvkA@yQD&&D>33tS>JY#*^*zMkanPEr)W%4t{< zP>>cm1Jka2!%vI>r6Y|F1q~rX5l)XBpiJQZnCZMK^W$d2C`2o<;U!`{} zr^z);es4+|Gh4(A-N_62K1M6gc~w^i$7s0>q&RsCGMjqhJ?_}KUtJ5^4@mY!3=7_c zk7H!F{*H&N6g$o=+e8SzqQnz7TdoJlEaF`I`l~cO2HRh8xvaZAFz~NE#*jL46b~?w zika94Gf_V!e$5P<*CJKO*)SFNQfWd9Ym|# z*G)|sFaC|5HD%ohmZb0&QYub{k^RC%(N1QjksoSStRAUILk-82T~hqdD{HEmFS+R9 zrqS7#F?}W%#W&FG-vWQ6XfLkX+@_H%vBceUw2vC4P74o_*Jw%&98~mdElY{U58ASv z6u(u8lkEOiJ%`k&&j01*Yv*0~dR5J$$I3Lfb(^{91A=LJf~Y*RI&d?|(7$s5sHq^i zbEmVpN_K(Yk-7k~vEEATDS#EEZ>{!ZpuQXdtuFX5YuSF~`eg`0mY^R=3FO9N$5X^8 z17H`MT})Totok|~gjE|HbxGH1bACOui>PxiMD+R`1lyU&htm!@JDp(OjE@8r-{3_? z^gJ-{k=9-698C3~)7$V~fU_RtC%!3#JV_jH8hE5SEiyKIK=JqM-&&UHQ$97k@>Kur z86T#zjSQ3S3(1?|DYF{yBI1f9UQ~TM`ne{}us=hK0Y9r;;XZ&4ATNw9Qnv~*o9fmD zu(w7br;Sg^v@^k~h}GWfILM8Y#5JI1O&v2jZ+IOnh>o>3IK-b3;hMJY{VJrx+}xWo zI*QoF{Gww%NvY!3BkZS)N8Rz4K+1T3>0W_O-z?wLRyvn~!oZ9Rk@%{i2AUxY>Zog_-Vfec)>X_;S!7418A_L69)!UgRpC1o=Q z;h>~E%>fP0Ur@*astkxF3ud4Y0c9Aw(@Rp(xXP0Kh9#zzt23!8;hdEk-zu!-$Gf5F zN(!mcU5%h7>{*q0X?hjGZ`)sYhGW;7>_X<<-f=`>CP}qqSxY9ytE*W;)Q_>!67&J? z(}9pVrcVQxUHEEi3OiGv2SeC^IAios0ndJF%nEYExJY)XXhC(akA``YF3tKAOrNVE zxBR>x4%3n-yRavTio|=3lOFn8TYG`@@-X{_L+`w*;e$e!yI8!nTSHg6%c&cm zHL%!>d)(JymVm!C0J3k;A67o1b=pS9GB3Vsk4XNM@a#k};Pyt)O)C?wJn?wFK1DFK z+5xxiB$WjhhYP$yO{!p8T>u0U>1mhT8hkPi03?8RFSm7)^2osD-fzwZGIDxxy!bU~ zEHp*}SxzOI#awm=uk6>Ubt0s%lL%C0aurfGe9)PSl)xN8bGT_~DLQUaUTnBapZMOq z)CS_ZiShO}2;Eh|!XejHi28xoESbRTrq@u`#)<#s(VsFEqZeplg^iAu@h6rNV$th2 zXOZqAF~`Yv70YFR2?J9VIzTsNz47Nf-|13s=nTEzd6TP- zITAS;v{35(Oq1PXdipY)ua{{2h0$sw?`^tw_(mGt$xgKE&U>jCcR=udWj2Dn^n^91 zx7}+#khd9Io>exQ_$Ve@oFW6O_xaFd=!6-1chV`$ayC-~nMPq}&gjxn0J~UUl_dyr z!+w?O`(@Vm_}ATl7sc-S{?7?jnk7?)H_d)Z`e!5H>nxkqd`o9qSbC}No_y^$Nt4 zG%e>Tan&VzqwV^Ss7|YM$`IGz*pELmhMMfAMA?7w%jR+%^E|;R&X!DFyR0e{)ab|u zjM;~rKz5LSyOL`GxI_56$%{;1#42EZh42%6X%?e_RYS8jDk!Wbqgw>vvXy+8T5HRy zQo~B;h+6s}3;UG;_NU+mlBD1_zwPQ0Vk~reS#EMQz`%R@1A`7Bn7}c79S0w0RP*rSAW6Mv7L4Ux0iMuebEiJ8}prB}X?dreB;dnBW$)xoP z+i6ArF;NdM?QtMsug%l_TMCu|=a&y(snuDL+#?zS6g%!#f9o`=Tf>DjTdu&C=%fl0 zM2To%0vx4M5i?9Dvv@Sr=_ycR^sHRgrxpPKx^G9Sn_Mw&rZY^wS?~X#dKlA$nK>8v z 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 z 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 zΜ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 Q{}{2dl1dU~;;#b!4;5$0a{vGU diff --git a/doc/src/JPG/lammps-gui-prefs-accel.png b/doc/src/JPG/lammps-gui-prefs-accel.png index 392861e40b4cd7d5b04ee02bf821df77dda88cb2..ed0673c0e5e063a4895b5adc563f30e5c1690757 100644 GIT binary patch literal 32179 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 J0BZEvMQpo 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 diff --git a/doc/src/JPG/lammps-gui-prefs-charts.png b/doc/src/JPG/lammps-gui-prefs-charts.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9e42134ccd2cd0e231f2d0b26f70617fb54c4e GIT binary patch literal 49977 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 V6AjZ7tpXo`Bt&II%7njq{~!Gu06_o% literal 0 HcmV?d00001 diff --git a/doc/src/JPG/lammps-gui-prefs-editor.png b/doc/src/JPG/lammps-gui-prefs-editor.png index b3cf05958333ac1624f34baeabee03d73630ca2c..7c2c120121ce205b6b2df119f05dbc64619569f3 100644 GIT binary patch literal 39716 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

eYAR*)(gijMbe1~SX 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 Oq_4YVe%#!ZyZ;A&ZxGP{ diff --git a/doc/src/JPG/lammps-gui-prefs-general.png b/doc/src/JPG/lammps-gui-prefs-general.png index 7f161284c8a350083a0298e3fe0bf87556cd7d9b..15fefdc96d9b3e12d4959db7d425842158ec2831 100644 GIT binary patch literal 58345 zcmbq(RX|+9wq*k$5InfMyF>8c4#C~s-8ES75ZtwKcXxN!;L^CePUpUP^E30l=A*mM zsZ(cH^)6d`tsSl?FM$Y$3kLuI5TztVl>h+9VekhH77|>N$m}}-{`qA7UG6&oP!kLP zY6uO!Cv_3ia8b55b8$CxG6iU;5xbc>Ia}J>5pyy!Gcq%*6259DZfJ;zEB!}EFQUWQ1;$L`%>21coCkGsK_rbyGn&@q$K3`^oK11%l z^$MWaF{9<{`P+N(?<7hLC9SQeHw@3Wj=%h#7mOso6SK34h=WmtVfQEY$C44V|BOpm zk_^m?X-DR%!eV4-5KGI-c@SLh9M=SmIL`1XoGg`Tclr4e5fLSsY9>(x@8zaEPy-SA z(6zk33Li$!mMBy8U6T5Soq#}Gp7#f&w%EeZrYKwmsAp@xshXw;Wg;RmQC8bMZ;}|a zS65cT2XB*ku+V^%A#U|@0;HRk2SU~_lmtCpxJDGLh+5T3z~Agw6buZF zC!8nwHa0d6N021JPNFn&a±kuvh~ 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

K2*H-S*Z1=r&gCguFgzfiu6OM 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 diff --git a/doc/src/JPG/lammps-gui-prefs-image.png b/doc/src/JPG/lammps-gui-prefs-image.png index 2f830c85f3f73ca7da0b9a40485fc96a8fd47be7..3d9277f16a606d921a26ee2cda695bcf34c97326 100644 GIT binary patch literal 45180 zcma&NbyQqU@FqMs0RkkrTY|g0TL|v%?(Xg`!QI{6-Q6L$>)`HullS-SIlKStSfP;|{W+i>DXT_FHmU8b)XCtE{)0Yib%IP1CSx;?vim{5@6nXamD=h@?awVbww z{Ps=2Ox0X(CCjaw58YNkwU+=E|MGVEVjvx(KmD?cjfrq%a(WsG)}Ijcf;+m{Xb;wr znxd+Trc~?oZ7T7hs#t zYPH&EVPa-BdUP9st&I#RfE={k>EYsK>31hLn4-4!o9j2^^&&Dfpa&Kin%~z?=ogdz zQ7`?NlD3x$w?_m z$;dbH`C)Y2_hiS`A=^yRN{L^}b&_x*>9vy3d4ax-09fRx+O)g@YLa|Y_=%#`zpZvH zhBGPTO0Zyr0Lv@9+uky*X)H#i-FcsAoi69SEuYWx#d4K=(I}Ak(HSTKWZ^FQq14pW z(b3V9lat73J%$KmeKqA=*%C!c&rO=friI*_-GQYNfgtK2x7*Gp4N>)F$r!Z-!=ND%bZSXo$D7#QSA6^R2e zgXPK>IWrLrwy#?}!LmhBq3PM!Tx@NTVIiMM=Rl7g5io+*8capJ<%61*9rZc0v1+Gf z-p5!g;zLz$ft~qVf>Nv!;d^*`G1(=3b2>>Bwvo>D0C1Sb6Nk2JTm4-FErakzkRMDJ z!55&{0}DXbMSum<4P;``_fyG4yr}-<`G)z%>f9d;1_8ZLt+OR=>Bm58iY9MC(s(dvF)}gym}DFIjOinR z{qTmCP-#}Qrs9D~mPYJJzkuPG4n!m$c2{8x+AX0tI|a*4nWUDbIlWY7^McMbwL-=p zGH?Sfkg2Lom&YpuNSt%V)c8(V=&&$HeAu$gmg9!l$f3L#G0KSs8)oXkVy8>tF zKFyXZd5V-?US2dbG`CW*km!&C32c;!ls|t4(QtT+}16YH7+VB_`AA#$W>oKP&;!dp*30Ww3&&^HauaRM``ewZ_+E1RnmN6 zDJCaa$th_%N3YOTk1+E`3!?ZA?JzK-=g~KI)6G^ZmM);?_OvO46_-*UsFs2cB?dkM7fUf)GR zp-Hk@V+z?n$r~mFUwXhvDv)UFhH2_-+WB8pg}^+SbTn)zSzZpZcs%<0`#l~nGHomc zz~TJ~$Iv3}+}$~cs0GP?{#@ML%ym9r_2eZmh-82cBoC~psF<9bgn)pEkC#6?KTnh> z6wE~q6V5Ik0`rwLswz*H|0xrlZez?tL}Jw4Q*cr}o+lbJhk*0u_*RdOs|}U7+bTOJ zpXDsC&%rI#wmIirtB#XR79>M1+OH27DEXuP!=x?jDY*9Q_Z8NPF`<{3Eaj%Q8r84a ztbgH=>#7Yb+=zHHcI1ttt<2%>o5Si(8+;2Kf7j-Sr;ie7Th&s9AE}z{Bov*ezp~q1 zOmmaW6X~T3IK8;_wUC(ym zI_(TMxHR2cE(nK@f0LtaIy|Id95liL05V7;zW!>qJ;W)GryH-zc#BXdC;$M+yS`+D z%l=j%#za9=s}F%JER0u>JM8@H!rj+#-9W zOdQ+Z)(zHk<<>SfE|MjG<8FKtrDkqOy*G7R{SsG@sqC~@ED)Z8`7p6U8T$RC!H(On znew()e2!A#A^C5fjr$E^P~J}+xt_$(IkUfK(~;6uIS90QBW2MFG+_Ene>O{K%GFj} zt_!Pl=EG&DwApE-D45IHYrJO`fRa&7Rf}%wX4tB!4qyOGQU$pJ(1}VeVM!#_elM|7 z6*N*+6txo90_*4Hu(fj1ya%rtjt|wK_@HkGI_rZYJPL=Q9u>^`o&xhO<0E8vWFTZ#)?2kTb z^5sdlqMQH?_s4x?)-_%|i8&?V7n3}~nj%AcRCKHx5(@hK`tYC8n|S8xoWEt&CHsQr z1$;Uc7yudQU&sU5=qxi8iGC{f{JS6(t^DYR+MHiJ= z=Y_XN)3>f2(wUqGt?*(087eBy%;^3Ddd`uFiMyMdUAx%S6oFhT*Dq0CETq9ct8)Mgi##p zYXZ#I_(b?%rNVKg6LSQ8yX@KxDyScj!KB@AzhJ|SL;%<`-rh&B!;@8AP~a7wSKQj8 za1&1A@Go1Bq0mHMIfGa)cgVe^b^WlS9&W#eW2<6PMXMM01NfCHr?{F<-uj*-q4Zl7 z2Y;bpBiZ-%VpO@jkafBfd@5yPE23`Td(fXuqZMz(oYj?m(Yb$epT{F$2B4mESNcXJ zD$ahNUg?rxnc9p>c6MJ_;h4)ei=mXs+T_eO=P}fb&(@H5|9U0xIRcJ zGBnF%atq6( zP4ka!I5{~v>?qOVc?wiGKmMF~1}JEB38ktU{`^5tJ*UbSo=FCi+KCN36T|K1T-MOt zT1)83+Bvg5c5V#N#hA-d>(&aVbP}Y z9plT{6(-Yu`0%ln-)J8DZ5G3uiA7Q)j_6F&Q(cITB`Hp=x>$*2q3K|Nep%&cJPSDT ziJ`8iD~aLLeYsbefhFuSLn`KbE7Q}p8I&5@)7knJjZHCAKaJwqpj7MckboRF`|kHN zBu+3He*mUaIBqPq#l!}yRf$Fj1nAmx$=cYX8M#edT$*0}_@t?mL{kqZ*vL_+gn`nF znw{c{1qY7n>);^!PnAKGT5;Lo&T{y#X-F_t!enDlF|;D0tW_7MM>`&zhuJ?6myC2A zow!lZXi5}Hd!iH~Qd}P%1Y96&ewIFA{rVOeLSv)KWsT1Zq$VjQXBan>Z&1zGyDiX-RZ~vh5HSc=Ds@nvaeC9Fn(O)D^+pzH zWJpjwsEBhy{9t3={j8QDpI(oF<4p4898zSZHIb4qb; zi$%)A@w^(OfR^tuU3S3ytja z@RbW$+w26tp-gXTld2f}oIAzzdJ02EPl=F3)>Sgj$nZy)IldGG`$5j$7@2I-#M_jr zxurLQgcty*kw$ae`B->o7)|Mgev~zwbUnUo=utz;IrJ9%;ejCZHS%wNpGe|&XW;&5 zd~|d)D=X`B)*#52`Lx1C3;`DgtD!DeEXCAX`syLkh)92osa(Ez65?c*CW=V{z|WSM zMIA>)RxM#^g@BJrGWx@zNft#JI$j?Yz0=wPh#3a&!vq3U16weu%vJ@8BMxr3oj5c8 z;T6&&VmRvZB}1QYoX*zzf)Kt=jXY~*2bR`q}RU;KEU!nDW4vy6#G68bDF+NpX*VVud*_Bpm>*OG4#fbHsLglu) z=WCW}qK&5X$TxsUZ1Fs=>hRc0b$eSdo^|S=?2tU;!z~AeoJLKnx2%#PwC6B)k`RqOP{Fb ziWZMeR(o>4eA}sj$)aEC?ib`!1jDQgVWcM<@mBuffeS$dd5Vf>bZ(@7OGHh5))xd1 z0gXU-`9=zxhnr`XHogZQv|!$-UTKU44G^t-(Iw9D#yes6F_{RAVpuCyfqZX=p$H#8 zxN_ADYvI%Ii2bdj zqaOfYd?6KR5`%pZ1 z$6uaT+^NVjED*fnmnU+Ok=l$YSVK-6Nq|<~vZbqng}2hQu{V|eMKwDLK_!anuR5C^ z!&>G17H<+`b1MvmYKhK`JQt`Lr`0z1*_`-b9Yh1HuXCoi)$uYn_zW_-dJXKjtR|~L zMygTh0RGz_PqxB?*VbquF7|M%sj-xQ6tC@YX2hF;%{{uoiwDejL)bK|O$?O!yKYUx z>_@WUN4+rpT4Zfpi08m-%lBc`IIC&r-F6tkEwqf)HHk%KC*5hCP)~2R3!$=p89Yi= zi-i;B@jCJ0!_I8ttyF}&6&g%TLWZnH=1Qu4vdvb9Vu?gbC*aag1)_gm81=Y4J9pY) zN^0sj6QeI{Y8?YO;FGl|Pn>@e_xSELE@jq&w<_~^3Jj{Berk#q7cp5c1-w}B@A?M$ zcp0NnvE;<-m_iKfV3bTI9Kl`wX)ytW6Q`w~080hI;R(fymsCwpfr0UhTG*g$BySCr z)4&Q(LyO*;$=CXM8Smyx1E??H&*>v%60#xzh!DPaH$q0;(RrLwRIS;srcWJ&5q?ro zZstp#Zqj3xRTtf`=?8t}26MtZFf2HRV@%&>R0|_LZ>`S{iif|~N<+D^K?49M{V<(H zgHhPBty;zCM=Mv&`X-dDTj zA@(z64Dh12w<1Fk1~uq=XN_e8_w{tek)?~(cI8wb37VAfh>`5>r&fU+!G;ruE1M%j zb;P7uE*=5Kv*K)1tqF`}%0647WJqk%VWFHYuRCI2f*ZgU4Eh9Jpq22LYR}~{6sXj3 zaL{Y-Z}Kftd+OM`QQBeu%u7v*Lk7TSyNSIvhU&R8=5-M z9XB_1oDC)BQ>$rNZ~YMy-||$G!a_rZVBOq2=3&iPRy`r$_m7S+NHFzV#Azb*3%<&u zc*m(CE{z~dT;KFQQ`zHDk(=1mt{Dl1pkQkAK%*b>lV(U+h zO}%r&11w{=aPzAvNcNcXQ$bXYiKhbW{4C&b!DN{M0Anx@nM5LTa6!bx+{98zOD%RJ z7|G!v4yv@YG#dt8C>UXstVXu5E3u2y>Y#z>r*~HAfh^IH3=Qyit}TEeLIjsmzVv=N z;oZoZiRPzwoK#R|!aZKqz$p%THeq;nD!EXG{n*%;`A%QZ_ppM7dLd-UYbl~YYS14I zjau+m1h`1hiO0mm#Ku-kE>XTXc3@ws2nXP0@#0?RQKU>%q*N-sd4A`y{7b(&IQTO_ zVceEtk_iLeWH{up*8WK=sUd6keq7RLLRY2{yIiT1x~w`@i@rHC3ze&X=^&Q5syS7I zN;vM*TEcUyp`vGqnuLTSczDmv!z0<*8AMoiQAF0NSBk=Zfdm&56AKe2P6pWl#srDN z51)+H)zz1m7fyEe62-EDf**y9pF6uCpv9H_4dh)=mn#hr|L9W z18RXsCWd~ugZwTWhjSA430^B}mgEkipDb7EjG*4dbV1JYCw+L{fPQUIP*4|A!uSC~ zzbxwDfjtyB*mxa?d<0RD&(TW9QJ4(GpK;K_a@=-7eDJMru)_@fjHzSy@>iKJoHvdhiG;w18nRW-+ir z1h8DCRjyL4ZDtYzqW2s@$cawTpZv~&*aLFU4`N&C{%QX?&=T#(CvZ6;H?P_3!6Q0tg5OC79tQ<>#wr} z(buY~n91Wmqm-!cl*+Qfh~z|4gODYpr9rgr&*JxHv9`=Qp)K^<+S)DBrW}gEui0>V zU9E+|LxL-Ov6VTaZd^c6x~YH#KHrVt-*Yqtq@ZQ16J@=XsoU@!3rC zU7}=3lxRy>OTIb_1@6&rkk?xZeJDe!A0JDl@yQq6?gYt2`flIb!wAly3=~s6Xx$$h;9T8GW^bKK!@g|wdUNHA1R_}?4MrW!<2uWL79Cyna zr=0N*)Id`$Vu-OVIV;o(SyicUdxB?7f-1HwW8P zG=e9*HuUBX3D*DW^F@tYGzZN0S7meBooMR{3$|g0Rb+H}YB&Pd8oM9}0Q`^cuU9M6 z>XloZE#Kb{8p7q=tfKYh|M)@0+j^X@voxb-ox39d4~$H}Z(3qsF{Uij?D&q4SeV`_ z#`cBDrF|OAhW_|SX&`0MwYEw&tGH|Hzj616MtfXu2xOFS9`o`p4#gVIm4mdYCZhhkA$W9y2@irowYC#4Gxf6 zxIYIzXnH^J3Pg)IZ%VyLW!=YDLxIn1YOGtE@5j<~?loKS5~P$cIa#dx9Cqm4Q&Rv~ zPiC_gHKw>-ap+)BxTc}Ch9wD3Ose@J%)~u9493dxk%-a2i&r;_X|mSWL4(NpbhKG* zT>O?H`P1l071Nd}CXKf^mm2S?FIjvL(+EHT>ev$4T}^*cx_xae@p#cVy1w*T zZ)2iEsj0m5eIADntESdzI&xMG?rD5ZDU5h^hmS;s@s;XmcUozikI7Ri!k>hmKF(^h zoSRH~m6j|KggD;4ywGkxKkIjqkDAF((EPlj>AlmA*Vh1e8}S_l{`#>N34`^(JS^MwhLRy+UOUkvM%wF8vc-mHwN` zbmyEB4oh94RTXcTLhdbHJJ*rt;!j?VuG{Uzqi>_?xtS{cRsCX)<@(`w0nxW4uT|&S zZicTbN3*H8Yo~akG6YNf1XpM+%Mnol=tB=$3-r3TU4Ue}SM=tI4j_Bp0mAQ?SzH}soktU|cPv}^LUXMg0c_n1VARK+8>LlZee<&K zCdptH!^YHVDJ-zY4Vsp7@d4@1+V0-npAhCvgAV|2RQj{o4-HM9_whOw&(_ zxEa-kh__i74vE&$k;6K+_h~t%xp={-+uuY)Yv+P^&gp%tWLTDDqE>4R^ds>xJ?nYr z?iF$Bm+^E;MAz5vE$~hkCG9@buGzF4^Hp9v3v%Nkk(_15adSTpQ|6;y;ZwkToGx3z z!LX_H@RmaX!|`}%){zcdUz7sl1_%3XVM8s_GR zOJ17TVsvl|Qs{owD9}>pb&%0-K4@27Y=AcF8CB|@_!vChPug6<1QctpeVDZOjw4O& z4r;1#x!nG#beg8QLD65?*czI8U$#1%6VfUVoe%iXWbj#nJXj)O^7OFc%;Koq(mqPW zz)mV^TWZrTi)vDPeYSnRq@nYf+mPgVQ>|M#a)koH~j*1YS`tK-mtYvzlKrh?alt7zm|l?8{c{#DBATh)j(*`^*Mab3kDr8%nKbu% zx4852Yd8&*G$95r6a9F=s`YN(2}T{!#{V!{TREzg=<;&Hb>Jt=^ZPg^X1@vMj+r>1mj8MA6+SQIpWoY`T2Hmv_}sBh|Ei#72+MGG%>NAt#?&)D-4vDKhcN%uUr5pnC!Cd8jO%}J(OxZ zAIoKv!wfK%ps>%k+8s~%D28%pJkACKJGzJ-p5JU+NmxLq*k6@JPLi9r8lAuwoKnhe z8hCcjx{C%!;1wmV9Zf*`BY3islfE$6Tb=!U?Frqy96YHGCb8^!QIP~1Hc0YV> zm~=P?TXVK_s1q}+gjerAJ)7^L5>rm~>hZif9yZ85IO*NtwwEb&o21mz;1O|1%g}7o zHQqXnY|{0Y!RCObZ6nf&%f%*bYy9Cp%V_PwWZORp$0A=)krcI!!a?bENdP~5SmUUw zqsW5QYR@kpW=YDNu)D?b<3eR@`upANChZPop(Pj1^WIU?)7Tslo<_q3gXK_NCD~<1 zyw}S{AToWaaivM5<;A(_S0+y_%zALO{tnWY+WJlM*eXL;cZgZ!EC;wFi>| z5y$8D2EJ*hrZltsuiEPJ@%^nhK_V{D1Y^z`j}zsb!*wSR{X*H8Rr|bX>e%|_?f7K3 z4Tc3qnY6K?5%qbMsitToM}6F=Il#z9 zTg=a*v&~rtGpO&x1xZKu{m62?(aDTpICLI}#H|DdkS1^OV5>Oo4M_4VOCqrPc(>0T zGjc$!{)1hss}QfCHr6{dCcf`)^eCef?sVSmWJ-bo*ORw0!q6LIlHGY%wMS3K538Cw zU^9UfW%&4!UWiAh`ADxN6zY3)^6xX_I{Zr-JNxu;Kd#>1)-ju?*9DD zRV1?E9}!idF|As((s_OrTw1)8s(e*-p)lVpFkj@fA$dY~kea@M;lQE!cEXeiWbpML z|Jmuo6k5sTW{4xh1i6GqhJb)oORo$I=phvqEu92DFFG_H0#aCT8*~legTjoi5#fM+ z*6X2;mb{bk5P+#k4R>5F4<1)pBLaND_T8(GmQ)pkxl;_MGHg$7e`F@!U87y2@4+&> zb-rL0Ajn!Gz`R)gBC9h_-tG9(3;34=5aA9X=F-J>ayEDr;FV_U@N=ZYLvdFr{D+eJ z_!KwSB4G@xyKMO`7(lRC~3`TnSjwjVz&0DN0%RavKeg%QQB+CFc+BXLoMTG z6}zS^?ExnW7xZ0`At@=v@WyYr7Fjyi9cddMdpD33Pg!a+`#OAv5&=}(i17HZGR1yi zgaC}Kjx)7y#;OtvVkcrl++M?bs417~XJ3{|q-v!2sb|V8XL14cr=#PS9WfK1Xs?WV z%2ntt2~^!3lNHjxz>_sQ?_zSb84&@CeCfqM}GypxpR**$y zdiz19Fr{njH7n)5v52+A;anH~3fdhMc{Q8-0MV;(A>f^iU4Ie&NlvHvBQ%8hx zeed=R7=~D3;*UEUB`87Ok^~8Kc(3BK^$Yjyt1U7gzQ$jp_0=0jcNM?1ctkJ__;C@V z9I}o^c#)~575&A3Fh3Dg3g!Y(Q{h-WdXEkU)IOm&%Hfbh`bSqqKNaGN>IsBKDG)Vu z?GoUA!ixB3jKWu?roxKo^`yv+Fr}sl2?6mKx!KPXGsbj*bdewEW|V;sPjS8KG26sA8nb_Ro|cv*N5f_k9I3Ee43Q9c!@sCXf1Qc zbU=pZJ3MuTWrZm#5v?B-8z|@Q7j~5PPKF=Y-vSMdC2nv)g(7+C)BHSVChK~e&uXE_%xAsdeF%AB`v{=gzJoHgnnd_1qUNg9IM!o41oOIB>~2SP-GU+w!_hQHaqb#cOMH2T>-xtlbEH! zyz_V^%H+MW(iGlV>Ko0+SvQOx;OH=x|CtwDp+CFS=q^>hXpu(yz87H;!dmg^RMc}n zO`!zOjr=`ABo>sab|@LPJ0bZqbdYqAL&&^B^B%$M%X(Ve7gyIxH8_Co%ciC*WRbWI?MRT&k90B72_eO6S2dH4!< zWVGy>H`lj}Rz7!3;eXa@V9~-YhX)B?7}0iqOLe@~v0U#9pl2vJ?RZ#P>IZR~V7rdW zqYK;d2r>=wd=GlY4aVbGEBa3zEvCzu7^h)royCQD<-XzqpGn*%x=+Qgp58pRrt4j~ zlaoGMVhpmABeS1;q0>ixL%PSR>2bLeYQHs5CV-;Xlp#!R?;cu&L}R1lH$`SJaw@+M=Ejtf>w!{2WID z_Ksw4d_XZIv@reOLj}rfBBD`CCk;5j-(!~@%C7QulFGPX?ilo?3N1NU-1+c(_bJ@x zx9pY6K1SPKKd9kOb)$=woaHZ;H17-Hv}aDCs|})wXK^q3tzYKE?M%gz;cV}{0>L|e z0060U1YPoe900(%b|vGdq$@LPxy~7qKPvhzylakfnY}a_DU-r;kXE=o^r8Gm8{Usn z^?tnbZlB9NfXibZ+4I4FtEKq=?<|k3SbNjO$~gA71p*V|g;r(VmEjl)%sY~Ztha&@ zS4(r_9>oc^w9>xI!44$P%Cf)C{KMGM#^8uhCpP~1n0sD7qr2&=ZL&Fhh7a3B5Q@E@ zVxiHK&=-UW~>zNAbV&iW+B&jxA3I)SFAk<34bct3v^LzNwU~*iG~VgPRS6 zOka?^sk0&rz)&$sfsN8P5kj zGYy@<*7G*|azfqFlu&=sCi;WXdo?^>rhhL!es7D9`(s(bY4B7@Dt8;gPb9)S(^8w@ z>3n;y1T~fUY-wqcY>(UhzI1vR6OtH=e3QrLgO`{$bI|Q!ibd?ktq&Rpn+DPT!Q!H{ zv)N^Qv8G_*sfUT`5gJ}9)|wOP}di=U(MWVL6%Kb229s1zaD!r()V!Frbf zNj?g{v}B{*TS*U2Njg1WHE}%xE>`5$Zk}tcV}r-w<_049q7xRu{rTx|g{NBz`xa5?rzQdw!|G0*bMlJH`%yLwk%L0?;E zqxSlng5R+C-go$}THFG}-30PRbFsfQqC?v-6%AY*8Ddco;Nz})6ZJMKB&)l@ z)ckIf03$C~hJXBE7>&8z->w_&_r_#*U4OG`X0(V|X)&qouDtH%ER+A_*gGxG&X_BA z$o_(p#etN5e;YeRd-?ffHnT*C2be+B3TBB~WvDd?x!8LcTEzW)jXW%Z4SP4P$h@H9 z;kB`4^ZC5!Ptp{{ORmH|wDOEpn=^emG|FU8#y~utX&Mh@nZ|>zUZXFgL;}RR>w) z=*LLoaGdu5KY=v+L*f1IZ!L!2Ch_gRea_ac23C92ocii2Qn(O?RWtGq{<t?tOHjA;kcZ^FOkLTU%bBEU?nY4xris|L*;OpG7JjY88 zB~&bor)3OyB@n5{p14mAS69Mky-}1_ER*s1IFp7_YOZc*4OCxj{>)oB2Pz>GgN|4P zoi6^4+nJ%#kobg=fu;WD^AsYf?mPRsz6+67=WKd*&-v0I5@}m2N|p;2XU}fb*@~@4 znY04crlH~-Zno4W@1V!p`DGbv_GEGe2pRqJv-8*a>i71AC4%0O*-0EnYZvE9oe1Og zOL`BD?u==sA+)l#lJHJr={W1Z-PV0ZHFuV*x_5*he~fG>uw#F{GjvC;bRM1A#D9t_ z5ydr@%K$mxVNjQ;tnJ>;fqpHgf1%xUg2E+%EZ4cLn=L47t<4G>v*X5Jnh4a`&P_Q< z8tzNhT&6;smS6=w#=+p0MF(dSaGlHM)rZb!;$U*|A$r3&4>&|{AG?pHKW zf44~7v$J-+n>;_znOaSn`S8)dT`(O~!zkQkOIaXldwJIEEb(QxyfXoOA4WL<+pSO2 z>q~mZS&U)jcW=)zS$r4=`~dFcC6wi+tS7e*av(Y%fyK3&Ill_N$L_4^`_VeZ?P`VR z%;EfpG=vKuCM*E34juuKh6*Cc{_Hv6iogPD&fXdj##UK@lKX$zu%0#IESTvsA^-w3BW&uydct@Cs7kmaf z*TGpYy56+i^OD8rv^eN4eo0M2*JxLKz-w{TJ8DDJX~`TkeY{A2C5KjGwm7FVc<{-U zJ!s+xN4mMa#o=xQ) zlqAd6)NajllS+vl7x4&`ykAfo{w<`x)!|6G*?L2@X}kRg;B=|df;;nHuxE0oQN|m{ z$x$+$3(>#++q&j@O%G*C@}!xvY48lHADbhurJXCe!u|MpycX^Jqq_K*JePsrwqT7yA-t92&PuLaxpH^9)DIL^vpf4+`|&@vckU5G zjoT?8^6QL>4ZqP)*dfBkRy1zt#o87)+3MKcz$BMJUfw2@bdD#F9YR{nlVIMgVBfWu z^j^(8tOAWb=n7KguvVF^72wOE`kjx`t;)x+Wu9(<#5nJqsEANoCS##$dVWLNHWdVX zu-?d<+Dfs{C7fA>e&CGD<6dqCaj};f(T4PjocjCXG7LI`!r_M!OB{@d9B3huyClNu zVlo~IgB-bx#LVthbWlLIT*%{oR|3f>lmI)YIv7!8#yFv2OcY2zw6wIe-$18T@G%|@ zsxx`#Yi~B4%`0j5JO~v@rq$}Q76S!V|16cr<~BmWCClC%D(`7dag_cs=l4-JZIhUyFbOTz=T{tHt5YyDrpB=zfk z&2g9O=5P`xRWd0fLvt02DAZ;c6guzg>swoEZ(tHc{$%-4LwEomBN)&l#^X_LO$?ZwoMo(WCI{&F+A^x^&9 z98CXmw|9A&#?_!<(M>wJdXN1MyyjQS^06xMXl+X0%Hg@Z|BOtOVrN*Y7ASXHMuWBp z!3)=Klu>cMc{Q_vO!pe7RCs-6yS3Q#?rAuGj8Ca3BpYtbxN#{vdsFNdeQ)YA0`mo5 zncrY~d1kXZTW)$BkoqJ&MbY(dzB60U@2&it7=ivTe%;5G0+(x+7RAwis}u4Kh=`{? zKg?uriqVtb4q9c z>&3*bTL^Kv0Qn5QDiqT9r<{jnu&fu=KW~x5lrlSRC$>UV z?gUMox5jz^{3~~wKCb#-s|xnY(wmW@Zt_63dZtyX92BVc$+&0$wfe`*_H3bwPx=;J9D;`Ni>^X3mvbH1W%s1hi^F3fTJ z6&ya$_gB3YQbE=VU|`zz%SLRAp26^qf!TG_rJ57QZL1ZL~LJ&t7Db-(Vg z;WVrJy;a&Mj+Q3!zV z-ltmg*%eoNl|u4+m!T)lPJCteg?mPHcTM;|8{yJ5Iho#28Pd)H4gj%fnCxhs>vtHM zKhV<&8zpX6j9}GNQ%M>ng1}NnLdDOvl}4F?O%m~|Up*mTVkTaROJAp#Da`01OSJIh+>J|zuZe^_XY zlDvjCSSZoS35e8}Yp!qtuM&ib|B;AXoh9b}7d+A~j|4MAYfFlj7mDpB)uMl%LSp)` z0Hk+gTfN5T!%^3db`IAi^G0toLv0==He|Z_<^OEq&C%L=M;QCMCd{s_eOKODF?|j7 z@kEu^5kXg2LJ<`UXRr}NHw^%wOsPc3{Oypts+WZcC6^r3L7_rlD<;aytDnMoo=R-c zdpJ)BX>ew<} zdz;c@{<4+z-{h<1m9yaV3Nex-wNYkGSN*Ljsn*irjsy1$+-*Q+YT)RW--;eFXEK(e zj+AtuNMCx87TEmtnz^HG9{ktEqr{B06ENiy3pv5~mUy9X$x$KNAgb(msQik(-WPKE z&}rgE6A;JW1CuB}XdH7~W8VtOF@n!f$#?qwYV?WQe!^5y3eQJ!mhBL;n5C80KHD=e zOzJPilrFQU0j|Nt^q^)*JYIm-0w>wM)$H*vy+xX-Ad zJ1J%PRUWRRyRY_jMm>t#=Fe}ZU}n)YsdA_;`{(VPenSFQXH*_```(T(dZ9 z&7`}WV%XTKJfG~9?d_eClK17FFTHtdIV|==Ff0({O>gn}V1bC1{*lI8F3)w;@vL+0 zR<4e@?ZI@H%avAdZ-VyZ^kh8Gce4som9t<6FSfe>_N~mAgsy z!--o^F4NK5!YGI5S}f68fa)Uw`t-S}z01nBHIJATY#E1MK{Y^*`7401j7e{A3_owJ zJL-70OX#xJ;sW-qILgZER;@NxEz=$U7sF^)qd5pmlMiDr3Ny@}s^6E}-i}5&T#9tx zIeB)vX?}W>cz5bE>e|C_4VXG%0#aY^FV3(XJco|4LN@8MFJIpE4XOybv$S1ijvp3r zCnl*gEu8S?n!K%NEmklT;2oEfkggG?MLTI-{#r(;t9EEph3 zD}$)G!iwfzg*MtN{@ZwZb&Qxg@8Pi@fqzMZC|WfNPyGCAB_@y+U2N;iT+NK&q3W$dn6lkj5y?Ij)GOqCN=q+V;;e!A4E$uS*(L}+f8jsEMrpy6M zPTowhXT`~b;7eMAjc^tRx%Nok95~tVV0k^p_FZ70q@kXXw45_9uQL{yj1bF;g*LZa zM8~Njn}DctqO!n0^B{l61BsrXwH#C~>h817W5u6r%{RfBA?q==+G<5J8dUB&OFOx$ z*c*d**>OWkOT$CMdc1ov-@6NKg`-NCv+?e+pscm=Fg%!iNwUfN=CId$R8;A~(kQBH z2`X)cl>10X1Od# zKCvz^~+&pz=uxE_g^e^O0v6S7#Es;R=GAz~E+4-A`6oW<$>Vvq=suq{nCosZqLa@9e+3kUppnCoW55nYH zY0*6Rt`>Vw+LiBb>W>*M?{?;*S7A_mPUbty6F%D=@wt=$z>M(5o551-g;g4h_5O0( zS`Ac)cEN51v+Bva)%ug5%&)apk$x zJL<*i>nxwr$_G!hg3HlViU8R2PGvm3fwEzF z5l!NO(WGl_weHFB1p>##d(x)3ps~oB%kE;mmW5BX^DpD;V|ghi;BO04#1US21*6^Y z2~)et(wCK%mo(IQO+;|O;O%6*F<#<}^qSMdZYhlck5IEzstaY>BpHsXv%xY&)A(E` zS#-tc=<`P00T(`b?hFOyxDZ&F0xQolL6&L&)k(|g;ki(LM|TJg{eqm!15GyT&9JxE zD-u4J$z+&G7{?wBJIP&N((_&j;@M~a)#&es^=NqkBIR!&b9gYp21|_$PCD5%*|OQF zg{ujCJXZ|}k8nEW>asE-6Pr%zR97)1?&D?T=Kx{pgO^Q;Nvf59xdMw8rZ6VY^}|G* z0M?zQ#AM5NqIgc_rpB7;O@pN?>@vwn0Kj&>&!V5u4dY(}9hO31^x$zQ~Ei%Wl_l zir*iMbff6~ZfCOd|Ksf~gX_qaEn!&(FI`#TGM@#mvmi%q&^VXfZQ0Gcz;8 zl)C%PeKWWF#!SR~-|>$V){(0AuCr_B%C%NzVPUHt-W+a{3c}VZg zjpes{THK;9?rlSB-cY46n=kbDY+UA+&+Z z38@c~Fh=1HmRya?)U(<<+?^#Jf6j|}c#_(j>JeH>0Ia!zbaU%Vk_`)M?10Yx`=Cnq z8*QbrM775eE*B&+F$JSP)Jqi*K+Y@tZa^@Ej=PqW7%2G}1f(d2B4Lh@5EGYHH1$R_ zvf^j7{=qxTx=$jNaK@A$FD0Ntw%UJetfB+DD2Nr&s_?AyViI9{98hkTtubGKG7W-(^aZcM@3-s~W zxODu*i1uzwukZ82*O)okp@KQx=NkMpzgb&lJhCGgm>y}G1Q^;V|5sS`&>5=Z_-E^* z+|lw}>Zg!$_Yn?xXFJ0af%izb$>5B`CY+(>5GKb%bNUs5l+p5Q422T6y}t zPCHkec0c>f${6Rx{Zo?&PQ#})8HDdYV!F+VxVxP#=5+d zHr$*&TwFW|vaVdSTdjs5Tqr>3rw5=+$O}2Uzt$X{Mo%Jojg+#U3Fu_Pfkr4zzNj6i zoj%#VdV?2GQsE!1cqY0!e{CQbKCOswL8kji=tz^)AV~zW{kZ#;kdsJfZ{T4wSMkQ= zc3^ou_S4suCg;(S>&wTv=B1{iwL=L)`g+Ka|Bn%xjE@#F^~Zr9IFNor&rbGsp)8!* zS0TLZy3hPdCPUYovy+Fg7|Sh5-t~z&)+MFd5AuPnE;}vI)_f!`lH|yrR49;z;S&QQ zBIR-XtMZRVf7%kMxy+DcgVZVA1i zkrG{xdQ5ywCyR$zPY;7vR=HMhd z#r$J-TM64E&xm@`kk`deO3VL(StW*N0J0LeR4P<7Z2C-jFn94A6%UDm0v{A`gI;fSG?6qVPu>KtruKvU8pA_6IkhsXv-dV8q}*9`MXoQH!+%_9|3 z4@mm@3Ma_H-_TFcz`$^FkEER%YH3u-YNhjn$F}gmP=WF#nK5Zi^;0ftX=Q{zqCn#} zW0~y@&rY_oglp3^B3Zr_HWyaKrJq*sp+592w+bF(vei6mG8Ky;XI%9MdXI{!j2at- zg6w%I{IRQ#-oh(_NXoZ($Dg39o?J>+e(8m!M;#LkQ&r{AmiW}kP$XH>f9Ly*nMero zeP)<+NDg=D_O{_3%!a_u!%wL+9s8|mq1t-IhoklgjNLll3F)&>clVautq>YT0Fbn8V7;6ybt6zCnY7FUB(9)GhKUi2f2eq3|=&x8vv%zKhR&s?2Tpq%eb- z!S?;!8G{02LT1&9P3kQ@0ts#SW$p2$sk-;p^KR>UP(YX=57~C!{{2h?OL(rzgemFJ z4eK3VEskw@Fy`;s`GIFu#7X!4&nm3Tc9p#udzFO>yG+A4y}wl0o|@J-k{2YzAJ>-% zFmEq?ulN1k8Gk3(U%0A`JhwLQynO3f=tuzo)l2SJ9bIL;h3iQ3`y%(Zzg=J!wO)0^ zuaD|&sMDDmFxEw$RTv-6!xi1EMpxv$I;ptI(N9ZNVGE=kxO8Hxk9^JrGbdUNBeC55HM8t7<)X6~q&l3)1L z=hpqnTc40I4%p;4_q$40XK)9r)p1=O?({x|@8en&B|JH3sX7|19lwu8E;xV^=luEU zRkV4%@ey(Gr`*{6+1c-w-&-4??u*uqA$;JG)8lRwOsfbOt@nNPQ234dWTYQT7lC5x zi5D3hC)xfA_Z4^ehax?(WKT`mLil@pg00BPMU+#=o(;7Hl1_V~M~=(B2FJ-<^Cl_2 z8oB)S&dW*XCY0ecTGO7C?$$^30ID5ZQ-Bl!c`5pkqIhOSeSGC!z-+w9^ZtCtRHy&> zGLo2A-?=^%YfeyEd|K;;Jf8c0wv6xh;-W9SAHI71MglRl-+MV(K~c;if7Gqp(nN$i<9$M#)AQ?i)WbJA!`gtY^2m4 z{s2mMi<3`-7AHxGgwv1L*e1-DgDiS?xX@%l@UdRnXw-bjxf?mhAN*u2)Zdx4=uK}) z*>E6h2AxbmNhGd>q%l!@Z)N)*UoF{WM3BsmNTOA;?wrZ5_DPGON}O`A$%{+6*&Cjw zQJmsc1GB~3>&nDGT)JsRdK_J0c2Ah=Em!9EOR5=Q0mHwK%} zXw+PyWg4UIyV>Nme7d=}>FTiWeHU8LQ?`05&6NjcrHs&L9f|Gk(7S)@dQ55{mrLSK zKvkC1rGq}1`dM21nB$tRwz!gcGkvX<+Fdf4Zd&$p_3uNC%r6CBA|1zXwX8*gtP#!b zj-B|R5qFSxkT2j#v^j>QIIpuu#|8K69hJ@z+(*z&TOTlj+q$~=5l9IcIS2aJ$!v>@Er>)*QaYn^i4~Xt~?xhslUh#>Gev~+42-STt&u~ z>KWX6Q4>op9(iqEE3lz>2kNy3ly`nN$A>Gl(R!WGy*$-e8>4U}?78Yy{{%fO2$+~d zYJ6=FnJZpk9hEJOuU!N#lz}Hu`etu$Z)&|HQ z-JYh|QXQ?!-I)Xn(G4*{ylRG}-H;_O9!By4$7IcrG_C_+C9C5>js{ z=IpW*$eD)Erh|h6vv<2eYeG>`QDbAHxA%LVy^&?-cVJKJ5@Kg1eNpZ&E2x2?&&T$C zK+X^1@~NSR8_JB|&5qWeZ^?^1DxYd(q%XgNMymeZvrc|fZ3e}xAhZ&8r4bR+%Tq!8 z=V;%aDX*cBox+5Kj$bX(Y7HG&fXC&P;0NV*`pT{JHd}nd;lWb1#p^`|pD#(jpY26u zUlfDl)05;!C>%dmtxFX(@bJ1rEFBQR9isx6Vv$?xU6Q8o2-^rtZH3J8b(^Dt4?K?% z*JJ8yy~z9bz;9T$q5T!-iBNzMgREix_ydl#F}($Mfc#m;1_fFE^zsVkaf(;5cdVnU zdwFruzy=A@z-?w$8WJLEFZix4{L>2L{&7`R6%f2HE-r+Hg&WvVKpMgTK@uRIYHIB4 z!9amuLWJ^IYeWXl()wKiU`78s%J}!QzkTjuzE%>kLXD4~(a_M)sr3y*OhcnpgaC+c zW8U0av(qCi;V3N+IL%)cCc0wE@X4R`-F^e9#s@qJCa~Skr~7f{cueMs4737}Ey-R)ME@OQ;^C@>Nl* zD8}i~&W@Bm*zanpb}4sHr@F*c5H{}4k8+)@(4)-pe1o5x+cPl{Jy!Vm1Td0h%=l|3ILK8XuzU zSW>+4K;CeF<=sE3a%()byY#wfd?KM;Of|G$gS2Z78A?Ie%DkVahHt8XACwhtp7J`0 zMqzE;aNOm12+Kvbh3^A@`WIwq1~DIUM-hsm;_~tLmno1H6zn~L1^l(&B?#KOy!wKI ze#l{M{vs6}FR#Un!nUP|U95}-Im$}YdAd-q4bvH-tFuheHe)fhI%p`Jub^eNiE=s<3CoiCy-dZ9NP{E zpzxnbh}D=Y=O~_RX5dN#r1ZA7w*373p779NWT5q8R8-W#$=KUPBl2>l@JY5il%D}< z6k`Q8P&qc|l1)@IVoD4>$`E)S@J{$LQKPHEk23?zJmizAloC$Oj;Rug&7Ks0Z-6H&Cmm|bZaj(eynTJu#pJ$O(Ip;M6gML?uoJx1Eq z;z#07=wlPF?$99n(|)^En2(PLpcEMxraL;k1hTlT0rc!~N?48({E!{6cyDwAd+-?u zTaWXs&=igC6n>W#ANZvd1Y7o>>ast>6m3sc&%T_IiOP$ADk>^Db_t!4`|@5efdW;1 zp~+}8@K8eiw-IeYi?>|1)43uj0zzbeH0kWjjGwRXUuPo8M}Zm{#I)y{Ld8wdvpd@q zU?<$ThqM-$EDA=8C7+_}LhNM4G8K|1(qKWfdR8)GEQ*pD-A4F8rghsa*A*HM_7N76 z!}+=LG`5wcW8l*!N~sc~y4urYSzRws+~4YaOC8;>Lzg(F3M})rM{tq~yrMLLCmGW< zoTeV-N@C45_DdBz$_-23Q12`Irb_N|GZU5dWZjc`vOakgCE*xp2eXR7c6TXX0&^P2 zoc68QrNSd0w!CM!qbD(&vH5MM=Gtk{-t$Cy{fE0dJfC0nz|Gxui||7MTPC52#kYYh(B;BxCJ#?MLH$gqSJhqP%DC_jHWDNb|-S7 zlxL=uv(@w-BYlweG)Pzk>UZW>Rc9q8NeMy7!{xGM0w171XRY}v?C{&}*Ao7{f#-y; z3!#&PYmfrILx)lTUCM5?A(}~7U@?{!yFVbOuCX%X=6{Nr?L8VC(#~>W zjt`}f;OwoAY32}M(UMqN-)0u|OHn>%)Lh2k#$;#f*xA|X2iXcS1E+Ul3=z)*q8AXu zxWe6}WbZutb^QGNYBc=&by(ThkoZnhuYoTcA4rLLaQasUEd_hBskt#O-7Nx)i*XZG}PuYJUM9I)egdFVJF~es``bF zlJ)9v*GUc66FPq=YR_>|W1J^kR$6*836Uzq35>_X%(P-{N5Dj_WmA1wau;1h%~r1K zAecVWJPk_G?(rq+`EkjntAV~|#YZ5^RxuZdZX$0P`q*zS7V3a+D= zFQJPe!@bOkPt^``W4MAaueBx#7PtIhZ)Y)|b@gU)EGtzP{Z5ENS!+5%4s1-C6S={0 zb0W>HcI#w~!wpLb%_H(ByHN=*B6)KY`!&%Vu>A3I&8)44H_V@w7uI)SP*tAbUm(qI_RT3smNk>*cV<-qPVtfDOfKcY>98VfSW73~Yyh8=kAJfMYHCAOveO&L4 zyuKt^n4l^-&ZAs#qb~4zdO?#^yIJkF!~X_}vW4*;n$4*4ZvMiCw(U7)H+l z$3bS+tmm9ed#3(ToI&42>!nP9p3DJ{a zc%l%h(5^znjfr|woMa$2IBNRi7Cv1l804SI-e)5H~m}kXlk1xYgGmhD5y@d_Vmh`3Z zfoEgF_wT8Q!r$~_tOp_YB|#S4ju{o>$NOy?v(jF?br7c9N%Z0$nb|j#Lij|J~~<` ziRbk6jJu`5Ur~w}VMAA6H<~=@Kw2y>f(DC4wd!0@y{D+k>Erv(m*GfA)y$dlCA#6$AZ4^$gXau$C!~{I)n9|Urs^hX;B*(A;=4FgXtLw zby>CtlS>~3iR9|&@8pLLxSSvALY@->Y5;IefWMAj^Yu~Y)EY*IP>OWf{?T`>Uoc-R zEY1-x2%jB*%>y2ZB~FDH4R0)@mOnAEp$N+Zj*w!+`1SRQCwQ_XTzvdX3EtQ)f-Tnj z{!&dsT8Q)T_<+FRKmu_XeCfEb`A!&~(YHu4AqHtJX4CYp-uhiNM# z6+49KY0$v8eRz*<`BomBU)w7fftb4MRG#}V9>4FvXOlY;86!G3>1EN8(!pE{$p|bw znW^8xBLodu5LpP~)PX1vo+qZ|{bPpLQ1K3`#2mzERMN`&FKC=XV(FMfLE*tF0xGfx zwOZkSrLIfFOoZFEsoA;W?kN)*)m%LTeZ?jNW*93(Er>s$-~K8xpdp_|&Zyp^TZ3}Fn&y$2oyoVuzZyJDMK&T-w_baQK>H&> zAwi*!_YS0?+Nm=diQArDcmOK8^MyT;oO*l?##2aTIN{f4XNSkYJf-5Gi;miGiPF@a zO5&(%wKAQbl_C4$kYsr`X-qE4Yqon~#P@zJo_A zW$YZ}SSFpaUVtc!V$_~FsJ0FwUaI{toT{>E?=oIoatLLQvp`D<-M>FKqEat8Wy}ld z>jlrVAu#ylYVaax_iB|L5IQbfHPqwSut@Hr0qZA}TDeXS=fd~s{y}->kEObd7D8^lZ+C+Y@_&xfAGq}8@Dvr~>yD_b zIS?u(n?<5hA1ZGX`8(b-$aT^Bz$;l=5Bn@{u%vre>O5Ir3nmbNXSVGa)V@Bw{$`YIV##LudW& zcU+}jHnV!ugO$w~;}3L|KJtK1ys^kGSLuc-y+p%tr|QGM*qlzp2)nH>;(u#4Ef_|LID@u;M$o=Ej1|3wYv$TwdpP$gTr! z@}yiIkhX$2dB2JV|3OqcasDe|efvWX^MAq{m$**LpKXGDe0%^f0~=kgQS8 zwC-?-PDev-dP;%U^D}?7vNsMm@x%$}=~<^VJw5HpnnB3RBLFmaS?Q)E}!bsf7Y-FW*U?ZU#8bAI}JQ#S7IOkUf?0^`!)b zF)2&^5IMb|DPv+Si zNE+oSPy0}kwr(J%ACmlgU-T*1n|_ZTmeF?Cf{UG{(rtxLr6H&KIfj36lvple759DN zU<+pX%&_CPE)i@M)GrN43}y%^e-Qm^Gn;cAx~?ZHkQV2f_1>hQii_!k|pT(bAuWn+@71s6i3 zcF#30ilx^NYm>c9^bVr09xB~L1dyeVCoNrcipVyc>`%p~l=XFOt2ay3ga|x*?Xe}8 zJil$(y}oL&G|YS%c0a{N5z2tn1jn~CX|pP$r_>%L)MWblvB9_rLb-lj`UDkqr5>$s zpx2p$an%IvH|^HKaCug%ikzBKD;-T-C_Hd7vqcATLHq7?idpgFBri3Vfnp=^pRDM- z&Of3|?(x~#Q-B8XtgLQ>Z=vYQ4iuv)kb>Ft=2k00ip@Ro=PvW{?5Z7@hTB!mMs!6| zlkmshX(*F#kA?Y3qUpl%#V(h*YnQ!v0N0*4wI>Hv%pe!@2~EtpA_n+`HN9=iG(|uX zDKo)0lwpn*F0FtT#zU^jG| zT}OHA2DY9f?ZeBeq!i+!Pt9p`(MP?AV}Rw=%{*EB>P9lc~zwp z0yvAd(l)gIdn2vn8yzrkr3YT?XirW-0raTP%FM*zVq{bZ!C(Nmu!BXnOW@);F?lv4 zdkGmyD5JViT^v}ZZ;v=_d>rC!ZG72kpd!f2sQr&=52%n3Zp27+^&=0dyBX8ZzOLQY&Hk6jWH6dso|gh79yp1De&X zudmC=$^A(XG(tGwK&h%K%~~~;ZaXlAKQys5vNPV_VI;gTaN__~9Qfqh+Cs%8wclxs zw9R>C3gU1L2~$n7XO~*y>9uRDKrdPBw;(AJVONOSee%;)%OWHPd*e2vkoy(Fd{o`z zl73f3ct{D-+S zwKAz1X{2b!dz4oZI~4)~0z}i;@9)kxf#-H4B_)0Q`0?iE=FfSlKu}iTIkHFb7*2cP zErrvL3zJ=(90D+ZG@L#FBeYsh(QbFeIX+`ZUp06dMf&vxM$XGtdl7P#(t1>kyJlfP zIy0ujI#>-B$l^Nq_>U3_&4~UNnK6OPv!$V~X3 zz#kD+w8fgbRmO;dE4GlVU3k|`UDcLFr}1MgR&9JQ-ug0oemtUeF6L8(g$>rqVSUDE zsB1oPQmm57FC{HSaG819y%YC&muTs1@j3vFXozBnVhi5|WLdd+y+80*BRcW6Z@;E{ znkaI-feB%Ic8Q*-WDrNwbJrxLJip`mVlU~exb-|@|3fJREv-_I4XJO8jI%`Z5LFT7 z$Q|ij*&yyzt|$XCzk`Nxqvl*NlG`kzHRo0?-$yK`4&>fGSna)|!(0pu4Cqh1N=oQS z6u@2Wg4=H6yJnTehyyXkVad8NRT_*tU>q3`)A1`quk|GTkdDVQydJvL=rrGYD81X_ z8~pm{yJ4@M|jzGeDGPY7ab{3 zgPcr%WJtpE{8%zbY=s+s?K{y3`&>br6cjhlEMdQR+9WGFF*LcFyklCk2JsQ%DS865oOC<3Dmj zAGqW%@8XS+p7p;v?>ju*xm2H`kDQqv46f*-K)_AOBJ{%Z=yVS=AlXH$ueWSwJ6~LF z1_lNK`vNvfbW98ur;9^8A3(MLdi)QZ(ra2n16gfuO!t5bTGJ&@YNuH|zSk%@Ji!3Y zkxFH4TaR(4%Vo=#*YoksQGP0>@!gdl*rHtTSU&l$xEPf;$W>Jy@$k2F4J z;xJHkg6gy=tSb)kt5`1Pw>JF*4s}+=A#7`Fo6hOVN(q=f7Kqn@Tx}EOfe3YTd1$X_WcD~CX0D7?{NF+5x%v8) zcpD$`l#PunrUc8-cetFeWdx*XUbOu7yQrK01$D+QEdMc9^beO7#1Llh;gFC}jhiF< z&S(@))rzn=^^lnh9UN_jZNMm?8d8IMJ^lHI2Xkh0S78(nci5B6glbc177y3Fmz;d+ z&L2r8mcw+vp%6fhHckqLtysh_EBa!#niIIX8Hfu~ltxt_DH9P<%vR#iDzI&gfxEfS)*8+wNQ$L;Hgl&6@vgtr%}gjxFKvIV8}UX#Z0 zHtp0%J$&iU+JVj#TfNopTXr9em9%B|`X0UQfpM<8C~YF4nkRT19Pu1!Y;5dCHlXwd zgd@ZrORy@^F_pm zNZ|=6qBmBBFq7R(?`;T}j8+?f$74O;uFje+)w~*=fHYbXJ_Hl^NV4tnfGgOjHV@so z2CRlYr4+gQq9_$B>QeaQ`+R8-`O2>AMDJFNj}aRi>*?tUJi8(k7c-ecAQS^IeorrF z0C)GE&* z$7FAf;hckdma-xNqQ1rTairP(L}NjG6h^snjw{!X?>HscAHE~Dr&OKw8}XR-_Ifb_ z1$%GbYo9h9A0HnbJ$+|qXHj9{p8|$G(pe`Ws=`b)*6B_~_o>ZY{c%VGIPPk|M(&QC zXuv|D=R4yA9lUu46Cx7)7g`!oRngCuM$AN|Iwni4c(esR3Q6$kd4@Eynsa9@Wt%dX z4v7$fww(etPc;xEg(gP_EHYHP1Bqar%LCW&5o@LO%sD(OP^#|MtGVPSB5Q7;nDIR*w?is-*6r~taT zt{)^E`1R~8C&S;pHKlppU)fZ|bPaiR`S8HV5ble^c(iRJZ)HbR4JFcTePtCrn2- zAc^Z(Z#PQzjZYzZz$sRG?x|{5FT1HUdTMGvoRDvtcDh$))4b&e!tCT}IAP(9MF||l zSDYT*D|%X~lcnmZW})G=z``q_=NT7jp$P1Gy&{*{aVd7uvC+s0XPWeFYHgN(o2ARn zP+}+-?_c6vL>H(+&3(T#9sbYzB#%M34e80%7I7yOOOwf<_Z3lDs=c*b!5>Km6Hc-t ztc*?z;_G!|yU|}iyxQJ-FT@n&W&+w$u6d!##o9oYu$n8-7n^3GeBFCRwK+zVo(_Ad z=X0746$N3nl<-q@vOkkabC-1Lw^VWCSJi7n(%Y1hDz)<>2(baJK!4kP^mL?xYw+i> zvSg$GU7MokMxkah+KdEQM#>`;KW@0oXhI46K?aRsbaVJpPff^*QS9;e^wPJm!LIC3 z(P@{o7936)iO={xXDv>=-LEZec32scGdfUB_NcSNjQ~lBCXO7B$vkCMu$pNYx=Fjh zuJD{JnLb7keEqmLfyR?Rx~F@>wEVK<+VOD41H-vm^oj<6h7(xeuKW(?_n*xcdj@pm zV@Ut^tdpkgDm9|W*;Jg7hZp9bN7V}Bqjof`jv^XbZLS=*l{%roQ9+liSv z^D(%1ZzI6m@XTuMlL;*9P*Eb6^l?vCG2i=6mJF=!_{?$%BMa`e5X~ zZu3I$r{UmKoo8{^^3d+4ily)m8y1KcK|&toU%U?5j8WGA^9Vb#OHqn=Z%=@jjczC4 zRFn1C8X7XN#&G(RztpF>zE@cHC9R}L%g^*R$m@n_Bau%DL;4+b7$Ju6J`O=Wn`Zz0G+M;-n) z4Bt0pdHFs-)hO%g2Ia8(Ocop8za-Lugid2AGye6n}#orepGc> z#(uH9ORqeo%Bv?~I}Is&W5hq_99}Bny0kR><%>1LM|AX$wne_2_`NgXk(~&cd(_Qm zG5f>tC_~3@*x3o(6Nb5ssG76{ss+XIx^C1;pW_^KCu3F3-D(*na&k=7D>J)F1+*_4Ln{Y#PHW+^GO1>cFMquc>=$-ff{wt!{X9ki#nj${~+4f>F_7 z9l{<4zoFYCT%%m9g_`>rCF-#V0c-`L0Zb?I9%AB{QxT;nF)D- z@<%=p=CNDR)*Wk0)qAKMW`CJK+W31=J373~b6*2#3$P3#W!4z|Y)kUfjyS?#1Qe*( zg!7+&IUdjPdwQPXdPrl>wvaY1zhV24??InBGjmqAbF<=Cm?bRknkQSRuhczewA`(I z`|VvqFc9F-(vdQLh4G=3&Z#57!?u=elf5Kqg^!qd+C=?j-xnoM1vfZTN|_t)h5dkA51xsCou|9xS;fx5)3|{M_LkPGX53U=QRJV z#ZrHvF(UZJTt5RtG5mQ3EFx~CUIg9pz{nwApDiojI;Qt9@*)t|)05pN#Cj+{NIx6R zp$XOEkO%b@<{`YwV%C9`Rm7Rhw>$3C9w~NhLSp*&bfk1`w!`U)iq+eL@{*u`MJEY@ z7mv<_fU#P^{RR|Auka$oX5;yMx%d>VfFY{hUos$GXT9*+HnPeGma0|?R`Q1l4N+DB zJks6Kw|Th|iX}ay;BSEfJ5f|}pcO#szfVSSpGt1H78M% z16us}Xcymo^k&pHoH=LVbS*BIs@ic@hBmgC!>BpO7h(jSd}@}iU9IQ3>PEZbnj)6Q zM+aeSo&Y+B{J0-ddN^cMlR;J4U&8+0RbmwNS_=;>^u0*HNwPM;$fYDq@_|wV$>N?{ z)#zbyR%nzU%v9MDPu?o#@a{&xqU}F8Ht~JBuEcCba8w;-3yR9feBcEz8C}Mbi{hgU z1#-Q)(CdW$%c^p1h~eFz5KbrXmGA@^F`x5zEA4k|4TT#+hL95Fc{w%5rZqt|j^>0s zJ;|4DoE5hXLzJS-rnBSCXyd$klRzB=o#(^L#kjKbdaTRR{HiJ%iieKsc-!~aHrX@| z%Rr44$oC&V)$r?<@k#x(e z`QG1dcaDRAGw9KVM?VVCh(NyM1%A{%0w1rfJ=Jlk`G)%S@+Q@$uzzk`I8;9;zu}10 zZG*3`g4f;gYdU+(BaubHVU+jRK_MUbQZ18-^dHXX8k2=iCN9XnqM<@MwI-Xny(F^Z zA)>ZiN?sww4psW+2b<IAcXSYr+9&8 zsgfl;+|pZh)+GX5oCqXV)q%8S$_q4{T|FoViiyD_-MI|467ctymbgCt;bW-JTTe&3 zv!~@#s;`Pn%SH(c9xvYCLVAW4TTIXM@vi|@4d3UjM8u8v@DEOiRglJ;iFi1*Sl8-w zS=?}%w_U8+l}T{GsMz=Oi~yD8u#&MF1I0;tquh5qzG-yLFH$(DlT#<$^2A+Da#$xO z1ybm!m!*a({4PT(qJvX=le|$MYCZh}1B0tq$k~Ucoo9{wJ(=78m(mZ1x^Yu^RSL6x zRs8?b+U|>?eE!|(lUV@ym${Rq%I$4kf;v<14e1;i_Z9#7tEB!q zy`Ly=Sv%=&*b(h6rGGW{B>#%Vq~3lx>--9g(ZifLe^$)bpKbp7Yl}NuY3aGOtJc&r zK`gEKCxT=Dto&jRYmwkV2p<~5O@xKHae(PRnYQCH`G(RXQUteT&al(8E zsiBS@N>A)dyd>j2nuBOrUrPP7`lP&*8qL7rpDczSLum&&NPl#v!ijADi@or zRHT9o!eFru_w$bIQo6cISisD@#l*IZ5w%vn$&&QwlB1zrbt527(oYnIg%6wL{|Fh* zhQ(!RI%b6bQ|d|XMQNQ}->soPAaHRZ4C0dbWbh{H$e6DV;!CQ%X*${7u|s)T-@(Nh zlH=W-GP(owW?EPEF3E){fJ_G%*_{svXLL6c@*yJt3G?E{%p zE^>HU#b2{i6?g!jMr6rC%)&%`85^)d1Ouo*Buq=cS~X0hJIL>~2?h4efQh4?#5%4E^}-Y9lh}T-Grrmsx6j?mjJ&0$Njp zQ_5;tnxUphcX))Z1+@^h8xzdD0tsJSEF}qEFCd*8by2N29p_`e^!I(?b=}%d8jPkA zL+$8HIeO6JsI$IYk?9!F+(MOMl>7uYjYu{yM3|$i92xi7_kIjWw>=~vuI2;!6~h?> zCA__HFNZkAHO9S)b#=3I-(Fo@t)z6l6TARODkmV!6Aq-hqVcnc})=Vb`R``wv2P0~dXt~L5&Tfz- zek&qx`Un0dTt#c+m-$;@Gie%i72 zjKK7Fc;aTT2NC$zf5jtR5$J5hB@?8XJ`C9TbK$bs?10oQJiT%xzRok|7=q!78JERH zc#T&v2$-U@Z=1Stx!&G}V;+bEQ&IC+KM`>1m z{ue5$l7fQyWlxZ^EYGgYS`iVEPRk|WF}02F-~B4$aK1SLns-E~fV646xl#TSDiZ#8 zp~7DA{t)oWJXO(kZ@c4PetK1SG_Rv|CM^j_N3*&>z5dEeL_T4b`midex3u_lp{&Zo zEjK%4ws2&aUJ`nN4BB!AJgdvu+4*8qs|@4{g-|doBq-$>2kR;?GP-BUaYJPLpYEh_uonSY6A#R&U5G~Xy3<3z;&%eQ z)9lzpGymNgtVMTD)<)qU{T3UAVj}xN%s@3B2TRrDsgbC9$sNe1&T!nF5^y>cl@w&{i&^20 zYgAd{mj3B2j{5K3Vrto!wI!Ii^`Kvggvc~L4`NGJW&}Lo8GbvRaUAozws?y!gBkn} z-=Gn26C%&M0&E9+jRv)TSVqly#TXV@Cw-z?`<$ZSk$kGc;0Pbqw^6&+(;3oQyf6MXBfHMW|5irIdf&-tJwdbD6W>iEU~{%d+*%V0trz6oVF;_hGv?|_ zTWvP%-xzWgR6rAPdC>9oG&@f|1AAKtFWsbW=`#ef2< zzUipgM0%U_dWU$F_{|H`oH!}{E*>{`7ETaQV&#ok6~@(Tx8F(p!9Zo_?Vh6*Vygya zmWH{=FsMog{mE1fjtr4}?k!|UPs%JTA`4q_Q%CQl!Qu@tIPG8VpIe|{1m^clLL}t2 zcqisXgg_t!v|IS8J z{j^nSild|ufe%m}JJ@2pBZ1B2r>SeG$ztdZT3bQXURsLJ&(GhAfp+_RzszkZcT_o% zv@;G(TzYAZt6Q-iu&{KM(vAAu~dE6s{zp3r&-~!>J?FbqEglY5&76TTj9Wb4vRra+-=k z{gsiS;~bq#mJpb9oepn%=dbGDDa8T_Ayt-Xt=qCZ=-i-V%`MOAP{6}X)R+MQqzuoW zp?`m~1MFJ;@B*nyF&a1P*kfhTq%ws!V<&Q35F&tfTDn9tpARuVU_7)i5 zdl}>x{&c@E9e>L1eluM!KlJ@o4D2A25xz>N!~4E=(}q{}PxCeG4_SrZt;N1V`CL~RerPrJOO=y z;a`vS^$NWryTK!M?P1l*(|=#Ot9Lj?KF)xduo)n>_)^a};6)M9`jUZ-OjD+~xp<5Y z58FtQ?{0J2j~Y+>uEAL~|Dts9G>5ww_bkA2eOvW%#zeSQ1{7D`-Q9hy#Y98v>+7pp z0R?0cuQA`%16y-xdWTGM*KNx#XQX6FHixAqA;0%JUHQy~KZG56jh(7sW~5N5#l-;$ zb(1A0-M2a8M548fuB@qUv+cJqBEImd=d&cY9!g^YINQ3C^s&O|*Z-->x#;}Qie_fO zy~N*FSeTSshHj=ea9EZNo-R1~UsiGQ`7@I9=~?m6Tl*vK(1$UHGQyvBUCua;6YJNW~*YXBx1Lms68*`isCfUEIx4qH9mKqj5(N zZ2)R@$$hsnFTY_#e~6(?|3KB0Dm8c20Wo(Se3&M9o}|y0{3G?fZPn0u%y`A30pWpy zaHR^TOr4`d5i*z$AWwjb4D7kh64fTJL#_Az??LX!ff|;-)8}{t{@Jje5OV!Z@O~iNL9SY899t}<)ZNMN~I?eT?-@cf;P@wFc*sn>~KObjZC|Fa{V z+*2?u7Qlkh{0GBP0G*;>bdvL~iHe5s-`m<W>1%6u{-janq(g(o{2%RoS5y>1v@I$sL1YvG zQD6iG$w&qPQ4kT3;2@bHNX|JYMUo&OIDnE7h9T!X45K1JqU1OX8HOB(G~u=PzMr?& zz3=CKy|rHdbys)ws;aKjwa=-u_ucf0l+BautAJySx{^QqczdDQpBZqGw-qgTT#7Oh zIx-gTdwPu{yrgf}L+hCOD8nbLIKS^}UBFhxTk2!MXP&ELCv0X`_1!!4gTziBfor_0 zF}#l72Jog&OfRgW$bNPv7QJb83APo-la}SkHjA;bqX=30t*;D`OI}W^WhOl9bsQ1< zr;eY2;P!vJG3uzwY&&_5?Qr!XGsGsk{Zn$!REFNc3&eTj z)V-~a<-|tPxH}7-aBw>IS7d#%}+t%a&&Y|dhqQPH;{u)IPDSrY(PMx zWD`ohI}oHpY__eFxc7`xUgBAtv_Jou|Nj ze$x4@-sN)dc+j2WP+}gb|4SCpucu}*nFe=L9;xm%t9-aJ5Yi;*dzq9dTt<8i>~MJz z#x&+Q6k}WB=b%XCZBNws6JQRf(4cZ$TpMUuHvH%q*MHx}i`_l>PE+Kpgv&g1(c@uI zt#_d%@>K7w^WjplvzAS0VZeEzOhZC<=CsQ+!}!ed?)Gb)W)Zcv#!RlOXG+v!-L818oNGg0^qn7mr0Iyzmr{QH{FJ<}gxttDV#k$uv`xNq(srrt0jLJb=Iq5_f3(A&2Xy=ulBXAQEEw!slt`Mdby z0$z2D@kRy|ZCP@hSlsvGs-qfjZpIz1=VOKX$j?hI91W*J;dk!m&ATEVR6f>h4KVE);b9J-pck$H)~suY)3=7k{iJCnir>w?d= z0Dp^!ElI^A3ZB!Vf*Rhx^1>HF@FBBkEDx z*E5^NGMQF&EIe5c#n2!C5bTvU58;3hm$7_80OtyuYkt{W^+ zTO7O^IxQ8L0!rz~dvYEE>mn*S*^BQFyJjj#-Nx@Vw1tDza2lN)Fecl(!>u?d7yCF2|N{L|RZ%Qo?+c-&IEfWv8d7?HwIsWya$kb%^AP*2yqY zNl8hp;~$C{=`dx$z};}4`|&>b9N*sAnd$?5m&5=9%>ml>H*UP1V!Y6OC+sq1sPP2~ z8;ecA&+v%uClFQq8fgw-^;b%j08lUB_=ner-Snw`|NL&0Q{!=O|ENGT3` zF>8_e=KGrEM7^FO?vxieKR1oRR1(?-Eb**QGQSoCUXB=Z#lQ#hf~Ryn&!aAjh5B!i z)`;}MjaKFw&0#>QeY4M2_w-lo>vayJ4#Nc+a42m~DQ^c8t@@gh4mZBEnASRoG_ANb{b}MgNu9 zq6(MFI+kNniF}FmmePR_bZ7g-=Wv8=`ugEVyLJDzX&!yMs;4sf_D1&l7kECXIem&y zQ&(lsBgZgShkh9*lWcxwaNYG~iyd$)xjk0eIrs3YZ}B$YqGWuaSN9)NTBhqot9;=v ziAQ~%FPw^HaczHmDVIoepH;@orjp$^x?cP0d(K|yL*Tk1vX?_z&$t0MLS2kCNp7oE zM;Y2h2{eN9jwUSnW+i`_boidheL{ZPvLU>)e~6)4nDn4$}n=7e>)5+~vrxD+_ORZP7;6Wgg^@ z!t_onhBm@3R?kFzUg2hz-Zx#{x}4Jekcd!C)L>5|+ma&6B~WvQPpf!=q{f_Ue83R< zdkmMZT6%GWiw-&AX5#{s>q@tUfUgQl@LBGNrHky_z!nz^J%2j=EDwC<^W&jo2>X=y zPz~g`>VCc4*;u;Si+Ig!)Mn7Mt?kTfksTSRX^Y$7-xA%TH`?Vq<_tpP`n|dhYaJ}8 zzS2SZ@HIuM*VZQp1v=sKHr*H+r>d?royHe*a1Xtba@&BPH53$52@9+(EKkhmlitUR zF!60|ZYK|OUkhAVD~-rY^Pfy$I~g`DawKM0nNyeD-Of5&%|?9ca*JgT8lRZQUi&I5 zY6P!mMIQG5Ae=rM7Kbt@GI?F(vt!5|*DoyqDbhPl6dD<#y`S@XZ>dY+r01Ep7c}|c z)hW&8xXS|aW z#h2#j!!(kAXX~fK+M^`mCC7~JV zJe_Fv;3a~w=Qo>JKtrqL@9sRD8a0RbIrgq8867BF=P-B{KWoXf*=rQh4Sis_5zA(L zXm-|+SU33z%&lC%)^H-+x!NmcysAKanQ&b&yCus!gde$@i%!T(|c7V`Px(XT3Tu}cZ<%M&<&#%%CzSzP3i#>cgOz9@1%)i zJ2W=d4&J_vzkZD#-N9~0uKc(mq_<+J+*%Iuw;BDt`b0YTJiPrtmXd47SSAoJrOKzx z1Bbbv#oFuWnKs+*hq1&FwnAOAjtHNsbUx^#$NJ0|^h$KI3>(}WzjShIlrhXF;*B+5 zo@@*=XPIs7cTMYnuX$Hx>;IBIIF;Sl4t_foCES!b^T?AhgD@*=buf|&U7lh7?!nLP z(QL`;>4cn(zH@-4NqA*M=x~0*>?;spzaMQY*n`FCWIAd|0~^;!XB!pznyy3nAG5Qw z4{n8B)@D`Pt#Cify`*yOm{0eTw*_5^Str+a0&%t47`3H>2fsQlVt5T@R?H{2F4YZ) zZik$W>Ua251BQa!v#o9?(%KjK^*4um^!CSoBbg)|UrFrueL#OB-tZ2lN{@^Dt~d_NI+6Eczdsvq z`;r%4VEkz~U>eaW=N5P#nOtUwxr2{2HUl4Y>`4mu-3};0BtiJN-gxXn2MA`Jk99vN z8R5aB4+;DAbPA@T`Mo%5_gf5#%VT`DSvSzulj~pR6XL;RA|qJD+bvm@IMjgcag6S{ zn7U6FnA9E=91MpU?{|O8(y}M-U$EA8pJhy9@?Cn@MluUEL7UIy>$>NnNW-(nRDBBj z3i4ri;p{3x>KAHN=J+7;?B=Mgqx=Li0tsTN0=JOdhuHEW#gFmMvQAc=CyW(>@}CpY zQ|~cZ?7psZ;DboI5DQY8t1qGYAgV$kUCL$d9j`)D{d!P3T5pa!!^Bnu_}6uSJp&s) zW`Mq+MWy6dQ!LK+?sra$ zM@=J+LqC=eNeV(kY+)vukG*3)ed;~E&B8KSq=P6)5$H3M%lX9DQ4U(H7{~&jd;=-k zHOJbv8{etDOIrE+L_-d+qX+i#D`lxDtciFPmOzPAaYNM;ZR0n=^L(P$1p}QYPwRzy z9n79FC{lW{->7RPAKI(S3Z0+>{Mp%auX+cB%zrQFNhv3-U{t{mYz%_=A|##U?eH7) zb?$OQ=V|F(8;@g??fXM5tYZXq8~qy{WprlbW@l$=L^V0a~%Y_;Ap@}_L8-3kd2GBox$e6n1Q!L(@r$~@hhj}p@bGDy3tSLoVo z)I~Hy#T$=Q`en_j6SN+^$$>whze8Gn?6X-2ivc!PeEQ@?2(o7RH*I2g4g7r4Tg!}p zDw{ZZv5Vv#L=$v2t{D+9IWq$R%ULz8+x|xqc2DLpc?Dhxd`sNnZuX?j)M--F*E;vZ zRn7KrcnAv$Gt#7C(A13lC~h1BRqOO^3z6Y%A7p%su5=mtA{JlAE+0Z-I|>WN2(IeA zILb=JSjO*%7Ypx@lLPgl%%&-uKh1nRha>D6E!vX z8$9NrCX^!{!h*w>8tb>Tph`K8d$XkO&G5dkWAX*Z**Gr^=PE_rk#Go)jNHdisNHmx zig0W78ZL=?GcL(4!?dmbxO9pl|UTcNMKv$!_)=S&20F$3$VK^2~vM&6Q zA(Fz^fK%e-IxKeHcDi{3;yt4E!8B78akOA-bnc+W%Q4W=VJg0U6{kq$zrR~0-tajs z*&7bKIk|P~*C<8@ zVVC!74Wj4pzTyUtj@zWrR4g-m_izmZv*#kiI-WWZHNi>`F2;j{6eu)EX}O5aQEyY+ z#a*I5Q!bO&k>{J(A*3hdB;qqf?RC+{#2WajMu@jhiSnXsfI63W0(!jl)P9Wt>R_bl zlGdkPRe&>s2_iMKe9)Kew07brhW(A=$DVUw)IIefYRki|$MVT9g#E1T z|3)J@32}{=%+Lz9nVmmm7@AF%Tdi`Qw(wK(T&JX6LSf#Nj5!j*Ju85K(|)2^foHvynq|m%W@?@FKb&k?x8J+FK{mfG1un z`c(h$%Um6f2XQiW2|zFJ!^{+~zzkc$uK}GGyDxO_-j7GuG!|t*JZ4@{scZM|-OH)v zzX+26%K8Tege4{GT`f8H}f<{Zx`DCp}|pFjJj%k|$P&j0zF{vWR0F)?+-TMN_PZ7@YmK5V)@qC!+aZBlrL8#~9K(0SZ7xVB9Qp(y6|& zv2m#Ur3eiT%|0G~otnC7eI_onDO0VUz1bY*hf>qbe5y_d4ov-g$SI%>cmYf*EIZ?y znwxz##>#5>A)EEC*bu_W9)C@Hq-A+p$$9v;HMxp*$5m_A%VgtDlHSB+Y9@+z8`d?G zQw^>aFutvrTS&b!Bj=gMy>1-Bd2Da1C0XEH#oSH3f;U|>rt%)(b#OxonKa&m3v3y| zKGQM_naJ$@z0BM5tlUG|E0>2{@vp*Py!3)hX$4Tn6i9If_gYSZ(GAcC%_II+#m)vjXj!{jTlgmo0N6a? z{Kf*}8lLX%gW`f>V#6Zp!{Q~Q#Tx;$QXh_PXNSCGNmuM=V7DLX7-P#kDgDty0Jz0wPq*uMtVZ1=;GCdfSE8f8}TWg@`ZeG2Pai zT=+Uxx|NBU>I(`wnHKJKChUFfaEWi`;f3GgTC^Ng;{~Sl%_rY$3osN zj9o^>#>Rp;1qJ*1`UK_WF-_<9@81V9+u9uJY;0^+goMe2g)f=k;#3m04f_^aICpFY z)zP3yB_%P-b0`&usHRhhZAYLPXYc9F!7gPv)D{Xz=lRl8Gbgf`P+Okb zhpyJV@8H%^Ezj1e0W9U~rwoy>Ux()N%ku@Wm#Tf|Px%&)NBNJV^%hkyH%e6j8e(jU zk_vu8`s^TiI#RqD>RH?TvS@P^?QcD@sYI9Ue|*}{7|}dG?HhAjz%O5lA_w%wRIfw= zXthg&Y;{EWM!%<+sA#EP$-yla^v*c?c^Tfh#9=+{laAS|^y>YfVFXj@WaWH~)S3Pa zacrXK?jjtbhGU8)1Rj+p;{zWGLyvGX&l(7)^ZEV?1$^+OtVHosQKP36yhiv?|iXbS}#jOR{W@?#rODUZ$@xqi!Et_TI9kd1bY8zbgZE_KaJ79 z*?JG|wJrTuyzkMqZ+*kVVnA37f%)aqfNW}#NtIgYHxoZ}NWP@}jQ)2a;fHZLxQjGL zp8LU`?L;IXh%C^l=9e7diF4Eby>r)-y*c;*)>W6ii3tVGiRp0Y)c)X9V?iFX+>Gc; zhVSda!odOAAjPf|;ncDxEKlstD&upTK_uV!J4j#05dcI6#yQ>d3{a$T_s-s-nxWDd zZjqDEhy1A@;a{B+&Oq}(?_NHKE*mtxDQ3M_pB38!n^yyPjGabl`JWJ#B-uyn$~)fS-r?9vLTt-F4iNT2H;jt}YR)TCBXj#uc5 zY;c+$;E%?JbcXY*!Nf&v8~Eco;=b-+$jR{~mS=IUC0W6fJCF+1OR2->g zi==5V3B3Pb!ZXP-Lul#bhkGzk8c2=D`oY6#SUNI2W#^OKgcENEF5yZ8sms5ZOYX@} zZN};`_hrM{91*7CXpM`JuqU(ZsY#Gcz^!d`*_FQSv+5t-ag&_4%TMJGHvb&>7z&1p zJw2Ng+v9xHm}I#bVTw8)X~=R|_ZT_a>BN3}RJMK2AgkLl78%~mtm1E zqa!LRnh%?uodp_#!N_AVoWGER&hux4uYyrmM`+L;ye~}+q;P*&I*k(870B@cKU=p` zJo)ni26PNjf|Hhv@Rh=Nh+%`bpPxVV^s*Ha=0Co%yk$+-WQ%XP(69QUrt#cvNPAM9 z`Mcx&5{cYh2xJ%rVGNRI_>vTilB44lhSoD`o0d$R)Pw2>=Vi9%heb(J5A!#t@Q!Jr z(>4~(Ns81M*&kR9KKa93YAv$l34EMeIlOm`VF42Uc!h7DtqzC>P|$QXq3;O_YVa-t zJSK7?0GF$b%;fa6u^Nu&vwF!G%2#&hK6t={J$(W2*X(#Np3`US5tWNJulnw20D7eF z&ePwN%(;xdS#S*`i?Zf%utNF$W%a`?<4tQ^oKqXIp$e8uTZ4aApdUq`Jc+{0HgkSBd0F$WW4V5hF2ZEAmw%j6lC!SGkQ!Gd>pb-{|?mqB$J*8%n$C zs#cCE8FzMp#FQ#=Cd1SyeOP46^&{jxxm%H|)vpf&9+MciHl6{Ch+APTiV#TBsKe3G zQJqmu8Vz8<5C{auMGK&1{@zH{=-KOeOi2<6Jy~2_shF$|UL8RPaF(!9OxF*=JapHbn4FAm5hhZuby4Aww%#!E-H&J_|Q(yU^i@-|T#C(xiU* z`oJ5tnXZY5C0K3aiTYlukeP}_8DwC!!^a)FceV)VC78F-BSSDX!9D9T1N1C4d{yn0 z?nFmJw)SfFtLrC|$o6R9G?U=B(CfOmDJ91CAiX__hqdU@!xS;0*|x5`|FnvS9ccXCcZb?&bsCDshtkXn3NJithirs z>y&UlnkGp0!%X=Dv@S4x{BajWl9k@i!WvLx{j$&}Q!q?(hjhUrNJj zi}F7c26EXAKmm(Wvcbyv4qABstPk=-z00Z!#s45%sG)(}DQXsqEc;q-x)l5XFcUQM z;7&=VP2^51GE3u@KhcJ_l0QE@>uKFydKuZE;KYFw&Nrol`nT9rY~1IvvWC1D=Fq8L z6Q)Dizl1aVTZ{Byu~-1W4tM+1yUFbXXXI`}ix9Oby4ZrrxauIvQYPqB+#~e&E3rp+ zC8_KFfWBLxcHb7VQ{;Tw-P`*Z7guK7P`7CY&G^MlP`ACWAR#1G*G5N~4d4qU(BNLO) z;o2Z7@R<9-1DFpqCJ~KBCnRVY7)&JB1cXnHgWV0!kUdqutJC^B`jo&i%?GiJ-7T7lE8bpA$g_=P| zFVt41+MX#!1Fnr^AFc}&KlJ%VPEG$7hq|ycoMD-Zw7LLa&F5b=LTw27$Uk@lyZS`Md_sXf5RbZ z+_3bn0B|~Yb#@DG+vX36Cw#@vvUuf0OOgwgaxmyH7y&A(AGwKD0UE7n0u|VHN!ir$ zPkN^f{LcGX5kKygDpE=5$GY|EPtO11)nB@P*lRlRb~GG>v$t<=)dJoOYc%rq)sNLy zwAU28Zn(u5UqA&f+N4j@R6#_TwT z$?NBMro)L;c_3?VHP8)GbOanOxKUtCVZ3Deq54}UEx!o==%TNBscI-+#Zl5R^IyxD TN_z@iqEJ=Vd|s|-9`?Tg^lNw# literal 44816 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 MchQ_%Iu`r>4-2n+i~s-t From 7be6e9564775d8ba13c0b1fc5dd8aed913c25283 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Apr 2025 06:28:29 -0400 Subject: [PATCH 137/396] Rephrasing suggested by @simongravelle --- doc/src/Howto_lammps_gui.rst | 37 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/doc/src/Howto_lammps_gui.rst b/doc/src/Howto_lammps_gui.rst index 44ec9c9e16..592e67abc5 100644 --- a/doc/src/Howto_lammps_gui.rst +++ b/doc/src/Howto_lammps_gui.rst @@ -104,7 +104,8 @@ Installing Pre-compiled LAMMPS-GUI Packages ------------------------------------------- LAMMPS-GUI is available for download as pre-compiled binary packages for -Linux x86\_64, macOS 11 and later, and Windows 10 and later from the +Linux x86\_64 (Ubuntu 20.04LTS or later and compatible), macOS (version +11 aka Big Sur or later), and Windows (version 10 or later) from the `LAMMPS release pages on GitHub `_. A backup download location is at https://download.lammps.org/static/ Alternately, LAMMPS-GUI can be compiled from source when building LAMMPS. @@ -365,10 +366,10 @@ that the smoothing window includes 10 points each to the left and the right of the current data point for a total of 21 points and a fourth order polynomial is fitted to the data in the window. -With the "Title:" and "Y:" boxes you can edit the text shown as the plot -title and the y-axis label, respectively. The "Title:" text is applied -to *all* charts, while the "Y:" text is applied *only* to the y-axis of -the currently selected plot. +The "Title:" and "Y:" input boxes allow to edit the text shown as the +plot title and the y-axis label, respectively. The text entered in the +"Title:" box is applied to *all* charts, while the "Y:" text changes +only the y-axis label of the currently *selected* plot. You can use the mouse to zoom into the graph (hold the left button and drag to mark an area) or zoom out (right click) and you can reset the @@ -400,10 +401,10 @@ here you get the compounded data set starting with the last change of output fields or timestep setting, while the export from the log will contain *all* YAML output but *segmented* into individual runs. -The *Preferences* dialog has a *Charts* tab that allows to set multiple -chart related settings, like the default title, colors for the raw and -smooth graph, default choice of the raw / smooth graph selection, and -the default chart graph size. +The *Preferences* dialog has a *Charts* tab, where you can configure +multiple chart-related settings, like the default title, colors for the +graphs, default choice of the raw / smooth graph selection, and the +default chart graph size. Image Slide Show ---------------- @@ -758,15 +759,15 @@ Tutorials The *Tutorials* menu is to support the set of LAMMPS tutorials for beginners and intermediate LAMMPS users documented in (:ref:`Gravelle1 `). From the drop down menu you can select which of the -eight currently available tutorial sessions you want to start and then -will be taken to a 'wizard' dialog where you can choose in which folder -you want to work, whether you want that folder to be wiped from *any* -files, whether you want to download the solutions files (which can be -large) to a ``solution`` sub-folder, and whether you want the -corresponding tutorial's online version opened in your web browser. The -dialog will then start downloading the files requested (download -progress is reported in the status line) and load the first input file -for the selected session into LAMMPS-GUI. +eight currently available tutorial sessions you want to begin. This +opens a 'wizard' dialog where you can choose in which folder you want to +work, whether you want that folder to be wiped from *any* files, whether +you want to download the solutions files (which can be large) to a +``solution`` sub-folder, and whether you want the corresponding +tutorial's online version opened in your web browser. The dialog will +then start downloading the files requested (download progress is +reported in the status line) and load the first input file for the +selected session into LAMMPS-GUI. About ^^^^^ From 689b542da673be087657e6ab5b16417a1feaf7e9 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 14 Apr 2025 10:59:54 -0400 Subject: [PATCH 138/396] make minimize work with KOKKOS package without -suffix or suffix command --- src/min.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/min.cpp b/src/min.cpp index e20e4c191f..bf36e0539a 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -113,7 +113,10 @@ void Min::init() // create fix needed for storing atom-based quantities // will delete it at end of run - fix_minimize = dynamic_cast(modify->add_fix("MINIMIZE all MINIMIZE")); + if (lmp->kokkos) + fix_minimize = dynamic_cast(modify->add_fix("MINIMIZE all MINIMIZE/kk")); + else + fix_minimize = dynamic_cast(modify->add_fix("MINIMIZE all MINIMIZE")); // clear out extra global and per-atom dof // will receive requests for new per-atom dof during pair init() From e4c3b0c05e6a83d6d933a0514e09b8cb162728db Mon Sep 17 00:00:00 2001 From: talinke Date: Mon, 14 Apr 2025 11:33:02 -0700 Subject: [PATCH 139/396] New example and log files --- examples/gjf/README | 20 ++-- examples/gjf/in.gjf.vfull | 11 +- examples/gjf/in.gjf.vhalf | 9 +- examples/gjf/log.2Apr25.gjf.vfull.g++.1 | 137 +++++++++++++--------- examples/gjf/log.2Apr25.gjf.vfull.g++.4 | 147 ++++++++++++++---------- examples/gjf/log.2Apr25.gjf.vhalf.g++.1 | 131 ++++++++++++--------- examples/gjf/log.2Apr25.gjf.vhalf.g++.4 | 129 +++++++++++++-------- src/EXTRA-FIX/fix_langevin_gjf.cpp | 4 +- 8 files changed, 354 insertions(+), 234 deletions(-) diff --git a/examples/gjf/README b/examples/gjf/README index c22df903e7..b98e4134ab 100644 --- a/examples/gjf/README +++ b/examples/gjf/README @@ -13,33 +13,35 @@ mpirun -np $NP lmp_mpi -in.gjf.vhalf Compared to other thermostats, the GJ thermostat allows for larger timesteps with the correct Boltzmann statistics. A comparison using averaged properties from this example's input file is shown below. 'X' denotes a failed simulation. +The theoretical value for KE is 1.1168 eV. KINETIC ENERGY (eV) | Δt || 0.01 | 0.05 | 0.10 | 0.11 | 0.12 | 0.13 | 0.14 | |==============||========|========|========|========|========|========|========| -| langevin/gjf || 1.112 | 1.108 | 1.114 | 1.118 | 1.111 | 1.133 | 1.168 | -| langevin || 1.113 | 1.125 | 1.121 | 1.135 | 1.152 | X | X | -| nvt || 1.094 | 1.114 | 1.117 | 1.113 | 1.121 | X | X | +| gjf half || 1.117 | 1.116 | 1.119 | 1.119 | 1.123 | 1.136 | 1.170 | +| gjf full || 1.116 | 1.071 | 0.938 | 0.898 | 0.858 | 0.817 | 0.780 | +| langevin || 1.110 | 1.113 | 1.121 | 1.129 | 1.157 | X | X | +| nvt || 1.083 | 1.109 | 1.112 | 1.113 | 1.114 | X | X | |--------------||--------|--------|--------|--------|--------|--------|--------| POTENTIAL ENERGY (eV) | Δt || 0.01 | 0.05 | 0.10 | 0.11 | 0.12 | 0.13 | 0.14 | |==============||========|========|========|========|========|========|========| -| langevin/gjf || -55.16 | -55.16 | -55.15 | -55.15 | -55.15 | -55.14 | -55.12 | -| langevin || -55.16 | -55.12 | -54.93 | -54.85 | -54.71 | X | X | -| nvt || -55.17 | -55.10 | -54.95 | -54.88 | -54.82 | X | X | +| gjf half || -55.11 | -55.11 | -55.11 | -55.11 | -55.11 | -55.10 | -55.07 | +| gjf full || -55.11 | -55.11 | -55.11 | -55.11 | -55.11 | -55.10 | -55.07 | +| langevin || -55.11 | -55.07 | -54.87 | -54.79 | -54.65 | X | X | +| nvt || -55.14 | -55.07 | -54.90 | -54.84 | -54.76 | X | X | |--------------||--------|--------|--------|--------|--------|--------|--------| Script Commands: -- fix lang all langevin/gjf 10 10 1 26488 -vs +-- +fix lang all langevin/gjf 10 10 1 26488 vel vfull -- fix nve all nve fix lang all langevin 10 10 1 26488 -- -vs --- fix noho all nvt temp 10 10 1 -- \ No newline at end of file diff --git a/examples/gjf/in.gjf.vfull b/examples/gjf/in.gjf.vfull index 8512dad837..127b8fef87 100644 --- a/examples/gjf/in.gjf.vfull +++ b/examples/gjf/in.gjf.vfull @@ -5,18 +5,21 @@ atom_style full boundary p p p read_data argon.lmp - include ff-argon.lmp velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 -fix lang all langevin/gjf 10 10 1 26488 vel vfull method 4 +compute myKE all ke +compute myPE all pe -thermo 200 +fix lang all langevin/gjf 10 10 1 26488 vel vfull method 1 + +thermo 2000 run 5000 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE file ave.out +run 35000 \ No newline at end of file diff --git a/examples/gjf/in.gjf.vhalf b/examples/gjf/in.gjf.vhalf index 08b0b45c8c..ba805d693a 100644 --- a/examples/gjf/in.gjf.vhalf +++ b/examples/gjf/in.gjf.vhalf @@ -5,18 +5,21 @@ atom_style full boundary p p p read_data argon.lmp - include ff-argon.lmp velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 +compute myKE all ke +compute myPE all pe + fix lang all langevin/gjf 10 10 1 26488 -thermo 200 run 5000 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE file ave.out +thermo 2000 +run 35000 \ No newline at end of file diff --git a/examples/gjf/log.2Apr25.gjf.vfull.g++.1 b/examples/gjf/log.2Apr25.gjf.vfull.g++.1 index a1cb4de702..30a0f7e9c9 100644 --- a/examples/gjf/log.2Apr25.gjf.vfull.g++.1 +++ b/examples/gjf/log.2Apr25.gjf.vfull.g++.1 @@ -1,4 +1,4 @@ -LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +LAMMPS (2 Apr 2025 - Development - 09d3ac0a1b-modified) OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) using 1 OpenMP thread(s) per MPI task # GJ thermostat @@ -22,7 +22,6 @@ Finding 1-2 1-3 1-4 neighbors ... 1 = max # of special neighbors special bonds CPU = 0.000 seconds read_data CPU = 0.007 seconds - include ff-argon.lmp ############################# #Atoms types - mass - charge# @@ -47,33 +46,33 @@ pair_coeff * * 0.0102701 3.42 velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 -fix lang all langevin/gjf 10 10 1 26488 vel vfull method 4 +compute myKE all ke +compute myPE all pe -thermo 200 +fix lang all langevin/gjf 10 10 1 26488 vel vfull method 1 + +thermo 2000 run 5000 CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE Your simulation uses code contributions which should be cited: -- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 +- Langevin GJ methods: doi:10.1080/00268976.2019.1662506 -@Article{gronbech_jensen_2024, -title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, -volume = {191}, -number = {10}, -url = {https://doi.org/10.1007/s10955-024-03345-1}, -doi = {10.1007/s10955-024-03345-1}, -urldate = {2024-10-22}, -journal = {J. Stat. Phys.}, -author = {Gronbech-Jensen, Niels}, -year = {2024}, -pages = {137} +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020}, } CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE @@ -94,46 +93,24 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes Step Temp E_pair E_mol TotEng Press 0 10 -56.207652 0 -55.092137 33.341103 - 200 8.3566091 -55.074758 0 -54.142565 340.34804 - 400 8.5550582 -55.098903 0 -54.144573 333.63174 - 600 8.7873675 -55.044559 0 -54.064315 350.7384 - 800 8.7258741 -55.149735 0 -54.17635 318.83613 - 1000 8.3748307 -55.059754 0 -54.125529 343.7989 - 1200 8.6082188 -55.156326 0 -54.196066 316.8728 - 1400 8.9291902 -55.11836 0 -54.122295 328.12488 - 1600 8.3386383 -55.119788 0 -54.189601 325.81369 - 1800 8.0698034 -55.076285 0 -54.176086 338.69767 - 2000 8.5103978 -55.084479 0 -54.135131 338.12197 - 2200 8.3201517 -55.104858 0 -54.176733 329.95905 - 2400 8.7070407 -55.120649 0 -54.149366 328.06488 - 2600 8.4244379 -55.147583 0 -54.207824 321.45013 - 2800 8.7911907 -55.127309 0 -54.146638 325.76049 - 3000 8.250829 -55.1039 0 -54.183508 332.05048 - 3200 8.693979 -55.155552 0 -54.185726 318.29736 - 3400 8.9806023 -55.127303 0 -54.125504 327.48861 - 3600 8.8313967 -55.081076 0 -54.09592 339.16793 - 3800 8.8008688 -55.176748 0 -54.194998 313.08151 - 4000 8.1780418 -55.105368 0 -54.193096 330.04164 - 4200 8.3772045 -55.128813 0 -54.194323 324.29069 - 4400 8.3580983 -55.086979 0 -54.154621 335.63911 - 4600 8.1493124 -55.096648 0 -54.18758 332.51502 - 4800 9.0189389 -55.126828 0 -54.120752 326.36041 - 5000 8.7587383 -55.084993 0 -54.107943 337.17399 -Loop time of 2.34344 on 1 procs for 5000 steps with 864 atoms + 2000 8.5329244 -55.06102 0 -54.10916 343.01505 + 4000 7.8165794 -55.128803 0 -54.256851 322.07344 + 5000 8.4535562 -55.150518 0 -54.207511 318.20862 +Loop time of 2.26625 on 1 procs for 5000 steps with 864 atoms -Performance: 18434.456 ns/day, 0.001 hours/ns, 2133.618 timesteps/s, 1.843 Matom-step/s -99.9% CPU use with 1 MPI tasks x 1 OpenMP threads +Performance: 19062.331 ns/day, 0.001 hours/ns, 2206.288 timesteps/s, 1.906 Matom-step/s +100.0% CPU use with 1 MPI tasks x 1 OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 1.3044 | 1.3044 | 1.3044 | 0.0 | 55.66 -Bond | 0.00055276 | 0.00055276 | 0.00055276 | 0.0 | 0.02 -Neigh | 0.27376 | 0.27376 | 0.27376 | 0.0 | 11.68 -Comm | 0.055077 | 0.055077 | 0.055077 | 0.0 | 2.35 -Output | 0.00055401 | 0.00055401 | 0.00055401 | 0.0 | 0.02 -Modify | 0.68502 | 0.68502 | 0.68502 | 0.0 | 29.23 -Other | | 0.02412 | | | 1.03 +Pair | 1.2907 | 1.2907 | 1.2907 | 0.0 | 56.95 +Bond | 0.00032498 | 0.00032498 | 0.00032498 | 0.0 | 0.01 +Neigh | 0.28343 | 0.28343 | 0.28343 | 0.0 | 12.51 +Comm | 0.055491 | 0.055491 | 0.055491 | 0.0 | 2.45 +Output | 8.5614e-05 | 8.5614e-05 | 8.5614e-05 | 0.0 | 0.00 +Modify | 0.61129 | 0.61129 | 0.61129 | 0.0 | 26.97 +Other | | 0.02497 | | | 1.10 Nlocal: 864 ave 864 max 864 min Histogram: 1 0 0 0 0 0 0 0 0 0 @@ -145,8 +122,60 @@ Histogram: 1 0 0 0 0 0 0 0 0 0 Total # of neighbors = 18143 Ave neighs/atom = 20.998843 Ave special neighs/atom = 0 -Neighbor list builds = 257 +Neighbor list builds = 258 Dangerous builds = 0 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE file ave.out -Total wall time: 0:00:02 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 8.4535562 -55.150518 0 -54.207511 318.20862 + 6000 8.4899401 -55.108242 0 -54.161176 331.10703 + 8000 8.3618893 -55.092171 0 -54.15939 334.11831 + 10000 8.8684311 -55.100316 0 -54.111029 334.09931 + 12000 8.4339192 -55.07343 0 -54.132614 340.00487 + 14000 8.072393 -55.115121 0 -54.214633 327.98965 + 16000 8.3420289 -55.077813 0 -54.147247 337.74926 + 18000 8.3803911 -55.12201 0 -54.187164 326.10485 + 20000 8.4676985 -55.176339 0 -54.231754 311.57092 + 22000 8.8560138 -55.110505 0 -54.122603 330.66179 + 24000 8.3187826 -55.120592 0 -54.192619 327.01148 + 26000 8.0327666 -55.116664 0 -54.220596 326.25179 + 28000 8.3672169 -55.130413 0 -54.197037 324.2368 + 30000 8.1669275 -55.057678 0 -54.146645 344.9168 + 32000 8.3819314 -55.08989 0 -54.154873 335.45317 + 34000 8.109088 -55.17222 0 -54.267639 310.83717 + 36000 8.3048574 -55.079475 0 -54.153056 338.04291 + 38000 8.8708544 -55.108991 0 -54.119434 330.70097 + 40000 8.4012779 -55.080817 0 -54.143642 338.54326 +Loop time of 19.3814 on 1 procs for 35000 steps with 864 atoms + +Performance: 15602.554 ns/day, 0.002 hours/ns, 1805.851 timesteps/s, 1.560 Matom-step/s +100.0% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 12.065 | 12.065 | 12.065 | 0.0 | 62.25 +Bond | 0.0021494 | 0.0021494 | 0.0021494 | 0.0 | 0.01 +Neigh | 2.3755 | 2.3755 | 2.3755 | 0.0 | 12.26 +Comm | 0.40916 | 0.40916 | 0.40916 | 0.0 | 2.11 +Output | 0.0004907 | 0.0004907 | 0.0004907 | 0.0 | 0.00 +Modify | 4.3528 | 4.3528 | 4.3528 | 0.0 | 22.46 +Other | | 0.1765 | | | 0.91 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1592 ave 1592 max 1592 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18144 ave 18144 max 18144 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 2122 +Dangerous builds = 0 +Total wall time: 0:00:21 diff --git a/examples/gjf/log.2Apr25.gjf.vfull.g++.4 b/examples/gjf/log.2Apr25.gjf.vfull.g++.4 index 6d9543c087..454887a106 100644 --- a/examples/gjf/log.2Apr25.gjf.vfull.g++.4 +++ b/examples/gjf/log.2Apr25.gjf.vfull.g++.4 @@ -1,4 +1,4 @@ -LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +LAMMPS (2 Apr 2025 - Development - 09d3ac0a1b-modified) OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) using 1 OpenMP thread(s) per MPI task # GJ thermostat @@ -22,7 +22,6 @@ Finding 1-2 1-3 1-4 neighbors ... 1 = max # of special neighbors special bonds CPU = 0.002 seconds read_data CPU = 0.014 seconds - include ff-argon.lmp ############################# #Atoms types - mass - charge# @@ -47,33 +46,33 @@ pair_coeff * * 0.0102701 3.42 velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 -fix lang all langevin/gjf 10 10 1 26488 vel vfull method 4 +compute myKE all ke +compute myPE all pe -thermo 200 +fix lang all langevin/gjf 10 10 1 26488 vel vfull method 1 + +thermo 2000 run 5000 CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE Your simulation uses code contributions which should be cited: -- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 +- Langevin GJ methods: doi:10.1080/00268976.2019.1662506 -@Article{gronbech_jensen_2024, -title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, -volume = {191}, -number = {10}, -url = {https://doi.org/10.1007/s10955-024-03345-1}, -doi = {10.1007/s10955-024-03345-1}, -urldate = {2024-10-22}, -journal = {J. Stat. Phys.}, -author = {Gronbech-Jensen, Niels}, -year = {2024}, -pages = {137} +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020}, } CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE @@ -94,59 +93,89 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 6.427 | 6.427 | 6.427 Mbytes Step Temp E_pair E_mol TotEng Press 0 10 -56.207652 0 -55.092137 33.341103 - 200 8.3950866 -55.088994 0 -54.15251 334.90536 - 400 8.6408464 -55.090811 0 -54.126912 335.23135 - 600 8.3101447 -55.121286 0 -54.194277 325.43222 - 800 8.5045003 -55.090513 0 -54.141824 335.05857 - 1000 8.7236378 -55.101455 0 -54.12832 331.96596 - 1200 8.7063561 -55.109371 0 -54.138164 331.62683 - 1400 8.7935957 -55.089763 0 -54.108824 336.89842 - 1600 8.454418 -55.105207 0 -54.162104 330.18927 - 1800 8.7989267 -55.142078 0 -54.160544 322.47021 - 2000 8.7823094 -55.153625 0 -54.173945 318.95028 - 2200 8.6201117 -55.11511 0 -54.153524 329.13488 - 2400 9.1165215 -55.161069 0 -54.144107 318.48524 - 2600 8.7636341 -55.142401 0 -54.164805 322.46493 - 2800 8.4876731 -55.111528 0 -54.164715 329.66127 - 3000 8.7005957 -55.149445 0 -54.178881 319.92878 - 3200 8.1711364 -55.137611 0 -54.226108 322.83713 - 3400 8.7172512 -55.143449 0 -54.171026 322.68918 - 3600 8.6262526 -55.1002 0 -54.137928 333.02737 - 3800 8.1680259 -55.166423 0 -54.255267 313.66684 - 4000 8.8340067 -55.121759 0 -54.136312 328.58235 - 4200 8.427926 -55.126903 0 -54.186755 324.95528 - 4400 8.6352614 -55.193826 0 -54.23055 307.14392 - 4600 8.7381405 -55.120503 0 -54.14575 327.73985 - 4800 8.3857194 -55.081944 0 -54.146505 337.38629 - 5000 8.1179517 -55.162247 0 -54.256677 314.50176 -Loop time of 2.08834 on 4 procs for 5000 steps with 864 atoms + 2000 8.63533 -55.154093 0 -54.190809 317.34773 + 4000 8.2482881 -55.091551 0 -54.171442 333.83766 + 5000 7.946377 -55.076514 0 -54.190084 337.31999 +Loop time of 2.06641 on 4 procs for 5000 steps with 864 atoms -Performance: 20686.324 ns/day, 0.001 hours/ns, 2394.250 timesteps/s, 2.069 Matom-step/s -63.4% CPU use with 4 MPI tasks x 1 OpenMP threads +Performance: 20905.811 ns/day, 0.001 hours/ns, 2419.654 timesteps/s, 2.091 Matom-step/s +62.1% CPU use with 4 MPI tasks x 1 OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.53532 | 0.5439 | 0.54781 | 0.7 | 26.04 -Bond | 0.0006347 | 0.00066042 | 0.00068198 | 0.0 | 0.03 -Neigh | 0.10879 | 0.11194 | 0.118 | 1.1 | 5.36 -Comm | 0.94935 | 0.96017 | 0.97155 | 0.8 | 45.98 -Output | 0.0060135 | 0.006061 | 0.0061217 | 0.1 | 0.29 -Modify | 0.2483 | 0.24911 | 0.25049 | 0.2 | 11.93 -Other | | 0.2165 | | | 10.37 +Pair | 0.53593 | 0.54393 | 0.55031 | 0.7 | 26.32 +Bond | 0.0004435 | 0.00052388 | 0.000586 | 0.0 | 0.03 +Neigh | 0.10844 | 0.11152 | 0.11687 | 1.0 | 5.40 +Comm | 0.94337 | 0.94742 | 0.94979 | 0.3 | 45.85 +Output | 0.00076423 | 0.00077499 | 0.00078949 | 0.0 | 0.04 +Modify | 0.24993 | 0.25116 | 0.25286 | 0.2 | 12.15 +Other | | 0.2111 | | | 10.21 Nlocal: 216 ave 216 max 216 min Histogram: 4 0 0 0 0 0 0 0 0 0 -Nghost: 884.25 ave 892 max 875 min -Histogram: 1 1 0 0 0 0 0 0 0 2 -Neighs: 4535.5 ave 4737 max 4333 min +Nghost: 884.75 ave 885 max 884 min +Histogram: 1 0 0 0 0 0 0 0 0 3 +Neighs: 4536 ave 4737 max 4335 min Histogram: 2 0 0 0 0 0 0 0 0 2 -Total # of neighbors = 18142 -Ave neighs/atom = 20.997685 +Total # of neighbors = 18144 +Ave neighs/atom = 21 Ave special neighs/atom = 0 -Neighbor list builds = 280 +Neighbor list builds = 273 Dangerous builds = 0 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE file ave.out -Total wall time: 0:00:02 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.428 | 6.428 | 6.428 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 7.946377 -55.076514 0 -54.190084 337.31999 + 6000 8.2565866 -55.129244 0 -54.208209 324.57967 + 8000 7.9942397 -55.101417 0 -54.209648 331.24127 + 10000 8.5413968 -55.083292 0 -54.130486 337.82599 + 12000 8.3682078 -55.090905 0 -54.157419 335.08066 + 14000 8.5082065 -55.085051 0 -54.135948 336.2765 + 16000 8.1944037 -55.090733 0 -54.176635 334.03786 + 18000 8.2607106 -55.030131 0 -54.108637 352.49892 + 20000 8.1154691 -55.104072 0 -54.198779 330.14203 + 22000 8.5592601 -55.152019 0 -54.197221 318.03507 + 24000 8.3182914 -55.115242 0 -54.187324 328.46084 + 26000 8.3691375 -55.125275 0 -54.191685 325.43673 + 28000 8.531632 -55.107097 0 -54.155381 331.42771 + 30000 8.1102222 -55.099011 0 -54.194304 332.04678 + 32000 8.5558571 -55.077016 0 -54.122598 339.87746 + 34000 8.4213946 -55.097068 0 -54.157649 333.34935 + 36000 8.0936615 -55.152202 0 -54.249342 316.20169 + 38000 7.999652 -55.048407 0 -54.156034 345.07945 + 40000 8.6699753 -55.087634 0 -54.120485 337.23709 +Loop time of 17.4329 on 4 procs for 35000 steps with 864 atoms + +Performance: 17346.528 ns/day, 0.001 hours/ns, 2007.700 timesteps/s, 1.735 Matom-step/s +65.5% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 5.1129 | 5.1423 | 5.1581 | 0.8 | 29.50 +Bond | 0.0029266 | 0.0034929 | 0.0038279 | 0.6 | 0.02 +Neigh | 0.85004 | 0.87543 | 0.90992 | 2.4 | 5.02 +Comm | 6.6875 | 6.6993 | 6.7123 | 0.4 | 38.43 +Output | 0.0043725 | 0.0045522 | 0.005017 | 0.4 | 0.03 +Modify | 3.2524 | 3.2579 | 3.2677 | 0.3 | 18.69 +Other | | 1.45 | | | 8.32 + +Nlocal: 216 ave 222 max 210 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 905.5 ave 911 max 899 min +Histogram: 1 1 0 0 0 0 0 0 0 2 +Neighs: 4535.75 ave 4837 max 4218 min +Histogram: 1 0 0 1 0 0 1 0 0 1 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 2140 +Dangerous builds = 0 +Total wall time: 0:00:19 diff --git a/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 b/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 index fed8f271e5..5d07985f1c 100644 --- a/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 +++ b/examples/gjf/log.2Apr25.gjf.vhalf.g++.1 @@ -1,4 +1,4 @@ -LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +LAMMPS (2 Apr 2025 - Development - 09d3ac0a1b-modified) OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) using 1 OpenMP thread(s) per MPI task # GJ thermostat @@ -21,8 +21,7 @@ Finding 1-2 1-3 1-4 neighbors ... 0 = max # of 1-4 neighbors 1 = max # of special neighbors special bonds CPU = 0.000 seconds - read_data CPU = 0.008 seconds - + read_data CPU = 0.007 seconds include ff-argon.lmp ############################# #Atoms types - mass - charge# @@ -47,33 +46,32 @@ pair_coeff * * 0.0102701 3.42 velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 +compute myKE all ke +compute myPE all pe + fix lang all langevin/gjf 10 10 1 26488 -thermo 200 run 5000 CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE Your simulation uses code contributions which should be cited: -- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 +- Langevin GJ methods: doi:10.1080/00268976.2019.1662506 -@Article{gronbech_jensen_2024, -title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, -volume = {191}, -number = {10}, -url = {https://doi.org/10.1007/s10955-024-03345-1}, -doi = {10.1007/s10955-024-03345-1}, -urldate = {2024-10-22}, -journal = {J. Stat. Phys.}, -author = {Gronbech-Jensen, Niels}, -year = {2024}, -pages = {137} +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020}, } CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE @@ -94,46 +92,22 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes Step Temp E_pair E_mol TotEng Press 0 10 -56.207652 0 -55.092137 33.341103 - 200 9.8808461 -55.073599 0 -53.971376 345.62224 - 400 9.8712816 -55.072241 0 -53.971084 345.11909 - 600 10.528988 -55.066736 0 -53.892211 350.60112 - 800 10.167171 -55.148312 0 -54.014149 324.73698 - 1000 10.029026 -55.125705 0 -54.006952 331.93785 - 1200 9.8898479 -55.086642 0 -53.983414 342.04309 - 1400 10.610014 -55.076793 0 -53.89323 346.34338 - 1600 9.9402137 -55.111688 0 -54.002842 335.04779 - 1800 9.8078801 -55.140475 0 -54.046391 325.88652 - 2000 10.472791 -55.06102 0 -53.892765 349.97306 - 2200 9.877248 -55.191201 0 -54.089379 312.77421 - 2400 9.9739487 -55.108904 0 -53.996295 335.9089 - 2600 10.131803 -55.149444 0 -54.019226 325.44115 - 2800 9.6980127 -55.118395 0 -54.036568 331.2097 - 3000 9.7193425 -55.149785 0 -54.065577 323.32384 - 3200 10.27638 -55.083302 0 -53.936957 342.56458 - 3400 9.9253941 -55.082368 0 -53.975175 342.28594 - 3600 10.665862 -55.056774 0 -53.866981 352.03551 - 3800 10.011077 -55.084664 0 -53.967913 341.45122 - 4000 9.4182671 -55.128803 0 -54.078181 327.81846 - 4200 10.02466 -55.106046 0 -53.98778 336.56944 - 4400 9.3721033 -55.146068 0 -54.100596 322.38199 - 4600 9.5485537 -55.118577 0 -54.053421 332.04274 - 4800 10.039726 -55.074068 0 -53.954122 344.76817 5000 9.7731898 -55.150518 0 -54.060304 322.94195 -Loop time of 2.28614 on 1 procs for 5000 steps with 864 atoms +Loop time of 2.32188 on 1 procs for 5000 steps with 864 atoms -Performance: 18896.448 ns/day, 0.001 hours/ns, 2187.089 timesteps/s, 1.890 Matom-step/s -100.0% CPU use with 1 MPI tasks x 1 OpenMP threads +Performance: 18605.621 ns/day, 0.001 hours/ns, 2153.428 timesteps/s, 1.861 Matom-step/s +99.8% CPU use with 1 MPI tasks x 1 OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 1.2918 | 1.2918 | 1.2918 | 0.0 | 56.51 -Bond | 0.00048345 | 0.00048345 | 0.00048345 | 0.0 | 0.02 -Neigh | 0.2776 | 0.2776 | 0.2776 | 0.0 | 12.14 -Comm | 0.055375 | 0.055375 | 0.055375 | 0.0 | 2.42 -Output | 0.00054609 | 0.00054609 | 0.00054609 | 0.0 | 0.02 -Modify | 0.63625 | 0.63625 | 0.63625 | 0.0 | 27.83 -Other | | 0.02408 | | | 1.05 +Pair | 1.3154 | 1.3154 | 1.3154 | 0.0 | 56.65 +Bond | 0.00030719 | 0.00030719 | 0.00030719 | 0.0 | 0.01 +Neigh | 0.28939 | 0.28939 | 0.28939 | 0.0 | 12.46 +Comm | 0.055279 | 0.055279 | 0.055279 | 0.0 | 2.38 +Output | 4.3714e-05 | 4.3714e-05 | 4.3714e-05 | 0.0 | 0.00 +Modify | 0.63675 | 0.63675 | 0.63675 | 0.0 | 27.42 +Other | | 0.02471 | | | 1.06 Nlocal: 864 ave 864 max 864 min Histogram: 1 0 0 0 0 0 0 0 0 0 @@ -148,5 +122,58 @@ Ave special neighs/atom = 0 Neighbor list builds = 258 Dangerous builds = 0 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE file ave.out -Total wall time: 0:00:02 +thermo 2000 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.481 | 6.481 | 6.481 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 9.7731898 -55.150518 0 -54.060304 322.94195 + 6000 10.024842 -55.108242 0 -53.989956 336.6125 + 8000 10.118994 -55.092171 0 -53.963382 340.42078 + 10000 10.541359 -55.100316 0 -53.924412 340.09986 + 12000 10.023234 -55.07343 0 -53.955323 345.70551 + 14000 9.5912018 -55.115121 0 -54.045208 333.43739 + 16000 9.9450498 -55.077813 0 -53.968428 343.49906 + 18000 10.113744 -55.12201 0 -53.993806 332.32214 + 20000 9.9345204 -55.176339 0 -54.068128 316.83219 + 22000 10.585719 -55.110505 0 -53.929652 336.86599 + 24000 10.024757 -55.120592 0 -54.002315 333.13056 + 26000 9.7787474 -55.116664 0 -54.02583 332.51437 + 28000 9.6092087 -55.130413 0 -54.058491 328.69165 + 30000 9.8245787 -55.057678 0 -53.961731 350.86255 + 32000 10.066994 -55.08989 0 -53.966902 341.49724 + 34000 9.5677059 -55.17222 0 -54.104928 316.06902 + 36000 9.7252627 -55.079475 0 -53.994608 343.13769 + 38000 10.438984 -55.108991 0 -53.944506 336.32562 + 40000 10.238268 -55.080817 0 -53.938723 345.13228 +Loop time of 19.5673 on 1 procs for 35000 steps with 864 atoms + +Performance: 15454.339 ns/day, 0.002 hours/ns, 1788.697 timesteps/s, 1.545 Matom-step/s +99.9% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 12.065 | 12.065 | 12.065 | 0.0 | 61.66 +Bond | 0.002157 | 0.002157 | 0.002157 | 0.0 | 0.01 +Neigh | 2.384 | 2.384 | 2.384 | 0.0 | 12.18 +Comm | 0.40912 | 0.40912 | 0.40912 | 0.0 | 2.09 +Output | 0.00050573 | 0.00050573 | 0.00050573 | 0.0 | 0.00 +Modify | 4.5321 | 4.5321 | 4.5321 | 0.0 | 23.16 +Other | | 0.1749 | | | 0.89 + +Nlocal: 864 ave 864 max 864 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1592 ave 1592 max 1592 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18144 ave 18144 max 18144 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 18144 +Ave neighs/atom = 21 +Ave special neighs/atom = 0 +Neighbor list builds = 2122 +Dangerous builds = 0 +Total wall time: 0:00:21 diff --git a/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 b/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 index aa90fb779b..cac135e578 100644 --- a/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 +++ b/examples/gjf/log.2Apr25.gjf.vhalf.g++.4 @@ -1,4 +1,4 @@ -LAMMPS (2 Apr 2025 - Development - 4dd8c66390-modified) +LAMMPS (2 Apr 2025 - Development - 09d3ac0a1b-modified) OMP_NUM_THREADS environment is not set. Defaulting to 1 thread. (src/comm.cpp:99) using 1 OpenMP thread(s) per MPI task # GJ thermostat @@ -22,7 +22,6 @@ Finding 1-2 1-3 1-4 neighbors ... 1 = max # of special neighbors special bonds CPU = 0.002 seconds read_data CPU = 0.014 seconds - include ff-argon.lmp ############################# #Atoms types - mass - charge# @@ -47,33 +46,32 @@ pair_coeff * * 0.0102701 3.42 velocity all create 10 2357 mom yes dist gaussian - neighbor 1 bin timestep 0.1 +compute myKE all ke +compute myPE all pe + fix lang all langevin/gjf 10 10 1 26488 -thermo 200 run 5000 CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE Your simulation uses code contributions which should be cited: -- Langevin GJF methods: doi:10.1007/s10955-024-03345-1 +- Langevin GJ methods: doi:10.1080/00268976.2019.1662506 -@Article{gronbech_jensen_2024, -title = {On the Definition of Velocity in Discrete-Time, Stochastic Langevin Simulations}, -volume = {191}, -number = {10}, -url = {https://doi.org/10.1007/s10955-024-03345-1}, -doi = {10.1007/s10955-024-03345-1}, -urldate = {2024-10-22}, -journal = {J. Stat. Phys.}, -author = {Gronbech-Jensen, Niels}, -year = {2024}, -pages = {137} +@Article{gronbech-jensen_complete_2020, +title = {Complete set of stochastic Verlet-type thermostats for correct Langevin simulations}, +volume = {118}, +number = {8}, +url = {https://www.tandfonline.com/doi/full/10.1080/00268976.2019.1662506}, +doi = {10.1080/00268976.2019.1662506}, +journal = {Molecular Physics}, +author = {Grønbech-Jensen, Niels}, +year = {2020}, } CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE @@ -94,46 +92,22 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 6.427 | 6.427 | 6.427 Mbytes Step Temp E_pair E_mol TotEng Press 0 10 -56.207652 0 -55.092137 33.341103 - 200 9.8046819 -55.12733 0 -54.033603 329.70683 - 400 10.174622 -55.092357 0 -53.957363 340.4935 - 600 9.6157634 -55.174205 0 -54.101552 316.68047 - 800 9.9617862 -55.097525 0 -53.986273 339.257 - 1000 10.373198 -55.116484 0 -53.959338 335.09796 - 1200 10.064779 -55.17366 0 -54.050919 318.66487 - 1400 10.562182 -55.067856 0 -53.889628 349.23452 - 1600 9.7696935 -55.081542 0 -53.991718 342.92593 - 1800 10.454466 -55.130637 0 -53.964426 330.88658 - 2000 10.253701 -55.154093 0 -54.010277 323.15259 - 2200 9.6688957 -55.143479 0 -54.064899 325.16815 - 2400 10.059787 -55.134941 0 -54.012756 329.83534 - 2600 9.9050905 -55.096231 0 -53.991303 338.94947 - 2800 9.663551 -55.130202 0 -54.052218 328.77571 - 3000 9.950484 -55.123447 0 -54.013455 332.00143 - 3200 9.7210637 -55.120005 0 -54.035606 331.39812 - 3400 9.6457139 -55.080953 0 -54.004959 341.95838 - 3600 10.42249 -55.102379 0 -53.939734 339.66808 - 3800 10.276893 -55.126271 0 -53.979868 332.40943 - 4000 10.135481 -55.091551 0 -53.960922 340.60675 - 4200 10.129209 -55.084189 0 -53.95426 343.39315 - 4400 10.006953 -55.120704 0 -54.004413 331.57121 - 4600 10.497483 -55.144898 0 -53.973888 327.22996 - 4800 9.9230954 -55.126028 0 -54.019091 330.70489 5000 9.3726166 -55.076514 0 -54.030985 342.43571 -Loop time of 2.0887 on 4 procs for 5000 steps with 864 atoms +Loop time of 2.09273 on 4 procs for 5000 steps with 864 atoms -Performance: 20682.713 ns/day, 0.001 hours/ns, 2393.833 timesteps/s, 2.068 Matom-step/s -62.5% CPU use with 4 MPI tasks x 1 OpenMP threads +Performance: 20642.908 ns/day, 0.001 hours/ns, 2389.226 timesteps/s, 2.064 Matom-step/s +62.7% CPU use with 4 MPI tasks x 1 OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.53905 | 0.54518 | 0.5484 | 0.5 | 26.10 -Bond | 0.00062355 | 0.00066183 | 0.0007207 | 0.0 | 0.03 -Neigh | 0.10715 | 0.10937 | 0.11212 | 0.5 | 5.24 -Comm | 0.94637 | 0.95041 | 0.95905 | 0.5 | 45.50 -Output | 0.0061059 | 0.0061286 | 0.0061661 | 0.0 | 0.29 -Modify | 0.26086 | 0.26355 | 0.26979 | 0.7 | 12.62 -Other | | 0.2134 | | | 10.22 +Pair | 0.53092 | 0.54173 | 0.55017 | 1.0 | 25.89 +Bond | 0.00049283 | 0.00052862 | 0.00057217 | 0.0 | 0.03 +Neigh | 0.10693 | 0.11084 | 0.1158 | 1.0 | 5.30 +Comm | 0.95622 | 0.96088 | 0.96553 | 0.4 | 45.92 +Output | 0.00027302 | 0.00027645 | 0.00028114 | 0.0 | 0.01 +Modify | 0.2615 | 0.26289 | 0.2635 | 0.2 | 12.56 +Other | | 0.2156 | | | 10.30 Nlocal: 216 ave 216 max 216 min Histogram: 4 0 0 0 0 0 0 0 0 0 @@ -148,5 +122,58 @@ Ave special neighs/atom = 0 Neighbor list builds = 273 Dangerous builds = 0 +fix energies all ave/time 1 20000 20000 c_myKE c_myPE file ave.out -Total wall time: 0:00:02 +thermo 2000 +run 35000 +Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule +Per MPI rank memory allocation (min/avg/max) = 6.428 | 6.428 | 6.428 Mbytes + Step Temp E_pair E_mol TotEng Press + 5000 9.3726166 -55.076514 0 -54.030985 342.43571 + 6000 9.6911866 -55.129244 0 -54.048177 329.72537 + 8000 9.7296551 -55.101417 0 -54.016059 337.46595 + 10000 10.098808 -55.083292 0 -53.956755 343.4122 + 12000 10.114344 -55.090905 0 -53.962635 341.3438 + 14000 10.230012 -55.085051 0 -53.943878 342.45237 + 16000 9.5989709 -55.090733 0 -54.019954 339.07584 + 18000 10.016071 -55.030131 0 -53.912824 358.79514 + 20000 9.7197057 -55.104072 0 -54.019824 335.89619 + 22000 9.959647 -55.152019 0 -54.041005 323.05805 + 24000 10.075138 -55.115242 0 -53.991345 334.76239 + 26000 10.227192 -55.125275 0 -53.984416 332.10131 + 28000 10.177109 -55.107097 0 -53.971825 337.32979 + 30000 9.521036 -55.099011 0 -54.036925 337.10716 + 32000 10.265633 -55.077016 0 -53.93187 346.01018 + 34000 10.173978 -55.097068 0 -53.962146 339.63562 + 36000 9.6032778 -55.152202 0 -54.080942 321.61646 + 38000 9.8802995 -55.048407 0 -53.946245 351.82506 + 40000 10.372288 -55.087634 0 -53.93059 343.34304 +Loop time of 17.6209 on 4 procs for 35000 steps with 864 atoms + +Performance: 17161.415 ns/day, 0.001 hours/ns, 1986.275 timesteps/s, 1.716 Matom-step/s +64.2% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 5.0439 | 5.1029 | 5.1534 | 2.0 | 28.96 +Bond | 0.0031373 | 0.0034925 | 0.0038794 | 0.5 | 0.02 +Neigh | 0.84082 | 0.87558 | 0.91665 | 3.0 | 4.97 +Comm | 6.7337 | 6.7936 | 6.8487 | 1.6 | 38.55 +Output | 0.0044073 | 0.004559 | 0.0049773 | 0.4 | 0.03 +Modify | 3.3556 | 3.3647 | 3.3722 | 0.3 | 19.10 +Other | | 1.476 | | | 8.38 + +Nlocal: 216 ave 222 max 210 min +Histogram: 2 0 0 0 0 0 0 0 0 2 +Nghost: 905.5 ave 911 max 899 min +Histogram: 1 1 0 0 0 0 0 0 0 2 +Neighs: 4535.75 ave 4837 max 4218 min +Histogram: 1 0 0 1 0 0 1 0 0 1 + +Total # of neighbors = 18143 +Ave neighs/atom = 20.998843 +Ave special neighs/atom = 0 +Neighbor list builds = 2140 +Dangerous builds = 0 +Total wall time: 0:00:19 diff --git a/src/EXTRA-FIX/fix_langevin_gjf.cpp b/src/EXTRA-FIX/fix_langevin_gjf.cpp index c00fbb9ee5..ea0e75c598 100644 --- a/src/EXTRA-FIX/fix_langevin_gjf.cpp +++ b/src/EXTRA-FIX/fix_langevin_gjf.cpp @@ -139,7 +139,7 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg], "method") == 0) { GJmethod = utils::inumeric(FLERR, arg[iarg + 1], false, lmp); - if (GJmethod = 7) { + if (GJmethod == 7) { if (iarg + 3 > narg) error->all(FLERR, "Illegal fix langevin/gjf command for GJ-VII"); gjfc2 = utils::numeric(FLERR, arg[iarg + 2], false, lmp); if (gjfc2 < 0 || gjfc2 > 1) error->all(FLERR, "Choice of c2 in GJ-VII must be 0≤c2≤1"); @@ -149,7 +149,7 @@ FixLangevinGJF::FixLangevinGJF(LAMMPS *lmp, int narg, char **arg) : else { if (iarg + 2 > narg) error->all(FLERR, "Illegal fix langevin/gjf command"); if (GJmethod < 0 || GJmethod > GJmethods) error->all(FLERR, "Invalid GJ method choice in langevin/gjf command"); - if (GJmethod = 8) if (lmp->citeme) lmp->citeme->add(cite_langevin_gjf_8); + if (GJmethod == 8) if (lmp->citeme) lmp->citeme->add(cite_langevin_gjf_8); iarg += 2; } } else From 3a6ea0808daa42d5f681ec76cd53e4a8760989c8 Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Mon, 14 Apr 2025 15:36:33 -0600 Subject: [PATCH 140/396] Merged changes to documentation for further user clarity --- doc/src/fix_neighbor_swap.rst | 268 +++++++++++++++++----------------- 1 file changed, 136 insertions(+), 132 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index 9c87547321..da1e89bed5 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -18,19 +18,19 @@ Syntax * T = scaling temperature of the MC swaps (temperature units) * R0 = scaling swap probability of the MC swaps (distance units) * voro = valid voronoi compute id (compute voronoi/atom) -* one or more keyword/value pairs may be appended to args +* two or more keyword/value pairs may be appended to args * keywords *types* and *diff* are mutually exclusive, but one must be specified -* keyword = *types* or *diff* or *rates* or *ke* or *region* +* keyword = *types* or *diff* or *ke* or *region* or *rates* .. parsed-literal:: - *types* values = two or more atom types (1-Ntypes or type label) - *ke* value = *no* or *yes* - *no* = no conservation of kinetic energy after atom swaps + *types* values = two or more atom types (Integers in range [1,Ntypes] or type labels) + *diff* values = one atom type + *ke* value = *yes* or *no* *yes* = kinetic energy is conserved after atom swaps + *no* = no conservation of kinetic energy after atom swaps *region* value = region-ID region-ID = ID of region to use as an exchange/move volume - *diff* values = one atom type *rates* values = V1 V2 . . . Vntypes values to conduct variable diffusion for different atom types (unitless) Examples @@ -38,6 +38,7 @@ Examples .. code-block:: LAMMPS + compute voroN all voronoi/atom neighbors yes fix mc all neighbor/swap 10 160 15238 1000.0 3.0 diff 2 voro voroN fix myFix all neighbor/swap 100 1 12345 298.0 3.0 region my_swap_region types 5 6 voro voroN fix kmc all neighbor/swap 1 100 345 1.0 3.0 diff 3 rates 3 1 6 voro voroN @@ -47,140 +48,144 @@ Description .. versionadded:: TBD -This fix computes Monte-Carlo (MC) evaluations to enable kinetic -Monte Carlo (kMC)-type behavior during MD simulation through only allowing -neighboring atom swaps. This creates a hybrid type simulation of MDkMC simulation -where atoms are only swapped with their neighbors, but the swapping acceptance is -perfomed by evaluating the change in system energy using the Metropolis Criterion. -Neighboring atoms are selected using a Voronoi tesselation approach. A detailed -explination of the original implementation of this procedure can be found in -:ref:`(Tavenner 2023) <_TavennerMDkMC>` as originally intended for simulating -accelerated diffusion in an MD context. +This fix performs Monte-Carlo (MC) evaluations to enable kinetic +Monte Carlo (kMC)-type behavior during MD simulation by allowing +neighboring atoms to swap their positions. In constrast to the :doc:`fix +atom/swap ` command which swaps pairs of atoms anywhere +in the simulation domain, the restriction of the MC swapping to +neighbors enables a hybrid MD/kMC-like simulation. -Simulating inherently kineticly driven behaviors which rely on rare events -(such as atomic diffusion) is challenging for traditional Molecular Dynamics -approaches since simulations are restricted in their time-scale of events. -Since thermal vibration motion occurs on a timescale much shorter than the movement -of vacancies, such behaviors are challenging to model simultaneously. To address -this challenge, an approach from kMC simulations is adpoted where rare events can -be sampled at selected rates. By selecting such swap behaviors, the process -of atomic diffusion can be approximated during an MD simulation, effectively -decoupling the MD atomic vibrational time and the timescale of atomic hopping. +Neighboring atoms are defined by using a Voronoi tesselation performed +by the :doc:`compute voronoi/atom ` command. +Two atoms are neighbors if their Voronoi cells share a common face +(3d) or edge (2d). -To achieve such simulations, this algorithm takes the following approach. First, -the MD simulation is stopped after a given number of steps to perform atom swaps. -Given this instantaneous configuration from the MD simulation, Voronoi neighbors -are computed for all valid swap atoms. From the list of valid swap atoms, one atom -I is selected at random across the entire simulation. One if its Voronoi neighbors -that is a valid atom to swap is then selected. The atom ID is communicated to all -processors, such that if the neighbors are on different processors the swap still -occurs. The two atom types are swapped, and the change in system energy from before -the swap is compared using the Metropolis Criterion. This evaluation of the energy -change is a global calculation, such that it has a computational cost similar to -that of an MD timestep. If the swap is accepted from the Metropolis Criterion, the -atoms remain swapped. Else, the atoms are returned to their original types. This -process of MC evaluation is repeated for a given number of iterations until the -original MD simulation is resumed from the new state, where any successfully -swapped atoms have changed type, though the global system balance is preserved. +The selection of a swap neighbor is made using a distance-based +criterion for weighting the selection probability of each swap, in the +same manner as kMC selects a next event using relative probabilities. +The acceptance or rejection of each swap is determined via the +Metropolis criterion after evaluating the change in system energy due +to the swap. -A few key notes regarding this implementation are as follows. The parallel -efficiency of this algorithm is similar to that of other MC approaches. I.e, -due to the additional energy calculations for the MC steps, efficiency is -improved with a smaller number of atoms per processor than standalone MD simulation -since there is more weighting on the calculation of a given atomic domain and -minor additonal communication load. Communication of the atom ids to be swapped -between processors is negligible. Efficiency will additionally be much worse for -pair styles with different per-atom cutoffs, since the neighbor list will need to -be rebuilt between swap events. Limitations are imposed on the Voronoi neighbors -to restrict swapping of atoms which are outside of a reasonable cutoff. +A detailed explanation of the original implementation of this +algorithm can be found in :ref:`(Tavenner 2023) <_TavennerMDkMC>` +where it was used to simulated accelerated diffusion in an MD context. -Input Parameters Usage -""""""""""" +Simulating inherently kinetically-limited behaviors which rely on rare +events (such as atomic diffusion in a solid) is challenging for +traditional MD since its relatively short timescale will not naturally +sample many events. This fix addresses this challenge by allowing rare +neighbor hopping events to be sampled in a kMC-like fashion at a much +faster rate (set by the specified *N* and *X* parameters). This enables +the processes of atomic diffusion to be approximated during an MD +simulation, effectively decoupling the MD atomic vibrational timescale +and the atomic hopping (kMC event) timescale. -The fix is called every *N* timesteps and attempts *X* swaps. The system -is initialized with a random seed, using a temperature *T* for -evaluating the MC energy swaps. The distance-based probability is -weighted according to *R0* which sets the radius :math:`r_0` for the -weighting +The algorithm implemented by this fix is as follows. The MD +simulation is paused every *N* stepsA Voronoi tesselation is +performed for the current atom configuration. Then *X* atom swaps are +attempted, one after the other. For each swap, an atom *I* is +selected randomly from the list of atom types specified by either the +*types* or *diff* keywords. One of *I*'s Voronoi neighbors *J* is +selected using the distance-weighted probability for each neighbor +detailed below. The *I,J* atom IDs are communicated to all processors +so that a global energy evaluation can be performed for the post-swap +state of the system. The swap is accepted or rejected based on the +Metropolis criterion using the energy change of the system and the +specified temperature *T*. + +Here are a few comments on the computational cost of the swapping +algorithm. + +(1) The cost of a global energy evaluation is similar to that of an MD +timestep. + +(2) Simliar to other MC algorithms in LAMMPS, an optimized parallel efficiency +is achieved with a smaller number of atoms per processor than would typically +be used in an standard MD simulation. This is because the per-energy evaluation +cost increases relative to the balance of MD/MC steps as indicated by (1), but +the communication cost remains relatively constant for a given number of MD steps. + +(3) The MC portion of the simulation will run dramatically slower if +the pair style uses different cutoffs for different atom types (or +type pairs). This is because each atom swap then requires a rebuild +of the neighbor list to ensure the post-swap global energy can be +computed correctly. + +Limitations are imposed on selection of *I,J* atom pairs to avoid +swapping of atoms which are outside of a reasonable cutoff (e.g. due +to a Voronoi tesselation near free surfaces) though the +use of a distance-weighted probabiltiy scaling. + +---------- + +This section gives more details on other arguments and keywords. + +The random number generator (RNG) used by all the processors for MC +operations is initialized with the specified *seed*. + +The distance-based probability is weighted by the specified *R0* which +sets the radius :math:`r_0` in this formula .. math:: p_{ij} = e^{(\frac{r_{ij}}{r_0})^2} -where :math:`p_{ij}` is the probability of selecting atoms :math:`i` and -:math:`j` for an evaluated swap. +where :math:`p_{ij}` is the probability of selecting atom :math:`j` to +swap with atom :math:`i`. Typically, a value for *R0* around the +average nearest-neighbor spacing is appropriate. Since this is simply +a proability weighting, the swapping behavior is not very sensitive to +the exact value of *R0*. -Typically, a value around the average nearest-neighbor spacing is appropriate -for *R0*. Since this is simply a proability weighting, behavior is not -particularly sensitive to the exact value of *R0*. +The keyword *types* takes two or more atom types as its values. Only +atoms *I* of the first atom type will be selected. Only atoms *J* of the +remaining atom types will be considered as potential swap partners. -The keyword *types* is submitted with two or more atom types as the -value. Atoms of the first atom type are swapped with valid neighbors of -all the remaining atom types. +The keyword *diff* take a single atom type as its value. Only atoms +*I* of the that atom type will be selected. Atoms *J* of all +remaining atom types will be considered as potential swap partners. +This includes the atom type specified with the *diff* keyword to +account for self-diffusive hops between two atoms of the same type. -The keyword *diff* is used for implementation of simulated diffusion of -a given atom type as given by *diff type*. This command selects all atom -types as acceptable swap types to a centrally selected atom of type -*type*. This includes the atom type specified by the diff keyword to -account for self-diffusion hops of an atom type with itself. - -Keyword *voro* is currently required, and is implemented as - -.. code-block:: LAMMPS - - voro compute-ID - -where *compute-ID* is the ID of a corresponding Voronoi computation with -neighbor list, i.e. +The keyword *voro* is required. Its *vID* value is the compute-ID of +a :doc:`compute voronoi/atom ` command like +this: .. code-block:: LAMMPS compute compute-ID group-ID voronoi/atom neighbors yes -The group selected for computing *voro* should correspond to all the -potential atoms to be swapped at the initial step, i.e. +Note that the *neighbors yes* option must be enabled for use with this +fix. The group-ID should include all the atoms which this fix will +potentialy select. I.e. the group-ID used in the voronoi compute should +include the same atoms as that indicated by the *types* keyword. If the +*diff* keyword is used, the group-ID should include atoms of all types +in the simulation. -.. code-block:: LAMMPS +The keyword *ke* takes *yes* (default) or *no* as its value. It two +atoms are swapped with different masses, then a value of *yes* will +rescale their respective velocities to conserve the kinetic energy of +the system. A value of *no* will perform no rescaling, so that +kinetic energy is not conserved. See the restriction on this keyword +below. - group group-ID type 2 +The *region* keyword takes a *region-ID* as its value. If specified, +then only atoms *I* and *J* within the geometric region will be +considered as swap partners. See the :doc:`region ` command +for details. This means the group-ID for the :doc:`compute +voronoi/atom ` command also need only contain +atoms within the region. -for using *fix neighbor/swap* with *diff 2*. - -If atoms in the specified group are not in the voro calculated group -they will not be considered for swapping. - -The keyword *rates* can modify the swap rate for each swapped type by -values where the adjusted rates values are given in order of increasing -atom type. The number of rates provided must equal the number of atom -types in the simulation. In the third provided example above, a -simulation is conducted with three atom types where the third atom type -is the one sampled for attempted swaps. All three atom types are -considered valid swaps, but atoms of type 1 will be selected three times -as often as atoms of type 2. Conversely, atoms of type 3 are six times -more likely to be selected than atoms of type two and twice as likely as -atoms of type 1. - -Finally, the *region* keyword is implemented as in other atomic fixes, -where the *region region-ID* command indicates that atom swaps only be -considered in the area given by *region-ID*. If only atoms of certain -groups are expected to be in this region, the corresponding compute -voronoi command can be adjusted accordingly. - -Either the *types* or *diff* keyword must be specified to select atom -types for swapping - -Keyword Summary -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -types = Select random atom matching first type as type I, remaining -atom types are valid for selecting atom J. -diff = Select random atom of this type as atom I, all atoms are valid -for type J. -ke = re-scale velocities when atoms are swapped based on difference in -mass -region = select only atoms I and J from region -rates = pre-factor modification to the J atom selection probability -based on atom type. +The keyword *rates* can modify the swap rate based on the type of atom +*J*. Ntype values must be specified, where Ntype = the number of atom +types in the system. Each value is used to scale the probability +weighting given by the equation above. In the third example command +above, a simulation has 3 atoms types. Atom *I*s of type 1 are +eligible for swapping. Swaps may occur with atom *J*s of all 3 types. +Assuming all *J* atoms are equidistant from an atom *I*, *J* atoms of +type 1 will be 3x more likely to be selected as a swap partner than +atoms of type 2. And *J* atoms of type 3 will be 6.5x more likely to +be selected than atoms of type 2. If the *rates* keyword is not used, Restart, fix_modify, output, run start/stop, minimize info @@ -215,19 +220,18 @@ Restrictions This fix is part of the MC package. It is only enabled if LAMMPS was built with that package. See the :doc:`Build package ` -doc page for more info. Also this fix requires that the -:ref:`VORONOI package ` is installed, otherwise the fix -will not be compiled. +doc page for more info. Also this fix requires that the :ref:`VORONOI +package ` be installed, otherwise the fix will not be +compiled. -The voronoi command specified by *voro* must return neighboring atoms. - -When this fix is used with a :doc:`hybrid pair style ` -system, only swaps between atom types of the same sub-style (or -combination of sub-styles) are permitted. +The :doc:`compute voronoi/atom ` command +referenced by keyword *voro* must return neighboring atoms as +illustrated in the examples above. If this fix is used with systems that do not have per-type masses -(e.g. atom style sphere), the ke flag must be set to off since the -implemented algorithm will not be able to re-scale velocity properly. +(e.g. atom style sphere), the *ke* keyword must be set to *off* since +the implemented algorithm will not be able to re-scale velocities +properly. Related commands """""""""""""""" @@ -240,11 +244,11 @@ Related commands Default """"""" -The option defaults are *ke* = yes, *rates* = 1 for all -atom types. +The option defaults are *ke* = yes and *rates* = 1 for all atom types. ---------- .. _TavennerMDkMC: -**(Tavenner 2023)** J Tavenner, M Mendelev, J Lawson, Computational Materials Science, 218, 111929 (2023). +**(Tavenner 2023)** J Tavenner, M Mendelev, J Lawson, Computational + Materials Science, 218, 111929 (2023). From 51de62ce057f144ed59f5b4737734315e92bf3b4 Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Mon, 14 Apr 2025 15:58:19 -0600 Subject: [PATCH 141/396] Reconcile version changes to documentation and polish --- doc/src/fix_neighbor_swap.rst | 102 ---------------------------------- 1 file changed, 102 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index 5f0373d13b..da1e89bed5 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -25,13 +25,8 @@ Syntax .. parsed-literal:: *types* values = two or more atom types (Integers in range [1,Ntypes] or type labels) -<<<<<<< HEAD *diff* values = one atom type *ke* value = *yes* or *no* -======= - *ke* value = *no* or *yes* - *no* = no conservation of kinetic energy after atom swaps ->>>>>>> a3bc1a6c0b09ee7a84167ab8aa626e4a93443846 *yes* = kinetic energy is conserved after atom swaps *no* = no conservation of kinetic energy after atom swaps *region* value = region-ID @@ -53,7 +48,6 @@ Description .. versionadded:: TBD -<<<<<<< HEAD This fix performs Monte-Carlo (MC) evaluations to enable kinetic Monte Carlo (kMC)-type behavior during MD simulation by allowing neighboring atoms to swap their positions. In constrast to the :doc:`fix @@ -76,52 +70,6 @@ to the swap. A detailed explanation of the original implementation of this algorithm can be found in :ref:`(Tavenner 2023) <_TavennerMDkMC>` where it was used to simulated accelerated diffusion in an MD context. -======= -This fix computes Monte Carlo (MC) evaluations to enable kinetic -Monte Carlo (kMC) behavior during an MD simulation by allowing -neighboring atoms to swap their positions. This creates a hybrid MD/kMC -simulation -where atoms are swapped only with their neighbors, and the swapping acceptance is -perfomed by evaluating the change in system energy using the Metropolis criterion. -Neighboring atoms are selected using a Voronoi tesselation approach. A detailed -explination of the original implementation of this procedure can be found in -:ref:`(Tavenner 2023) <_TavennerMDkMC>` as originally intended for simulating -accelerated diffusion in an MD context. - -Simulating inherently kinetically-limited behaviors which rely on rare events -(such as atomic diffusion) is challenging for traditional Molecular Dynamics -approaches, since thermal vibration motion occurs on a timescale much -shorter than local structural changes such as vacancy hopping. -To address -this challenge, an approach from kMC simulations is adopted where rare events can -be sampled at selected rates. By selecting such swap behaviors, the process -of atomic diffusion can be approximated during an MD simulation, effectively -decoupling the MD atomic vibrational time and the timescale of atomic hopping. - -To achieve such simulations, this algorithm takes the following approach. First, -the MD simulation is stopped *N* steps to attempt *X* atom swaps. -Voronoi neighbors are computed for all valid swap atoms. -For each swap attempt, one atom -I is selected at random from the global list of valid atoms. One if its Voronoi neighbors -that is a valid atom to swap is then selected. The neighbor atom ID is communicated to all -processors, as it may be owned by a different processor. -The two atom types are then swapped, and the change in system energy from before -the swap is used to evaluate the Metropolis acceptance criterion. This evaluation of the energy -change is a global calculation, such that it has a computational cost similar to -that of an MD timestep. If the swap is accepted from the Metropolis criterion, the -atoms remain swapped. If the swap is rejected, the atoms are reverted to their original types. This -process of MC evaluation is repeated for a given number of iterations until the -original MD simulation is resumed from the new state, where any successfully -swapped atoms have changed type, though the global system balance is preserved. - -A few key notes regarding this implementation are as follows. The parallel -efficiency of this algorithm is similar to that of other MC approaches, i.e, -the global potential energy must be calculated after each attempted swap. -Efficiency is sensitive to the maximum cutoff distance for the pair style, -since the neighbor list will need to be rebuilt between swap events. -Limitations are imposed on the Voronoi neighbors -to restrict swapping of atoms that are outside of a reasonable cutoff. ->>>>>>> a3bc1a6c0b09ee7a84167ab8aa626e4a93443846 Simulating inherently kinetically-limited behaviors which rely on rare events (such as atomic diffusion in a solid) is challenging for @@ -189,15 +137,9 @@ average nearest-neighbor spacing is appropriate. Since this is simply a proability weighting, the swapping behavior is not very sensitive to the exact value of *R0*. -<<<<<<< HEAD The keyword *types* takes two or more atom types as its values. Only atoms *I* of the first atom type will be selected. Only atoms *J* of the remaining atom types will be considered as potential swap partners. -======= -Typically, a value around the average nearest-neighbor spacing is appropriate -for *R0*. Since this is simply a probability weighting, behavior is not -particularly sensitive to the exact value of *R0*. ->>>>>>> a3bc1a6c0b09ee7a84167ab8aa626e4a93443846 The keyword *diff* take a single atom type as its value. Only atoms *I* of the that atom type will be selected. Atoms *J* of all @@ -205,26 +147,9 @@ remaining atom types will be considered as potential swap partners. This includes the atom type specified with the *diff* keyword to account for self-diffusive hops between two atoms of the same type. -<<<<<<< HEAD The keyword *voro* is required. Its *vID* value is the compute-ID of a :doc:`compute voronoi/atom ` command like this: -======= -The keyword *diff* is used for implementation of simulated diffusion of -a given atom type as given by *diff type*. This command selects all atom -types as acceptable swap types to a centrally selected atom of type -*type*. This includes the atom type specified by the *diff* keyword to -account for self-diffusion hops of an atom type with itself. - -Keyword *voro* is currently required, and is implemented as - -.. code-block:: LAMMPS - - voro compute-ID - -where *compute-ID* is the ID of a corresponding Voronoi computation with -neighbor list, i.e. ->>>>>>> a3bc1a6c0b09ee7a84167ab8aa626e4a93443846 .. code-block:: LAMMPS @@ -251,7 +176,6 @@ for details. This means the group-ID for the :doc:`compute voronoi/atom ` command also need only contain atoms within the region. -<<<<<<< HEAD The keyword *rates* can modify the swap rate based on the type of atom *J*. Ntype values must be specified, where Ntype = the number of atom types in the system. Each value is used to scale the probability @@ -262,32 +186,6 @@ Assuming all *J* atoms are equidistant from an atom *I*, *J* atoms of type 1 will be 3x more likely to be selected as a swap partner than atoms of type 2. And *J* atoms of type 3 will be 6.5x more likely to be selected than atoms of type 2. If the *rates* keyword is not used, -======= -for using *fix neighbor/swap* with *diff 2*. - -If atoms in the specified group are not in the voro calculated group -they will not be considered for swapping. - -The keyword *rates* can modify the swap rate for each swapped type by -values where the adjusted rates values are given in order of increasing -atom type. The number of rates provided must equal the number of atom -types in the simulation. In the third provided example above, a -simulation is conducted with three atom types where the third atom type -is the one sampled for attempted swaps. All three atom types are -considered valid swaps, but atoms of type 1 will be selected three times -as often as atoms of type 2. Conversely, atoms of type 3 are six times -more likely to be selected than atoms of type two and twice as likely as -atoms of type 1. - -Finally, the *region* keyword is implemented as in other atomic fixes, -where the *region region-ID* command indicates that atom swaps only be -considered in the area given by *region-ID*. If only atoms of certain -groups are expected to be in this region, the corresponding compute -voronoi command can be adjusted accordingly. - -Either the *types* or *diff* keyword must be specified to select atom -types for swapping ->>>>>>> a3bc1a6c0b09ee7a84167ab8aa626e4a93443846 Restart, fix_modify, output, run start/stop, minimize info From 4bfdd3eb3481e15aa1fa7e9be746a952ec454b8d Mon Sep 17 00:00:00 2001 From: Jacob Tavenner Date: Mon, 14 Apr 2025 16:22:11 -0600 Subject: [PATCH 142/396] Remove trailing whitespace --- doc/src/fix_neighbor_swap.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/fix_neighbor_swap.rst b/doc/src/fix_neighbor_swap.rst index da1e89bed5..274c4ea939 100644 --- a/doc/src/fix_neighbor_swap.rst +++ b/doc/src/fix_neighbor_swap.rst @@ -48,11 +48,11 @@ Description .. versionadded:: TBD -This fix performs Monte-Carlo (MC) evaluations to enable kinetic -Monte Carlo (kMC)-type behavior during MD simulation by allowing +This fix performs Monte-Carlo (MC) evaluations to enable kinetic +Monte Carlo (kMC)-type behavior during MD simulation by allowing neighboring atoms to swap their positions. In constrast to the :doc:`fix atom/swap ` command which swaps pairs of atoms anywhere -in the simulation domain, the restriction of the MC swapping to +in the simulation domain, the restriction of the MC swapping to neighbors enables a hybrid MD/kMC-like simulation. Neighboring atoms are defined by using a Voronoi tesselation performed @@ -115,7 +115,7 @@ computed correctly. Limitations are imposed on selection of *I,J* atom pairs to avoid swapping of atoms which are outside of a reasonable cutoff (e.g. due to a Voronoi tesselation near free surfaces) though the -use of a distance-weighted probabiltiy scaling. +use of a distance-weighted probabiltiy scaling. ---------- From 0c29a0a0c9e555a16dc2dd439d9cf2cfece364d1 Mon Sep 17 00:00:00 2001 From: William Zunker Date: Tue, 15 Apr 2025 13:55:38 -0400 Subject: [PATCH 143/396] changed damp_type to be a mdr damping coefficent --- doc/src/pair_granular.rst | 16 ++++++---------- examples/granular/in.tableting.200 | 6 +++--- examples/granular/in.triaxial.compaction.12 | 6 +++--- src/GRANULAR/gran_sub_mod_damping.cpp | 8 +++++++- src/GRANULAR/gran_sub_mod_damping.h | 3 ++- src/GRANULAR/gran_sub_mod_normal.cpp | 4 +--- src/GRANULAR/gran_sub_mod_normal.h | 2 -- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/doc/src/pair_granular.rst b/doc/src/pair_granular.rst index 696c87b0ab..7998f11cc5 100644 --- a/doc/src/pair_granular.rst +++ b/doc/src/pair_granular.rst @@ -44,7 +44,7 @@ Examples pair_coeff * * hertz 1000.0 50.0 tangential mindlin 1000.0 1.0 0.4 heat area 0.1 pair_style granular - pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 0.0 0.7 rolling sds 2.7e5 0.0 0.6 damping mdr 1 + pair_coeff * * mdr 5e6 0.4 1.9e5 2.0 0.5 0.5 tangential linear_history 940.0 1.0 0.7 rolling sds 2.7e5 0.0 0.6 damping mdr 1 Description """"""""""" @@ -89,7 +89,7 @@ and their required arguments are: 4. *dmt* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 5. *jkr* : E, :math:`\eta_{n0}` (or :math:`e`), :math:`\nu`, :math:`\gamma` 6. *mdr* : :math:`E`, :math:`\nu`, :math:`Y`, :math:`\Delta\gamma`, - :math:`\psi_b`, :math:`\eta_{n0}`, :math:`d_{type}` + :math:`\psi_b`, :math:`\eta_{n0}` Here, :math:`k_n` is spring stiffness (with units that depend on model choice, see below); :math:`\eta_{n0}` is a damping prefactor (or, in its @@ -206,9 +206,6 @@ The model requires the following inputs: 6. *Damping coefficent* :math:`\eta_{n0} \ge 0` : The damping coefficient is a tunable parameter that controls damping in the normal direction. - 7. *Damping type* :math:`d_{type} =` 1 or 2 : The damping type specfies the - damping model defined for the *mdr* damping class described below. - .. note:: The values for :math:`E`, :math:`\nu`, :math:`Y`, and :math:`\Delta\gamma` (i.e., @@ -263,7 +260,7 @@ The *mdr* model currently only supports *fix wall/gran/region*, not any *fix wall/gran/region* commands must also use the *mdr* model. Additionally, the following *mdr* inputs must match between the *pair_style* and *fix wall/gran/region* definitions: :math:`E`, -:math:`\nu`, :math:`Y`, :math:`\psi_b`, and :math:`e`. The exception +:math:`\nu`, :math:`Y`, :math:`\psi_b`, and :math:`\eta_{n0}`. The exception is :math:`\Delta\gamma`, which may vary, permitting different adhesive behaviors between particle-particle and particle-wall interactions. @@ -329,7 +326,7 @@ for the damping model currently supported are: 3. *viscoelastic* 4. *tsuji* 5. *coeff_restitution* -6. *mdr* +6. *mdr* (class) : :math:`d_{type}` If the *damping* keyword is not specified, the *viscoelastic* model is used by default. @@ -420,9 +417,8 @@ restitution for both monodisperse and polydisperse particle pairs. This damping model is not compatible with cohesive normal models such as *JKR* or *DMT*. The *mdr* damping class contains multiple damping models that can be toggled between -by specifying different integer values for the :math:`d_{type}` parameter in the *mdr* -normal model. This damping option is therefore only compatible with the normal *mdr* -contact model. +by specifying different integer values for the :math:`d_{type}` input parameter. This +damping option is only compatible with the normal *mdr* contact model. Setting :math:`d_{type} = 1` is the suggested damping option. This specifies a damping model that takes into account the contact stiffness :math:`k_{mdr}` calulated diff --git a/examples/granular/in.tableting.200 b/examples/granular/in.tableting.200 index 02eb6743de..58fc8dde3e 100644 --- a/examples/granular/in.tableting.200 +++ b/examples/granular/in.tableting.200 @@ -50,8 +50,8 @@ variable mu_roll equal 0.6 variable k_roll equal 2.25*${mu_roll}*${mu_roll}*${YoungsModulus}*${atomRadius} variable gamma_roll equal 0.0 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} ${damp_type} & - damping mdr & +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & + damping mdr ${damp_type} & tangential linear_history ${kt} ${xgammat} ${mu_s} & rolling sds ${k_roll} ${gamma_roll} ${mu_roll} @@ -60,7 +60,7 @@ pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEne variable disp_upper equal 0.0 variable disp_lower equal 0.0 -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} ${damp_type} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" variable dieHeight2 equal 2*${dieHeight} diff --git a/examples/granular/in.triaxial.compaction.12 b/examples/granular/in.triaxial.compaction.12 index 6a948157d3..0a35ab3c0a 100644 --- a/examples/granular/in.triaxial.compaction.12 +++ b/examples/granular/in.triaxial.compaction.12 @@ -38,8 +38,8 @@ variable kt equal 2/7*${YoungsModulus}*${atomRadius} variable xgammat equal 0.0 variable mu_s equal 0.5 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} ${damp_type} & - damping mdr & +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} & + damping mdr ${damp_type} & tangential linear_history ${kt} ${xgammat} ${mu_s} ######################################### ADD IN PLANES ################################################ @@ -57,7 +57,7 @@ region plane_xz_neg plane 0 -${halfBoxWidth} 0 0 1 0 side in move NULL v_plane_d region plane_xy_pos plane 0 0 ${halfBoxWidth} 0 0 -1 side in move NULL NULL v_plane_disp_neg units box region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} ${damp_type} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} " +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} " fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index c35d63d668..b68a720413 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -190,6 +190,13 @@ void GranSubModDampingCoeffRestitution::init() GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : GranSubModDamping(gm, lmp) { + num_coeffs = 1; +} + +void GranSubModDampingMDR::coeffs_to_local() +{ + damp_type = coeffs[0]; // damping type 1 = mdr stiffness or 2 = velocity + if (damp_type != 1 && damp_type != 2) error->all(FLERR, "Illegal MDR normal model, damping type must an integer equal to 1 or 2"); } /* ---------------------------------------------------------------------- */ @@ -200,7 +207,6 @@ void GranSubModDampingMDR::init() error->all(FLERR, "Damping mdr can only be used with mdr normal model"); damp = gm->normal_model->get_damp(); - damp_type = gm->normal_model->get_damp_type(); } /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_damping.h b/src/GRANULAR/gran_sub_mod_damping.h index c73a4a8e5e..274c3d9e29 100644 --- a/src/GRANULAR/gran_sub_mod_damping.h +++ b/src/GRANULAR/gran_sub_mod_damping.h @@ -42,7 +42,7 @@ namespace Granular_NS { protected: double damp_prefactor; double damp; - int damp_type; + int damp_type; // damping type is only used by normal mdr model }; /* ---------------------------------------------------------------------- */ @@ -99,6 +99,7 @@ namespace Granular_NS { class GranSubModDampingMDR : public GranSubModDamping { public: GranSubModDampingMDR(class GranularModel *, class LAMMPS *); + void coeffs_to_local() override; void init() override; double calculate_forces() override; }; diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index aa53f5fcf6..68cb853d9d 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -441,7 +441,7 @@ GranSubModNormalMDR::GranSubModNormalMDR(GranularModel *gm, LAMMPS *lmp) : { if (lmp->citeme) lmp->citeme->add(cite_mdr); - num_coeffs = 7; + num_coeffs = 6; contact_radius_flag = 1; size_history = 27; nsvector = 1; @@ -474,7 +474,6 @@ void GranSubModNormalMDR::coeffs_to_local() gamma = coeffs[3]; // effective surface energy psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} damp = coeffs[5]; // coefficent of restitution - damp_type = coeffs[6]; // damping type 1 = mdr or 2 = velocity if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); if (nu < 0.0 || nu > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); @@ -482,7 +481,6 @@ void GranSubModNormalMDR::coeffs_to_local() if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); - if (damp_type != 1 && damp_type != 2) error->all(FLERR, "Illegal MDR normal model, damping type must an integer equal to 1 or 2"); G = E / (2.0 * (1.0 + nu)); // shear modulus kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus diff --git a/src/GRANULAR/gran_sub_mod_normal.h b/src/GRANULAR/gran_sub_mod_normal.h index 0b7bb664d5..8142d88cea 100644 --- a/src/GRANULAR/gran_sub_mod_normal.h +++ b/src/GRANULAR/gran_sub_mod_normal.h @@ -41,7 +41,6 @@ namespace Granular_NS { int get_cohesive_flag() const { return cohesive_flag; } double get_damp() const { return damp; } - double get_damp_type() const { return damp_type; } double get_emod() const { return Emod; } double get_fncrit() const { return Fncrit; } int get_material_properties() const { return material_properties; } @@ -52,7 +51,6 @@ namespace Granular_NS { protected: double damp; // argument historically needed by damping // typically (but not always) equals eta_n0 - int damp_type; // damping type is only used by normal mdr model double Emod, poiss; double Fncrit; int material_properties, cohesive_flag; From 49d5e02c11a84b3ed3c14fada9560e28cb9f6461 Mon Sep 17 00:00:00 2001 From: jtclemm Date: Tue, 15 Apr 2025 17:34:46 -0600 Subject: [PATCH 144/396] Variable name change, fixing some spacing/typos --- .../granular/log.4Feb25.tableting.200.g++.1 | 926 +++++++------- .../log.4Feb25.triaxial.compaction.12.g++.1 | 1080 +++++++++-------- src/GRANULAR/fix_granular_mdr.cpp | 8 +- src/GRANULAR/gran_sub_mod_damping.cpp | 3 +- src/GRANULAR/gran_sub_mod_damping.h | 4 +- src/GRANULAR/gran_sub_mod_normal.cpp | 35 +- src/GRANULAR/gran_sub_mod_normal.h | 2 +- 7 files changed, 1035 insertions(+), 1023 deletions(-) diff --git a/examples/granular/log.4Feb25.tableting.200.g++.1 b/examples/granular/log.4Feb25.tableting.200.g++.1 index 818198ccd7..c164f3dbee 100644 --- a/examples/granular/log.4Feb25.tableting.200.g++.1 +++ b/examples/granular/log.4Feb25.tableting.200.g++.1 @@ -1,4 +1,4 @@ -LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-583-g3d4b57d7fd-modified) +LAMMPS (4 Feb 2025 - Development - patch_5May2020-22356-g0c29a0a0c9-modified) ##################################### SIMULATION SETTINGS ################################################### atom_style sphere 1 @@ -20,7 +20,7 @@ Reading data file ... 1 by 1 by 1 MPI processor grid reading atoms ... 200 atoms - read_data CPU = 0.003 seconds + read_data CPU = 0.024 seconds #################################### ADD DIE AND ATOM PARAMETERIZATION ###################################### @@ -44,8 +44,9 @@ variable YieldStress equal 1.9e5 variable PoissonsRatio equal 0.4 variable SurfaceEnergy equal 2 variable SurfaceEnergyWall equal 0.0 -variable damp equal 1.0 variable psi_b equal 0.5 +variable damp equal 0.2 +variable damp_type equal 1 # linear_history = k_t, x_gammat, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} @@ -67,38 +68,40 @@ variable k_roll equal 2.25*0.6*0.6*5000000*${atomRadius} variable k_roll equal 2.25*0.6*0.6*5000000*0.00055 variable gamma_roll equal 0.0 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 ${gamma_roll} ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 ${mu_roll} -pair_coeff * * mdr 5000000 0.4 190000 2 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 0.6 +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history ${kt} ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 ${xgammat} ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 ${mu_s} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 ${gamma_roll} ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 ${mu_roll} +pair_coeff * * mdr 5000000 0.4 190000 2 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.7 rolling sds 2227.5 0 0.6 ######################################### ADD DIE AND PUNCH WALLS ############################################ variable disp_upper equal 0.0 variable disp_lower equal 0.0 -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" -granular mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 ${psi_b} ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 ${damp} damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 ${gamma_roll} ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 ${mu_roll} -granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll}" +granular mdr 5000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 ${YieldStress} ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 ${SurfaceEnergyWall} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history ${kt_wall} ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 ${xgammat} ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 ${mu_s_wall} rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds ${k_roll} ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 ${gamma_roll} ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 ${mu_roll} +granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 variable dieHeight2 equal 2*${dieHeight} variable dieHeight2 equal 2*0.01 @@ -111,11 +114,11 @@ region die cylinder z 0 0 0.004 0 ${dieHeight2} side in units box region die cylinder z 0 0 0.004 0 0.02 side in units box fix lowerPunch all wall/gran/region ${wall_contact_string} region lowerPunch contacts -fix lowerPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region lowerPunch contacts +fix lowerPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region lowerPunch contacts fix upperPunch all wall/gran/region ${wall_contact_string} region upperPunch contacts -fix upperPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region upperPunch contacts +fix upperPunch all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region upperPunch contacts fix die all wall/gran/region ${wall_contact_string} region die contacts -fix die all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 1 damping mdr tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region die contacts +fix die all wall/gran/region granular mdr 5000000 0.4 190000 0 0.5 0.2 damping mdr 1 tangential linear_history 785.714285714286 1 0.1 rolling sds 2227.5 0 0.6 region die contacts compute avgUpperPunchForce all reduce sum f_upperPunch[4] variable avgUpperPunchForce equal c_avgUpperPunchForce @@ -173,8 +176,9 @@ Your simulation uses code contributions which should be cited: author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken}, title = {Experimentally validated DEM for large deformation powder compaction: mechanically-derived contact model and screening of non-physical contacts}, + journal = {Powder Technology}, year = {2025}, - journal = {engrXiv}, + pages = {120972}, } CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE @@ -195,9 +199,9 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes Dt Step Atoms KinEng Volume v_disp_upper 4e-06 0 200 0 2.1e-06 0 -Loop time of 7.84e-07 on 1 procs for 0 steps with 200 atoms +Loop time of 7.43e-07 on 1 procs for 0 steps with 200 atoms -127.6% CPU use with 1 MPI tasks x no OpenMP threads +134.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total @@ -207,7 +211,7 @@ Neigh | 0 | 0 | 0 | 0.0 | 0.00 Comm | 0 | 0 | 0 | 0.0 | 0.00 Output | 0 | 0 | 0 | 0.0 | 0.00 Modify | 0 | 0 | 0 | 0.0 | 0.00 -Other | | 7.84e-07 | | |100.00 +Other | | 7.43e-07 | | |100.00 Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 @@ -263,78 +267,78 @@ Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes Dt Step Atoms KinEng Volume v_disp_upper 4e-06 0 200 0 2.1e-06 0 4e-06 100 200 1.5945503e-09 2.1e-06 0 - 4e-06 200 200 6.3722236e-09 2.1e-06 0 - 4e-06 300 200 1.4211064e-08 2.1e-06 0 - 4e-06 400 200 2.5258679e-08 2.1e-06 0 - 4e-06 500 200 3.9464769e-08 2.1e-06 0 - 4e-06 600 200 5.6825967e-08 2.1e-06 0 - 4e-06 700 200 7.7344469e-08 2.1e-06 0 - 4e-06 800 200 1.0060974e-07 2.1e-06 0 - 4e-06 900 200 1.2653591e-07 2.1e-06 0 - 4e-06 1000 200 1.5569212e-07 2.1e-06 0 - 4e-06 1100 200 1.8742647e-07 2.1e-06 0 - 4e-06 1200 200 2.215525e-07 2.1e-06 0 - 4e-06 1300 200 2.5959327e-07 2.1e-06 0 - 4e-06 1400 200 3.010369e-07 2.1e-06 0 - 4e-06 1500 200 3.4166871e-07 2.1e-06 0 - 4e-06 1600 200 3.8173997e-07 2.1e-06 0 - 4e-06 1700 200 4.2263596e-07 2.1e-06 0 - 4e-06 1800 200 4.6542919e-07 2.1e-06 0 - 4e-06 1900 200 5.1316032e-07 2.1e-06 0 - 4e-06 2000 200 5.6390086e-07 2.1e-06 0 - 4e-06 2100 200 6.1282692e-07 2.1e-06 0 - 4e-06 2200 200 6.6871978e-07 2.1e-06 0 - 4e-06 2300 200 7.2432957e-07 2.1e-06 0 - 4e-06 2400 200 7.7356329e-07 2.1e-06 0 - 4e-06 2500 200 8.3121212e-07 2.1e-06 0 - 4e-06 2600 200 8.9285402e-07 2.1e-06 0 - 4e-06 2700 200 9.5056709e-07 2.1e-06 0 - 4e-06 2800 200 1.0078859e-06 2.1e-06 0 - 4e-06 2900 200 1.0583726e-06 2.1e-06 0 - 4e-06 3000 200 1.1128777e-06 2.1e-06 0 - 4e-06 3100 200 1.149994e-06 2.1e-06 0 - 4e-06 3200 200 1.2038821e-06 2.1e-06 0 - 4e-06 3300 200 1.2266858e-06 2.1e-06 0 - 4e-06 3400 200 1.2785607e-06 2.1e-06 0 - 4e-06 3500 200 1.3382357e-06 2.1e-06 0 - 4e-06 3600 200 1.3864259e-06 2.1e-06 0 - 4e-06 3700 200 1.4382735e-06 2.1e-06 0 - 4e-06 3800 200 1.4261443e-06 2.1e-06 0 - 4e-06 3900 200 1.4409345e-06 2.1e-06 0 - 4e-06 4000 200 1.4794449e-06 2.1e-06 0 - 4e-06 4100 200 1.4696815e-06 2.1e-06 0 - 4e-06 4200 200 1.4980192e-06 2.1e-06 0 - 4e-06 4300 200 1.5093101e-06 2.1e-06 0 - 4e-06 4400 200 1.527165e-06 2.1e-06 0 - 4e-06 4500 200 1.5514338e-06 2.1e-06 0 - 4e-06 4600 200 1.5939536e-06 2.1e-06 0 - 4e-06 4700 200 1.6017087e-06 2.1e-06 0 - 4e-06 4800 200 1.5835827e-06 2.1e-06 0 - 4e-06 4900 200 1.5646707e-06 2.1e-06 0 - 4e-06 5000 200 1.5869167e-06 2.1e-06 0 -Loop time of 0.894952 on 1 procs for 5000 steps with 200 atoms + 4e-06 200 200 6.3750614e-09 2.1e-06 0 + 4e-06 300 200 1.4225143e-08 2.1e-06 0 + 4e-06 400 200 2.5255561e-08 2.1e-06 0 + 4e-06 500 200 3.947508e-08 2.1e-06 0 + 4e-06 600 200 5.6839079e-08 2.1e-06 0 + 4e-06 700 200 7.7346494e-08 2.1e-06 0 + 4e-06 800 200 1.0075645e-07 2.1e-06 0 + 4e-06 900 200 1.2660105e-07 2.1e-06 0 + 4e-06 1000 200 1.5571123e-07 2.1e-06 0 + 4e-06 1100 200 1.8785107e-07 2.1e-06 0 + 4e-06 1200 200 2.2200974e-07 2.1e-06 0 + 4e-06 1300 200 2.6009223e-07 2.1e-06 0 + 4e-06 1400 200 3.0148646e-07 2.1e-06 0 + 4e-06 1500 200 3.4269724e-07 2.1e-06 0 + 4e-06 1600 200 3.8502938e-07 2.1e-06 0 + 4e-06 1700 200 4.2763891e-07 2.1e-06 0 + 4e-06 1800 200 4.6779321e-07 2.1e-06 0 + 4e-06 1900 200 5.1285578e-07 2.1e-06 0 + 4e-06 2000 200 5.6630973e-07 2.1e-06 0 + 4e-06 2100 200 6.1904302e-07 2.1e-06 0 + 4e-06 2200 200 6.7462868e-07 2.1e-06 0 + 4e-06 2300 200 7.3066636e-07 2.1e-06 0 + 4e-06 2400 200 7.7407334e-07 2.1e-06 0 + 4e-06 2500 200 8.3353557e-07 2.1e-06 0 + 4e-06 2600 200 9.0017986e-07 2.1e-06 0 + 4e-06 2700 200 9.5154909e-07 2.1e-06 0 + 4e-06 2800 200 1.0110977e-06 2.1e-06 0 + 4e-06 2900 200 1.0661364e-06 2.1e-06 0 + 4e-06 3000 200 1.1226841e-06 2.1e-06 0 + 4e-06 3100 200 1.1703917e-06 2.1e-06 0 + 4e-06 3200 200 1.2254551e-06 2.1e-06 0 + 4e-06 3300 200 1.2239859e-06 2.1e-06 0 + 4e-06 3400 200 1.273437e-06 2.1e-06 0 + 4e-06 3500 200 1.3357598e-06 2.1e-06 0 + 4e-06 3600 200 1.3949477e-06 2.1e-06 0 + 4e-06 3700 200 1.459988e-06 2.1e-06 0 + 4e-06 3800 200 1.5053806e-06 2.1e-06 0 + 4e-06 3900 200 1.4952453e-06 2.1e-06 0 + 4e-06 4000 200 1.5037857e-06 2.1e-06 0 + 4e-06 4100 200 1.5225204e-06 2.1e-06 0 + 4e-06 4200 200 1.5375323e-06 2.1e-06 0 + 4e-06 4300 200 1.5552328e-06 2.1e-06 0 + 4e-06 4400 200 1.581097e-06 2.1e-06 0 + 4e-06 4500 200 1.6066427e-06 2.1e-06 0 + 4e-06 4600 200 1.6061944e-06 2.1e-06 0 + 4e-06 4700 200 1.6110891e-06 2.1e-06 0 + 4e-06 4800 200 1.6072997e-06 2.1e-06 0 + 4e-06 4900 200 1.5907992e-06 2.1e-06 0 + 4e-06 5000 200 1.5501104e-06 2.1e-06 0 +Loop time of 0.592588 on 1 procs for 5000 steps with 200 atoms -99.7% CPU use with 1 MPI tasks x no OpenMP threads +99.4% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.33414 | 0.33414 | 0.33414 | 0.0 | 37.34 -Neigh | 0.013978 | 0.013978 | 0.013978 | 0.0 | 1.56 -Comm | 0.00055911 | 0.00055911 | 0.00055911 | 0.0 | 0.06 -Output | 0.00042257 | 0.00042257 | 0.00042257 | 0.0 | 0.05 -Modify | 0.54341 | 0.54341 | 0.54341 | 0.0 | 60.72 -Other | | 0.002439 | | | 0.27 +Pair | 0.20465 | 0.20465 | 0.20465 | 0.0 | 34.53 +Neigh | 0.013252 | 0.013252 | 0.013252 | 0.0 | 2.24 +Comm | 0.00037594 | 0.00037594 | 0.00037594 | 0.0 | 0.06 +Output | 0.00037454 | 0.00037454 | 0.00037454 | 0.0 | 0.06 +Modify | 0.37295 | 0.37295 | 0.37295 | 0.0 | 62.93 +Other | | 0.0009914 | | | 0.17 Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 1663 ave 1663 max 1663 min +Neighs: 1632 ave 1632 max 1632 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 1663 -Ave neighs/atom = 8.315 +Total # of neighbors = 1632 +Ave neighs/atom = 8.16 Neighbor list builds = 83 Dangerous builds not checked @@ -352,170 +356,170 @@ run 14000 Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule Per MPI rank memory allocation (min/avg/max) = 72.3 | 72.3 | 72.3 Mbytes Dt Step Atoms KinEng Volume v_disp_upper - 4e-06 5000 200 1.5869167e-06 2.1e-06 0 - 4e-06 5100 200 1.533415e-06 2.1e-06 -0.00015706645 - 4e-06 5200 200 1.5210118e-06 2.1e-06 -0.00031405381 - 4e-06 5300 200 1.4717654e-06 2.1e-06 -0.00047088304 - 4e-06 5400 200 1.3867583e-06 2.1e-06 -0.00062747516 - 4e-06 5500 200 1.3210172e-06 2.1e-06 -0.00078375133 - 4e-06 5600 200 1.2694854e-06 2.1e-06 -0.00093963286 - 4e-06 5700 200 1.210939e-06 2.1e-06 -0.0010950413 - 4e-06 5800 200 1.1030246e-06 2.1e-06 -0.0012498983 - 4e-06 5900 200 1.0576145e-06 2.1e-06 -0.0014041259 - 4e-06 6000 200 9.6819458e-07 2.1e-06 -0.0015576465 - 4e-06 6100 200 8.4390663e-07 2.1e-06 -0.0017103828 - 4e-06 6200 200 7.1811878e-07 2.1e-06 -0.0018622579 - 4e-06 6300 200 5.9188275e-07 2.1e-06 -0.0020131953 - 4e-06 6400 200 4.8593994e-07 2.1e-06 -0.002163119 - 4e-06 6500 200 3.7604444e-07 2.1e-06 -0.0023119534 - 4e-06 6600 200 2.9315224e-07 2.1e-06 -0.0024596238 - 4e-06 6700 200 2.4346404e-07 2.1e-06 -0.0026060556 - 4e-06 6800 200 2.1035347e-07 2.1e-06 -0.0027511752 - 4e-06 6900 200 1.7982462e-07 2.1e-06 -0.0028949095 - 4e-06 7000 200 3.3817811e-07 2.1e-06 -0.0030371862 - 4e-06 7100 200 5.4229142e-07 2.1e-06 -0.0031779335 - 4e-06 7200 200 9.8011974e-07 2.1e-06 -0.0033170806 - 4e-06 7300 200 1.4073827e-06 2.1e-06 -0.0034545575 - 4e-06 7400 200 1.8007974e-06 2.1e-06 -0.0035902949 - 4e-06 7500 200 2.5690983e-06 2.1e-06 -0.0037242245 - 4e-06 7600 200 3.3504605e-06 2.1e-06 -0.0038562789 - 4e-06 7700 200 3.3047732e-06 2.1e-06 -0.0039863915 - 4e-06 7800 200 2.7409232e-06 2.1e-06 -0.0041144968 - 4e-06 7900 200 2.7731736e-06 2.1e-06 -0.0042405303 - 4e-06 8000 200 2.7721382e-06 2.1e-06 -0.0043644286 - 4e-06 8100 200 2.5449128e-06 2.1e-06 -0.0044861293 - 4e-06 8200 200 2.4113011e-06 2.1e-06 -0.0046055711 - 4e-06 8300 200 2.5104553e-06 2.1e-06 -0.0047226938 - 4e-06 8400 200 2.7969453e-06 2.1e-06 -0.0048374385 - 4e-06 8500 200 2.4549778e-06 2.1e-06 -0.0049497475 - 4e-06 8600 200 2.6065634e-06 2.1e-06 -0.005059564 - 4e-06 8700 200 1.94773e-06 2.1e-06 -0.005166833 - 4e-06 8800 200 1.8669003e-06 2.1e-06 -0.0052715003 - 4e-06 8900 200 1.7712516e-06 2.1e-06 -0.0053735132 - 4e-06 9000 200 1.5868574e-06 2.1e-06 -0.0054728204 - 4e-06 9100 200 1.2586882e-06 2.1e-06 -0.0055693718 - 4e-06 9200 200 1.7392355e-06 2.1e-06 -0.005663119 - 4e-06 9300 200 1.4103062e-06 2.1e-06 -0.0057540145 - 4e-06 9400 200 1.6133909e-06 2.1e-06 -0.0058420128 - 4e-06 9500 200 1.5715429e-06 2.1e-06 -0.0059270694 - 4e-06 9600 200 1.3060432e-06 2.1e-06 -0.0060091416 - 4e-06 9700 200 1.3016643e-06 2.1e-06 -0.0060881879 - 4e-06 9800 200 1.3827359e-06 2.1e-06 -0.0061641687 - 4e-06 9900 200 1.166866e-06 2.1e-06 -0.0062370457 - 4e-06 10000 200 1.1328931e-06 2.1e-06 -0.0063067821 - 4e-06 10100 200 1.0811811e-06 2.1e-06 -0.0063733428 - 4e-06 10200 200 1.0540805e-06 2.1e-06 -0.0064366944 - 4e-06 10300 200 9.3224876e-07 2.1e-06 -0.0064968049 - 4e-06 10400 200 8.8422228e-07 2.1e-06 -0.0065536441 - 4e-06 10500 200 9.6574449e-07 2.1e-06 -0.0066071833 - 4e-06 10600 200 6.5673924e-07 2.1e-06 -0.0066573956 - 4e-06 10700 200 5.7629287e-07 2.1e-06 -0.0067042557 - 4e-06 10800 200 5.1184648e-07 2.1e-06 -0.00674774 - 4e-06 10900 200 4.2140431e-07 2.1e-06 -0.0067878266 - 4e-06 11000 200 3.679501e-07 2.1e-06 -0.0068244954 - 4e-06 11100 200 2.7198635e-07 2.1e-06 -0.0068577278 - 4e-06 11200 200 3.9270049e-07 2.1e-06 -0.0068875071 - 4e-06 11300 200 2.5364345e-07 2.1e-06 -0.0069138184 - 4e-06 11400 200 2.311875e-07 2.1e-06 -0.0069366483 - 4e-06 11500 200 9.1194666e-08 2.1e-06 -0.0069559855 - 4e-06 11600 200 5.9128951e-08 2.1e-06 -0.0069718201 - 4e-06 11700 200 3.8675445e-08 2.1e-06 -0.0069841441 - 4e-06 11800 200 1.5261639e-08 2.1e-06 -0.0069929515 - 4e-06 11900 200 4.1435674e-09 2.1e-06 -0.0069982376 - 4e-06 12000 200 3.6182887e-10 2.1e-06 -0.007 - 4e-06 12100 200 3.4148153e-09 2.1e-06 -0.0069982376 - 4e-06 12200 200 1.201855e-08 2.1e-06 -0.0069929515 - 4e-06 12300 200 2.7088001e-08 2.1e-06 -0.0069841441 - 4e-06 12400 200 4.7261349e-08 2.1e-06 -0.0069718201 - 4e-06 12500 200 7.585591e-08 2.1e-06 -0.0069559855 - 4e-06 12600 200 1.0717843e-07 2.1e-06 -0.0069366483 - 4e-06 12700 200 1.4357347e-07 2.1e-06 -0.0069138184 - 4e-06 12800 200 2.3364223e-07 2.1e-06 -0.0068875071 - 4e-06 12900 200 2.6460705e-07 2.1e-06 -0.0068577278 - 4e-06 13000 200 3.0878617e-07 2.1e-06 -0.0068244954 - 4e-06 13100 200 4.0950412e-07 2.1e-06 -0.0067878266 - 4e-06 13200 200 5.4382238e-07 2.1e-06 -0.00674774 - 4e-06 13300 200 5.9323976e-07 2.1e-06 -0.0067042557 - 4e-06 13400 200 6.0024632e-07 2.1e-06 -0.0066573956 - 4e-06 13500 200 8.9144808e-07 2.1e-06 -0.0066071833 - 4e-06 13600 200 7.4298898e-07 2.1e-06 -0.0065536441 - 4e-06 13700 200 7.5476346e-07 2.1e-06 -0.0064968049 - 4e-06 13800 200 9.4480881e-07 2.1e-06 -0.0064366944 - 4e-06 13900 200 6.9480641e-07 2.1e-06 -0.0063733428 - 4e-06 14000 200 3.6996473e-07 2.1e-06 -0.0063067821 - 4e-06 14100 200 3.7522265e-07 2.1e-06 -0.0062370457 - 4e-06 14200 200 9.5971189e-07 2.1e-06 -0.0061641687 - 4e-06 14300 200 6.3482043e-07 2.1e-06 -0.0060881879 - 4e-06 14400 200 4.4208165e-08 2.1e-06 -0.0060091416 - 4e-06 14500 200 2.5451697e-09 2.1e-06 -0.0059270694 - 4e-06 14600 200 2.3358938e-10 2.1e-06 -0.0058420128 - 4e-06 14700 200 6.5542266e-10 2.1e-06 -0.0057540145 - 4e-06 14800 200 5.7442167e-10 2.1e-06 -0.005663119 - 4e-06 14900 200 1.8498409e-10 2.1e-06 -0.0055693718 - 4e-06 15000 200 8.9754087e-12 2.1e-06 -0.0054728204 - 4e-06 15100 200 1.5735217e-10 2.1e-06 -0.0053735132 - 4e-06 15200 200 2.0644095e-11 2.1e-06 -0.0052715003 - 4e-06 15300 200 3.1810324e-12 2.1e-06 -0.005166833 - 4e-06 15400 200 9.2248411e-13 2.1e-06 -0.005059564 - 4e-06 15500 200 1.049892e-12 2.1e-06 -0.0049497475 - 4e-06 15600 200 5.1537473e-13 2.1e-06 -0.0048374385 - 4e-06 15700 200 8.0874962e-14 2.1e-06 -0.0047226938 - 4e-06 15800 200 1.9259517e-14 2.1e-06 -0.0046055711 - 4e-06 15900 200 6.1677187e-14 2.1e-06 -0.0044861293 - 4e-06 16000 200 4.0175545e-14 2.1e-06 -0.0043644286 - 4e-06 16100 200 2.8906156e-14 2.1e-06 -0.0042405303 - 4e-06 16200 200 1.4689406e-14 2.1e-06 -0.0041144968 - 4e-06 16300 200 1.4816055e-14 2.1e-06 -0.0039863915 - 4e-06 16400 200 1.8585236e-14 2.1e-06 -0.0038562789 - 4e-06 16500 200 1.485896e-14 2.1e-06 -0.0037242245 - 4e-06 16600 200 1.5799533e-14 2.1e-06 -0.0035902949 - 4e-06 16700 200 1.5241276e-14 2.1e-06 -0.0034545575 - 4e-06 16800 200 1.1272606e-14 2.1e-06 -0.0033170806 - 4e-06 16900 200 1.2135244e-14 2.1e-06 -0.0031779335 - 4e-06 17000 200 1.143872e-14 2.1e-06 -0.0030371862 - 4e-06 17100 200 1.1915182e-14 2.1e-06 -0.0028949095 - 4e-06 17200 200 1.2037492e-14 2.1e-06 -0.0027511752 - 4e-06 17300 200 1.2142546e-14 2.1e-06 -0.0026060556 - 4e-06 17400 200 1.2259988e-14 2.1e-06 -0.0024596238 - 4e-06 17500 200 1.2151413e-14 2.1e-06 -0.0023119534 - 4e-06 17600 200 1.2016981e-14 2.1e-06 -0.002163119 - 4e-06 17700 200 1.1899607e-14 2.1e-06 -0.0020131953 - 4e-06 17800 200 1.1847233e-14 2.1e-06 -0.0018622579 - 4e-06 17900 200 1.2597274e-14 2.1e-06 -0.0017103828 - 4e-06 18000 200 1.2571584e-14 2.1e-06 -0.0015576465 - 4e-06 18100 200 1.2548167e-14 2.1e-06 -0.0014041259 - 4e-06 18200 200 1.2600584e-14 2.1e-06 -0.0012498983 - 4e-06 18300 200 1.2060676e-14 2.1e-06 -0.0010950413 - 4e-06 18400 200 1.2159889e-14 2.1e-06 -0.00093963286 - 4e-06 18500 200 1.2213635e-14 2.1e-06 -0.00078375133 - 4e-06 18600 200 1.2323751e-14 2.1e-06 -0.00062747516 - 4e-06 18700 200 1.2137887e-14 2.1e-06 -0.00047088304 - 4e-06 18800 200 1.2201084e-14 2.1e-06 -0.00031405381 - 4e-06 18900 200 1.2210617e-14 2.1e-06 -0.00015706645 - 4e-06 19000 200 1.2385845e-14 2.1e-06 2.0903119e-17 -Loop time of 9.48207 on 1 procs for 14000 steps with 200 atoms + 4e-06 5000 200 1.5501104e-06 2.1e-06 0 + 4e-06 5100 200 1.5146077e-06 2.1e-06 -0.00015706645 + 4e-06 5200 200 1.4902158e-06 2.1e-06 -0.00031405381 + 4e-06 5300 200 1.3871134e-06 2.1e-06 -0.00047088304 + 4e-06 5400 200 1.3531184e-06 2.1e-06 -0.00062747516 + 4e-06 5500 200 1.3154278e-06 2.1e-06 -0.00078375133 + 4e-06 5600 200 1.2461265e-06 2.1e-06 -0.00093963286 + 4e-06 5700 200 1.1840322e-06 2.1e-06 -0.0010950413 + 4e-06 5800 200 1.083844e-06 2.1e-06 -0.0012498983 + 4e-06 5900 200 9.8572649e-07 2.1e-06 -0.0014041259 + 4e-06 6000 200 8.6605656e-07 2.1e-06 -0.0015576465 + 4e-06 6100 200 7.6694391e-07 2.1e-06 -0.0017103828 + 4e-06 6200 200 7.1292979e-07 2.1e-06 -0.0018622579 + 4e-06 6300 200 6.475067e-07 2.1e-06 -0.0020131953 + 4e-06 6400 200 5.378202e-07 2.1e-06 -0.002163119 + 4e-06 6500 200 4.5668598e-07 2.1e-06 -0.0023119534 + 4e-06 6600 200 3.1208987e-07 2.1e-06 -0.0024596238 + 4e-06 6700 200 2.2996407e-07 2.1e-06 -0.0026060556 + 4e-06 6800 200 1.658813e-07 2.1e-06 -0.0027511752 + 4e-06 6900 200 1.4495016e-07 2.1e-06 -0.0028949095 + 4e-06 7000 200 1.6172966e-07 2.1e-06 -0.0030371862 + 4e-06 7100 200 4.6620591e-07 2.1e-06 -0.0031779335 + 4e-06 7200 200 6.8121833e-07 2.1e-06 -0.0033170806 + 4e-06 7300 200 1.5506154e-06 2.1e-06 -0.0034545575 + 4e-06 7400 200 2.5919669e-06 2.1e-06 -0.0035902949 + 4e-06 7500 200 2.9403576e-06 2.1e-06 -0.0037242245 + 4e-06 7600 200 2.7726732e-06 2.1e-06 -0.0038562789 + 4e-06 7700 200 2.6586936e-06 2.1e-06 -0.0039863915 + 4e-06 7800 200 2.7059447e-06 2.1e-06 -0.0041144968 + 4e-06 7900 200 2.8454301e-06 2.1e-06 -0.0042405303 + 4e-06 8000 200 2.7747574e-06 2.1e-06 -0.0043644286 + 4e-06 8100 200 2.6329747e-06 2.1e-06 -0.0044861293 + 4e-06 8200 200 2.3654294e-06 2.1e-06 -0.0046055711 + 4e-06 8300 200 2.616465e-06 2.1e-06 -0.0047226938 + 4e-06 8400 200 2.6920973e-06 2.1e-06 -0.0048374385 + 4e-06 8500 200 2.6041158e-06 2.1e-06 -0.0049497475 + 4e-06 8600 200 1.8236056e-06 2.1e-06 -0.005059564 + 4e-06 8700 200 2.1290462e-06 2.1e-06 -0.005166833 + 4e-06 8800 200 1.8723934e-06 2.1e-06 -0.0052715003 + 4e-06 8900 200 1.7196474e-06 2.1e-06 -0.0053735132 + 4e-06 9000 200 1.558001e-06 2.1e-06 -0.0054728204 + 4e-06 9100 200 1.1714433e-06 2.1e-06 -0.0055693718 + 4e-06 9200 200 1.7973167e-06 2.1e-06 -0.005663119 + 4e-06 9300 200 1.4951874e-06 2.1e-06 -0.0057540145 + 4e-06 9400 200 1.197557e-06 2.1e-06 -0.0058420128 + 4e-06 9500 200 1.1638085e-06 2.1e-06 -0.0059270694 + 4e-06 9600 200 1.2591061e-06 2.1e-06 -0.0060091416 + 4e-06 9700 200 1.2747299e-06 2.1e-06 -0.0060881879 + 4e-06 9800 200 1.2424243e-06 2.1e-06 -0.0061641687 + 4e-06 9900 200 1.1624586e-06 2.1e-06 -0.0062370457 + 4e-06 10000 200 1.0724272e-06 2.1e-06 -0.0063067821 + 4e-06 10100 200 1.0806622e-06 2.1e-06 -0.0063733428 + 4e-06 10200 200 9.2046484e-07 2.1e-06 -0.0064366944 + 4e-06 10300 200 8.1801156e-07 2.1e-06 -0.0064968049 + 4e-06 10400 200 7.74927e-07 2.1e-06 -0.0065536441 + 4e-06 10500 200 6.85447e-07 2.1e-06 -0.0066071833 + 4e-06 10600 200 5.4693931e-07 2.1e-06 -0.0066573956 + 4e-06 10700 200 4.5275522e-07 2.1e-06 -0.0067042557 + 4e-06 10800 200 4.2807826e-07 2.1e-06 -0.00674774 + 4e-06 10900 200 3.5676739e-07 2.1e-06 -0.0067878266 + 4e-06 11000 200 2.9448839e-07 2.1e-06 -0.0068244954 + 4e-06 11100 200 2.7397196e-07 2.1e-06 -0.0068577278 + 4e-06 11200 200 1.8313029e-07 2.1e-06 -0.0068875071 + 4e-06 11300 200 1.4616679e-07 2.1e-06 -0.0069138184 + 4e-06 11400 200 1.0916404e-07 2.1e-06 -0.0069366483 + 4e-06 11500 200 7.4608897e-08 2.1e-06 -0.0069559855 + 4e-06 11600 200 4.9799693e-08 2.1e-06 -0.0069718201 + 4e-06 11700 200 2.996701e-08 2.1e-06 -0.0069841441 + 4e-06 11800 200 1.1810054e-08 2.1e-06 -0.0069929515 + 4e-06 11900 200 3.9455661e-09 2.1e-06 -0.0069982376 + 4e-06 12000 200 7.0818836e-11 2.1e-06 -0.007 + 4e-06 12100 200 3.989114e-09 2.1e-06 -0.0069982376 + 4e-06 12200 200 1.0481589e-08 2.1e-06 -0.0069929515 + 4e-06 12300 200 2.3561653e-08 2.1e-06 -0.0069841441 + 4e-06 12400 200 4.1819363e-08 2.1e-06 -0.0069718201 + 4e-06 12500 200 6.5328826e-08 2.1e-06 -0.0069559855 + 4e-06 12600 200 9.3738095e-08 2.1e-06 -0.0069366483 + 4e-06 12700 200 1.3058219e-07 2.1e-06 -0.0069138184 + 4e-06 12800 200 1.7668602e-07 2.1e-06 -0.0068875071 + 4e-06 12900 200 2.1482809e-07 2.1e-06 -0.0068577278 + 4e-06 13000 200 2.7185589e-07 2.1e-06 -0.0068244954 + 4e-06 13100 200 3.3577426e-07 2.1e-06 -0.0067878266 + 4e-06 13200 200 3.9749034e-07 2.1e-06 -0.00674774 + 4e-06 13300 200 5.0743398e-07 2.1e-06 -0.0067042557 + 4e-06 13400 200 5.6629069e-07 2.1e-06 -0.0066573956 + 4e-06 13500 200 5.9092105e-07 2.1e-06 -0.0066071833 + 4e-06 13600 200 7.313638e-07 2.1e-06 -0.0065536441 + 4e-06 13700 200 1.0954352e-06 2.1e-06 -0.0064968049 + 4e-06 13800 200 7.1637332e-07 2.1e-06 -0.0064366944 + 4e-06 13900 200 8.5398051e-07 2.1e-06 -0.0063733428 + 4e-06 14000 200 1.0429888e-06 2.1e-06 -0.0063067821 + 4e-06 14100 200 1.6673022e-07 2.1e-06 -0.0062370457 + 4e-06 14200 200 2.0206568e-08 2.1e-06 -0.0061641687 + 4e-06 14300 200 5.6062261e-09 2.1e-06 -0.0060881879 + 4e-06 14400 200 4.5198973e-09 2.1e-06 -0.0060091416 + 4e-06 14500 200 2.5522353e-09 2.1e-06 -0.0059270694 + 4e-06 14600 200 9.091094e-10 2.1e-06 -0.0058420128 + 4e-06 14700 200 1.3992806e-10 2.1e-06 -0.0057540145 + 4e-06 14800 200 1.0208666e-11 2.1e-06 -0.005663119 + 4e-06 14900 200 8.4078334e-11 2.1e-06 -0.0055693718 + 4e-06 15000 200 1.2567311e-10 2.1e-06 -0.0054728204 + 4e-06 15100 200 5.2285722e-10 2.1e-06 -0.0053735132 + 4e-06 15200 200 1.5839179e-10 2.1e-06 -0.0052715003 + 4e-06 15300 200 3.2283374e-11 2.1e-06 -0.005166833 + 4e-06 15400 200 2.9516435e-12 2.1e-06 -0.005059564 + 4e-06 15500 200 1.0302118e-11 2.1e-06 -0.0049497475 + 4e-06 15600 200 1.7289975e-11 2.1e-06 -0.0048374385 + 4e-06 15700 200 1.4850209e-11 2.1e-06 -0.0047226938 + 4e-06 15800 200 8.0260964e-12 2.1e-06 -0.0046055711 + 4e-06 15900 200 2.616591e-12 2.1e-06 -0.0044861293 + 4e-06 16000 200 3.0793261e-13 2.1e-06 -0.0043644286 + 4e-06 16100 200 4.9187696e-13 2.1e-06 -0.0042405303 + 4e-06 16200 200 3.9849142e-13 2.1e-06 -0.0041144968 + 4e-06 16300 200 5.2823345e-13 2.1e-06 -0.0039863915 + 4e-06 16400 200 3.9902725e-13 2.1e-06 -0.0038562789 + 4e-06 16500 200 1.9259043e-13 2.1e-06 -0.0037242245 + 4e-06 16600 200 5.3557316e-14 2.1e-06 -0.0035902949 + 4e-06 16700 200 3.7734621e-15 2.1e-06 -0.0034545575 + 4e-06 16800 200 3.0867115e-15 2.1e-06 -0.0033170806 + 4e-06 16900 200 1.1841579e-14 2.1e-06 -0.0031779335 + 4e-06 17000 200 1.3850503e-14 2.1e-06 -0.0030371862 + 4e-06 17100 200 9.8491914e-15 2.1e-06 -0.0028949095 + 4e-06 17200 200 4.7140149e-15 2.1e-06 -0.0027511752 + 4e-06 17300 200 1.3440466e-15 2.1e-06 -0.0026060556 + 4e-06 17400 200 1.0627828e-16 2.1e-06 -0.0024596238 + 4e-06 17500 200 6.2015781e-17 2.1e-06 -0.0023119534 + 4e-06 17600 200 2.8723007e-16 2.1e-06 -0.002163119 + 4e-06 17700 200 3.6601367e-16 2.1e-06 -0.0020131953 + 4e-06 17800 200 2.7862312e-16 2.1e-06 -0.0018622579 + 4e-06 17900 200 1.4268051e-16 2.1e-06 -0.0017103828 + 4e-06 18000 200 4.5443603e-17 2.1e-06 -0.0015576465 + 4e-06 18100 200 5.2330376e-18 2.1e-06 -0.0014041259 + 4e-06 18200 200 7.3566254e-19 2.1e-06 -0.0012498983 + 4e-06 18300 200 6.5880468e-18 2.1e-06 -0.0010950413 + 4e-06 18400 200 9.5744931e-18 2.1e-06 -0.00093963286 + 4e-06 18500 200 7.8604487e-18 2.1e-06 -0.00078375133 + 4e-06 18600 200 4.3166295e-18 2.1e-06 -0.00062747516 + 4e-06 18700 200 1.5188792e-18 2.1e-06 -0.00047088304 + 4e-06 18800 200 2.3221067e-19 2.1e-06 -0.00031405381 + 4e-06 18900 200 4.7558964e-21 2.1e-06 -0.00015706645 + 4e-06 19000 200 1.4567292e-19 2.1e-06 2.0903119e-17 +Loop time of 6.96616 on 1 procs for 14000 steps with 200 atoms -99.6% CPU use with 1 MPI tasks x no OpenMP threads +99.5% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 5.3814 | 5.3814 | 5.3814 | 0.0 | 56.75 -Neigh | 0.04326 | 0.04326 | 0.04326 | 0.0 | 0.46 -Comm | 0.0018574 | 0.0018574 | 0.0018574 | 0.0 | 0.02 -Output | 0.0018533 | 0.0018533 | 0.0018533 | 0.0 | 0.02 -Modify | 4.047 | 4.047 | 4.047 | 0.0 | 42.68 -Other | | 0.006661 | | | 0.07 +Pair | 3.8534 | 3.8534 | 3.8534 | 0.0 | 55.32 +Neigh | 0.038778 | 0.038778 | 0.038778 | 0.0 | 0.56 +Comm | 0.0015081 | 0.0015081 | 0.0015081 | 0.0 | 0.02 +Output | 0.0018007 | 0.0018007 | 0.0018007 | 0.0 | 0.03 +Modify | 3.0668 | 3.0668 | 3.0668 | 0.0 | 44.02 +Other | | 0.003851 | | | 0.06 Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 3146 ave 3146 max 3146 min +Neighs: 3031 ave 3031 max 3031 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 3146 -Ave neighs/atom = 15.73 +Total # of neighbors = 3031 +Ave neighs/atom = 15.155 Neighbor list builds = 233 Dangerous builds not checked @@ -532,170 +536,170 @@ run 14000 Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule Per MPI rank memory allocation (min/avg/max) = 72.31 | 72.31 | 72.31 Mbytes Dt Step Atoms KinEng Volume v_disp_upper - 4e-06 19000 200 1.2385845e-14 2.1e-06 0 - 4e-06 19100 200 1.2261513e-05 2.1e-06 0.00010097765 - 4e-06 19200 200 1.668842e-05 2.1e-06 0.00020194258 - 4e-06 19300 200 8.188349e-06 2.1e-06 0.00030288209 - 4e-06 19400 200 3.786144e-06 2.1e-06 0.00040378347 - 4e-06 19500 200 9.574368e-06 2.1e-06 0.00050463403 - 4e-06 19600 200 1.1344815e-05 2.1e-06 0.00060542105 - 4e-06 19700 200 5.9381813e-06 2.1e-06 0.00070613186 - 4e-06 19800 200 6.6666301e-06 2.1e-06 0.00080675378 - 4e-06 19900 200 1.090387e-05 2.1e-06 0.00090727414 - 4e-06 20000 200 7.740567e-06 2.1e-06 0.0010076803 - 4e-06 20100 200 6.2375154e-06 2.1e-06 0.0011079596 - 4e-06 20200 200 9.3040254e-06 2.1e-06 0.0012080994 - 4e-06 20300 200 8.9696433e-06 2.1e-06 0.0013080871 - 4e-06 20400 200 6.5727278e-06 2.1e-06 0.0014079102 - 4e-06 20500 200 7.762698e-06 2.1e-06 0.001507556 - 4e-06 20600 200 9.2433982e-06 2.1e-06 0.0016070121 - 4e-06 20700 200 7.3505514e-06 2.1e-06 0.0017062658 - 4e-06 20800 200 6.9601084e-06 2.1e-06 0.0018053047 - 4e-06 20900 200 8.6605025e-06 2.1e-06 0.0019041164 - 4e-06 21000 200 8.0661649e-06 2.1e-06 0.0020026884 - 4e-06 21100 200 6.9330037e-06 2.1e-06 0.0021010083 - 4e-06 21200 200 7.8802994e-06 2.1e-06 0.0021990637 - 4e-06 21300 200 8.12707e-06 2.1e-06 0.0022968422 - 4e-06 21400 200 7.1184483e-06 2.1e-06 0.0023943316 - 4e-06 21500 200 7.3747722e-06 2.1e-06 0.0024915196 - 4e-06 21600 200 7.941038e-06 2.1e-06 0.0025883939 - 4e-06 21700 200 7.2906871e-06 2.1e-06 0.0026849424 - 4e-06 21800 200 7.0584615e-06 2.1e-06 0.0027811529 - 4e-06 21900 200 7.6303484e-06 2.1e-06 0.0028770133 - 4e-06 22000 200 7.3276603e-06 2.1e-06 0.0029725116 - 4e-06 22100 200 7.0392936e-06 2.1e-06 0.0030676356 - 4e-06 22200 200 7.1860378e-06 2.1e-06 0.0031623734 - 4e-06 22300 200 7.1628093e-06 2.1e-06 0.0032567132 - 4e-06 22400 200 6.9556524e-06 2.1e-06 0.0033506429 - 4e-06 22500 200 6.9109402e-06 2.1e-06 0.0034441509 - 4e-06 22600 200 6.981937e-06 2.1e-06 0.0035372253 - 4e-06 22700 200 6.8009271e-06 2.1e-06 0.0036298544 - 4e-06 22800 200 6.6923037e-06 2.1e-06 0.0037220265 - 4e-06 22900 200 6.7438993e-06 2.1e-06 0.0038137301 - 4e-06 23000 200 6.6280705e-06 2.1e-06 0.0039049537 - 4e-06 23100 200 6.4659616e-06 2.1e-06 0.0039956856 - 4e-06 23200 200 6.486839e-06 2.1e-06 0.0040859145 - 4e-06 23300 200 6.4478859e-06 2.1e-06 0.0041756291 - 4e-06 23400 200 6.2666043e-06 2.1e-06 0.004264818 - 4e-06 23500 200 6.2352434e-06 2.1e-06 0.00435347 - 4e-06 23600 200 6.2074024e-06 2.1e-06 0.004441574 - 4e-06 23700 200 6.068366e-06 2.1e-06 0.0045291188 - 4e-06 23800 200 5.9784229e-06 2.1e-06 0.0046160935 - 4e-06 23900 200 5.9536629e-06 2.1e-06 0.0047024871 - 4e-06 24000 200 5.8480609e-06 2.1e-06 0.0047882887 - 4e-06 24100 200 5.707216e-06 2.1e-06 0.0048734875 - 4e-06 24200 200 5.6922834e-06 2.1e-06 0.0049580728 - 4e-06 24300 200 5.6187319e-06 2.1e-06 0.005042034 - 4e-06 24400 200 5.4774741e-06 2.1e-06 0.0051253604 - 4e-06 24500 200 5.4144843e-06 2.1e-06 0.0052080417 - 4e-06 24600 200 5.3595768e-06 2.1e-06 0.0052900673 - 4e-06 24700 200 5.2374057e-06 2.1e-06 0.0053714269 - 4e-06 24800 200 5.1410204e-06 2.1e-06 0.0054521104 - 4e-06 24900 200 5.0888231e-06 2.1e-06 0.0055321075 - 4e-06 25000 200 4.984139e-06 2.1e-06 0.0056114082 - 4e-06 25100 200 4.9836569e-06 2.1e-06 0.0056900025 - 4e-06 25200 200 4.7331289e-06 2.1e-06 0.0057678805 - 4e-06 25300 200 4.6728119e-06 2.1e-06 0.0058450324 - 4e-06 25400 200 4.7016583e-06 2.1e-06 0.0059214485 - 4e-06 25500 200 4.5200193e-06 2.1e-06 0.0059971192 - 4e-06 25600 200 4.378095e-06 2.1e-06 0.0060720349 - 4e-06 25700 200 4.3949017e-06 2.1e-06 0.0061461862 - 4e-06 25800 200 4.2795904e-06 2.1e-06 0.0062195638 - 4e-06 25900 200 4.116551e-06 2.1e-06 0.0062921585 - 4e-06 26000 200 4.0844003e-06 2.1e-06 0.006363961 - 4e-06 26100 200 4.0601132e-06 2.1e-06 0.0064349624 - 4e-06 26200 200 3.8632558e-06 2.1e-06 0.0065051538 - 4e-06 26300 200 3.7501901e-06 2.1e-06 0.0065745262 - 4e-06 26400 200 3.7665658e-06 2.1e-06 0.006643071 - 4e-06 26500 200 3.6221171e-06 2.1e-06 0.0067107795 - 4e-06 26600 200 3.483452e-06 2.1e-06 0.0067776432 - 4e-06 26700 200 3.4573133e-06 2.1e-06 0.0068436537 - 4e-06 26800 200 3.3725298e-06 2.1e-06 0.0069088027 - 4e-06 26900 200 3.2275695e-06 2.1e-06 0.0069730819 - 4e-06 27000 200 3.1636462e-06 2.1e-06 0.0070364833 - 4e-06 27100 200 3.1002791e-06 2.1e-06 0.007098999 - 4e-06 27200 200 2.9719515e-06 2.1e-06 0.0071606209 - 4e-06 27300 200 2.8999181e-06 2.1e-06 0.0072213415 - 4e-06 27400 200 2.8296722e-06 2.1e-06 0.0072811529 - 4e-06 27500 200 2.7244185e-06 2.1e-06 0.0073400478 - 4e-06 27600 200 2.6342108e-06 2.1e-06 0.0073980187 - 4e-06 27700 200 2.5655873e-06 2.1e-06 0.0074550582 - 4e-06 27800 200 2.4771843e-06 2.1e-06 0.0075111593 - 4e-06 27900 200 2.3805529e-06 2.1e-06 0.0075663148 - 4e-06 28000 200 2.3094253e-06 2.1e-06 0.0076205178 - 4e-06 28100 200 2.2443631e-06 2.1e-06 0.0076737615 - 4e-06 28200 200 2.1339799e-06 2.1e-06 0.0077260391 - 4e-06 28300 200 2.0525827e-06 2.1e-06 0.0077773442 - 4e-06 28400 200 2.0012311e-06 2.1e-06 0.0078276702 - 4e-06 28500 200 1.9064828e-06 2.1e-06 0.0078770108 - 4e-06 28600 200 1.8186848e-06 2.1e-06 0.0079253598 - 4e-06 28700 200 1.7614909e-06 2.1e-06 0.0079727111 - 4e-06 28800 200 1.6854916e-06 2.1e-06 0.0080190587 - 4e-06 28900 200 1.5987487e-06 2.1e-06 0.0080643969 - 4e-06 29000 200 1.5345142e-06 2.1e-06 0.0081087198 - 4e-06 29100 200 1.4807046e-06 2.1e-06 0.008152022 - 4e-06 29200 200 1.3891852e-06 2.1e-06 0.0081942979 - 4e-06 29300 200 1.3152808e-06 2.1e-06 0.0082355423 - 4e-06 29400 200 1.2682955e-06 2.1e-06 0.00827575 - 4e-06 29500 200 1.1980726e-06 2.1e-06 0.0083149158 - 4e-06 29600 200 1.1206391e-06 2.1e-06 0.0083530349 - 4e-06 29700 200 1.069315e-06 2.1e-06 0.0083901025 - 4e-06 29800 200 1.0128853e-06 2.1e-06 0.0084261138 - 4e-06 29900 200 9.4294228e-07 2.1e-06 0.0084610645 - 4e-06 30000 200 8.8682322e-07 2.1e-06 0.00849495 - 4e-06 30100 200 8.3143727e-07 2.1e-06 0.0085277661 - 4e-06 30200 200 7.7886925e-07 2.1e-06 0.0085595086 - 4e-06 30300 200 7.2644265e-07 2.1e-06 0.0085901737 - 4e-06 30400 200 6.7416382e-07 2.1e-06 0.0086197574 - 4e-06 30500 200 6.2520867e-07 2.1e-06 0.0086482559 - 4e-06 30600 200 5.7710448e-07 2.1e-06 0.0086756657 - 4e-06 30700 200 5.3156928e-07 2.1e-06 0.0087019834 - 4e-06 30800 200 4.8684727e-07 2.1e-06 0.0087272057 - 4e-06 30900 200 4.4454752e-07 2.1e-06 0.0087513293 - 4e-06 31000 200 4.0418128e-07 2.1e-06 0.0087743512 - 4e-06 31100 200 3.677997e-07 2.1e-06 0.0087962686 - 4e-06 31200 200 3.2762411e-07 2.1e-06 0.0088170786 - 4e-06 31300 200 2.9156601e-07 2.1e-06 0.0088367787 - 4e-06 31400 200 2.6235825e-07 2.1e-06 0.0088553663 - 4e-06 31500 200 2.2926207e-07 2.1e-06 0.0088728392 - 4e-06 31600 200 1.9870435e-07 2.1e-06 0.0088891951 - 4e-06 31700 200 1.7318685e-07 2.1e-06 0.0089044319 - 4e-06 31800 200 1.4793716e-07 2.1e-06 0.0089185479 - 4e-06 31900 200 1.2335756e-07 2.1e-06 0.0089315411 - 4e-06 32000 200 1.024269e-07 2.1e-06 0.0089434099 - 4e-06 32100 200 8.4811971e-08 2.1e-06 0.0089541529 - 4e-06 32200 200 6.5610079e-08 2.1e-06 0.0089637686 - 4e-06 32300 200 4.9804549e-08 2.1e-06 0.008972256 - 4e-06 32400 200 3.7696394e-08 2.1e-06 0.0089796139 - 4e-06 32500 200 2.6121364e-08 2.1e-06 0.0089858413 - 4e-06 32600 200 1.6302764e-08 2.1e-06 0.0089909376 - 4e-06 32700 200 9.4496486e-09 2.1e-06 0.008994902 - 4e-06 32800 200 4.3514823e-09 2.1e-06 0.0089977341 - 4e-06 32900 200 1.0546756e-09 2.1e-06 0.0089994335 - 4e-06 33000 200 7.3695568e-13 2.1e-06 0.009 -Loop time of 11.7961 on 1 procs for 14000 steps with 200 atoms + 4e-06 19000 200 1.4567292e-19 2.1e-06 0 + 4e-06 19100 200 1.9132195e-05 2.1e-06 0.00010097765 + 4e-06 19200 200 3.1561748e-06 2.1e-06 0.00020194258 + 4e-06 19300 200 1.4462178e-05 2.1e-06 0.00030288209 + 4e-06 19400 200 4.6622112e-06 2.1e-06 0.00040378347 + 4e-06 19500 200 1.1929852e-05 2.1e-06 0.00050463403 + 4e-06 19600 200 5.6933661e-06 2.1e-06 0.00060542105 + 4e-06 19700 200 1.0429976e-05 2.1e-06 0.00070613186 + 4e-06 19800 200 6.6580254e-06 2.1e-06 0.00080675378 + 4e-06 19900 200 9.1721686e-06 2.1e-06 0.00090727414 + 4e-06 20000 200 7.4553343e-06 2.1e-06 0.0010076803 + 4e-06 20100 200 8.3534813e-06 2.1e-06 0.0011079596 + 4e-06 20200 200 7.8671075e-06 2.1e-06 0.0012080994 + 4e-06 20300 200 7.9115898e-06 2.1e-06 0.0013080871 + 4e-06 20400 200 8.2222312e-06 2.1e-06 0.0014079102 + 4e-06 20500 200 7.5281175e-06 2.1e-06 0.001507556 + 4e-06 20600 200 8.4242027e-06 2.1e-06 0.0016070121 + 4e-06 20700 200 7.3282364e-06 2.1e-06 0.0017062658 + 4e-06 20800 200 8.3501222e-06 2.1e-06 0.0018053047 + 4e-06 20900 200 7.3417566e-06 2.1e-06 0.0019041164 + 4e-06 21000 200 8.0702927e-06 2.1e-06 0.0020026884 + 4e-06 21100 200 7.5896194e-06 2.1e-06 0.0021010083 + 4e-06 21200 200 7.6596342e-06 2.1e-06 0.0021990637 + 4e-06 21300 200 7.7009755e-06 2.1e-06 0.0022968422 + 4e-06 21400 200 7.4010568e-06 2.1e-06 0.0023943316 + 4e-06 21500 200 7.7254953e-06 2.1e-06 0.0024915196 + 4e-06 21600 200 7.2931076e-06 2.1e-06 0.0025883939 + 4e-06 21700 200 7.5667043e-06 2.1e-06 0.0026849424 + 4e-06 21800 200 7.2767179e-06 2.1e-06 0.0027811529 + 4e-06 21900 200 7.3632148e-06 2.1e-06 0.0028770133 + 4e-06 22000 200 7.2563523e-06 2.1e-06 0.0029725116 + 4e-06 22100 200 7.2003226e-06 2.1e-06 0.0030676356 + 4e-06 22200 200 7.1862422e-06 2.1e-06 0.0031623734 + 4e-06 22300 200 7.0035785e-06 2.1e-06 0.0032567132 + 4e-06 22400 200 7.1023437e-06 2.1e-06 0.0033506429 + 4e-06 22500 200 6.8767896e-06 2.1e-06 0.0034441509 + 4e-06 22600 200 6.9556381e-06 2.1e-06 0.0035372253 + 4e-06 22700 200 6.7754491e-06 2.1e-06 0.0036298544 + 4e-06 22800 200 6.7752923e-06 2.1e-06 0.0037220265 + 4e-06 22900 200 6.6947789e-06 2.1e-06 0.0038137301 + 4e-06 23000 200 6.5811876e-06 2.1e-06 0.0039049537 + 4e-06 23100 200 6.5600064e-06 2.1e-06 0.0039956856 + 4e-06 23200 200 6.407054e-06 2.1e-06 0.0040859145 + 4e-06 23300 200 6.4635326e-06 2.1e-06 0.0041756291 + 4e-06 23400 200 6.2604509e-06 2.1e-06 0.004264818 + 4e-06 23500 200 6.2914059e-06 2.1e-06 0.00435347 + 4e-06 23600 200 6.1416598e-06 2.1e-06 0.004441574 + 4e-06 23700 200 6.0839487e-06 2.1e-06 0.0045291188 + 4e-06 23800 200 6.0216029e-06 2.1e-06 0.0046160935 + 4e-06 23900 200 5.896464e-06 2.1e-06 0.0047024871 + 4e-06 24000 200 5.8682556e-06 2.1e-06 0.0047882887 + 4e-06 24100 200 5.8744357e-06 2.1e-06 0.0048734875 + 4e-06 24200 200 5.6172509e-06 2.1e-06 0.0049580728 + 4e-06 24300 200 5.6527872e-06 2.1e-06 0.005042034 + 4e-06 24400 200 5.4706998e-06 2.1e-06 0.0051253604 + 4e-06 24500 200 5.4368713e-06 2.1e-06 0.0052080417 + 4e-06 24600 200 5.3496195e-06 2.1e-06 0.0052900673 + 4e-06 24700 200 5.2020248e-06 2.1e-06 0.0053714269 + 4e-06 24800 200 5.2035809e-06 2.1e-06 0.0054521104 + 4e-06 24900 200 5.0302031e-06 2.1e-06 0.0055321075 + 4e-06 25000 200 5.0094633e-06 2.1e-06 0.0056114082 + 4e-06 25100 200 4.8588064e-06 2.1e-06 0.0056900025 + 4e-06 25200 200 4.8221437e-06 2.1e-06 0.0057678805 + 4e-06 25300 200 4.7117322e-06 2.1e-06 0.0058450324 + 4e-06 25400 200 4.6148719e-06 2.1e-06 0.0059214485 + 4e-06 25500 200 4.5348297e-06 2.1e-06 0.0059971192 + 4e-06 25600 200 4.4325937e-06 2.1e-06 0.0060720349 + 4e-06 25700 200 4.3587865e-06 2.1e-06 0.0061461862 + 4e-06 25800 200 4.2449842e-06 2.1e-06 0.0062195638 + 4e-06 25900 200 4.1730814e-06 2.1e-06 0.0062921585 + 4e-06 26000 200 4.0712085e-06 2.1e-06 0.006363961 + 4e-06 26100 200 3.9603603e-06 2.1e-06 0.0064349624 + 4e-06 26200 200 3.9152641e-06 2.1e-06 0.0065051538 + 4e-06 26300 200 3.7864366e-06 2.1e-06 0.0065745262 + 4e-06 26400 200 3.7211553e-06 2.1e-06 0.006643071 + 4e-06 26500 200 3.6038142e-06 2.1e-06 0.0067107795 + 4e-06 26600 200 3.5518456e-06 2.1e-06 0.0067776432 + 4e-06 26700 200 3.4213616e-06 2.1e-06 0.0068436537 + 4e-06 26800 200 3.348649e-06 2.1e-06 0.0069088027 + 4e-06 26900 200 3.2592054e-06 2.1e-06 0.0069730819 + 4e-06 27000 200 3.1640896e-06 2.1e-06 0.0070364833 + 4e-06 27100 200 3.1491467e-06 2.1e-06 0.007098999 + 4e-06 27200 200 2.9475347e-06 2.1e-06 0.0071606209 + 4e-06 27300 200 2.9234007e-06 2.1e-06 0.0072213415 + 4e-06 27400 200 2.8106832e-06 2.1e-06 0.0072811529 + 4e-06 27500 200 2.7190831e-06 2.1e-06 0.0073400478 + 4e-06 27600 200 2.6595021e-06 2.1e-06 0.0073980187 + 4e-06 27700 200 2.5384163e-06 2.1e-06 0.0074550582 + 4e-06 27800 200 2.4906759e-06 2.1e-06 0.0075111593 + 4e-06 27900 200 2.3760852e-06 2.1e-06 0.0075663148 + 4e-06 28000 200 2.3135864e-06 2.1e-06 0.0076205178 + 4e-06 28100 200 2.206388e-06 2.1e-06 0.0076737615 + 4e-06 28200 200 2.1580755e-06 2.1e-06 0.0077260391 + 4e-06 28300 200 2.0541807e-06 2.1e-06 0.0077773442 + 4e-06 28400 200 1.9879886e-06 2.1e-06 0.0078276702 + 4e-06 28500 200 1.9080731e-06 2.1e-06 0.0078770108 + 4e-06 28600 200 1.8244513e-06 2.1e-06 0.0079253598 + 4e-06 28700 200 1.7612085e-06 2.1e-06 0.0079727111 + 4e-06 28800 200 1.6725418e-06 2.1e-06 0.0080190587 + 4e-06 28900 200 1.6108221e-06 2.1e-06 0.0080643969 + 4e-06 29000 200 1.5315923e-06 2.1e-06 0.0081087198 + 4e-06 29100 200 1.4668177e-06 2.1e-06 0.008152022 + 4e-06 29200 200 1.389947e-06 2.1e-06 0.0081942979 + 4e-06 29300 200 1.3244327e-06 2.1e-06 0.0082355423 + 4e-06 29400 200 1.2613389e-06 2.1e-06 0.00827575 + 4e-06 29500 200 1.189317e-06 2.1e-06 0.0083149158 + 4e-06 29600 200 1.1328651e-06 2.1e-06 0.0083530349 + 4e-06 29700 200 1.0634003e-06 2.1e-06 0.0083901025 + 4e-06 29800 200 1.0089659e-06 2.1e-06 0.0084261138 + 4e-06 29900 200 9.452383e-07 2.1e-06 0.0084610645 + 4e-06 30000 200 8.8857387e-07 2.1e-06 0.00849495 + 4e-06 30100 200 8.3934751e-07 2.1e-06 0.0085277661 + 4e-06 30200 200 7.7404495e-07 2.1e-06 0.0085595086 + 4e-06 30300 200 7.2760888e-07 2.1e-06 0.0085901737 + 4e-06 30400 200 6.7239685e-07 2.1e-06 0.0086197574 + 4e-06 30500 200 6.245416e-07 2.1e-06 0.0086482559 + 4e-06 30600 200 5.7834155e-07 2.1e-06 0.0086756657 + 4e-06 30700 200 5.2814574e-07 2.1e-06 0.0087019834 + 4e-06 30800 200 4.8878902e-07 2.1e-06 0.0087272057 + 4e-06 30900 200 4.4241206e-07 2.1e-06 0.0087513293 + 4e-06 31000 200 4.0442514e-07 2.1e-06 0.0087743512 + 4e-06 31100 200 3.642199e-07 2.1e-06 0.0087962686 + 4e-06 31200 200 3.2738558e-07 2.1e-06 0.0088170786 + 4e-06 31300 200 2.9389397e-07 2.1e-06 0.0088367787 + 4e-06 31400 200 2.5861566e-07 2.1e-06 0.0088553663 + 4e-06 31500 200 2.2934636e-07 2.1e-06 0.0088728392 + 4e-06 31600 200 1.9888494e-07 2.1e-06 0.0088891951 + 4e-06 31700 200 1.7250531e-07 2.1e-06 0.0089044319 + 4e-06 31800 200 1.4678036e-07 2.1e-06 0.0089185479 + 4e-06 31900 200 1.2324632e-07 2.1e-06 0.0089315411 + 4e-06 32000 200 1.0248084e-07 2.1e-06 0.0089434099 + 4e-06 32100 200 8.2609273e-08 2.1e-06 0.0089541529 + 4e-06 32200 200 6.551679e-08 2.1e-06 0.0089637686 + 4e-06 32300 200 5.0080052e-08 2.1e-06 0.008972256 + 4e-06 32400 200 3.6856646e-08 2.1e-06 0.0089796139 + 4e-06 32500 200 2.5648284e-08 2.1e-06 0.0089858413 + 4e-06 32600 200 1.637837e-08 2.1e-06 0.0089909376 + 4e-06 32700 200 9.2578154e-09 2.1e-06 0.008994902 + 4e-06 32800 200 4.0824723e-09 2.1e-06 0.0089977341 + 4e-06 32900 200 1.0371165e-09 2.1e-06 0.0089994335 + 4e-06 33000 200 6.1012168e-14 2.1e-06 0.009 +Loop time of 7.70808 on 1 procs for 14000 steps with 200 atoms 99.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 7.033 | 7.033 | 7.033 | 0.0 | 59.62 -Neigh | 0.047308 | 0.047308 | 0.047308 | 0.0 | 0.40 -Comm | 0.0020382 | 0.0020382 | 0.0020382 | 0.0 | 0.02 -Output | 0.0022072 | 0.0022072 | 0.0022072 | 0.0 | 0.02 -Modify | 4.7043 | 4.7043 | 4.7043 | 0.0 | 39.88 -Other | | 0.00727 | | | 0.06 +Pair | 4.4414 | 4.4414 | 4.4414 | 0.0 | 57.62 +Neigh | 0.040941 | 0.040941 | 0.040941 | 0.0 | 0.53 +Comm | 0.001526 | 0.001526 | 0.001526 | 0.0 | 0.02 +Output | 0.0019617 | 0.0019617 | 0.0019617 | 0.0 | 0.03 +Modify | 3.2183 | 3.2183 | 3.2183 | 0.0 | 41.75 +Other | | 0.003942 | | | 0.05 Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 3145 ave 3145 max 3145 min +Neighs: 3026 ave 3026 max 3026 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 3145 -Ave neighs/atom = 15.725 +Total # of neighbors = 3026 +Ave neighs/atom = 15.13 Neighbor list builds = 233 Dangerous builds not checked @@ -712,80 +716,80 @@ run 5000 Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule Per MPI rank memory allocation (min/avg/max) = 72.31 | 72.31 | 72.31 Mbytes Dt Step Atoms KinEng Volume v_disp_upper - 4e-06 33000 200 7.3695568e-13 2.1e-06 0.009 - 4e-06 33100 200 1.0383246e-10 2.1e-06 0.009 - 4e-06 33200 200 5.9976193e-12 2.1e-06 0.009 - 4e-06 33300 200 6.2729949e-12 2.1e-06 0.009 - 4e-06 33400 200 9.0819715e-12 2.1e-06 0.009 - 4e-06 33500 200 4.1741245e-12 2.1e-06 0.009 - 4e-06 33600 200 4.2796157e-13 2.1e-06 0.009 - 4e-06 33700 200 1.2198973e-13 2.1e-06 0.009 - 4e-06 33800 200 5.0253099e-13 2.1e-06 0.009 - 4e-06 33900 200 3.2987112e-13 2.1e-06 0.009 - 4e-06 34000 200 9.8474325e-14 2.1e-06 0.009 - 4e-06 34100 200 2.0804908e-14 2.1e-06 0.009 - 4e-06 34200 200 3.5479858e-14 2.1e-06 0.009 - 4e-06 34300 200 4.6823841e-14 2.1e-06 0.009 - 4e-06 34400 200 2.8845396e-14 2.1e-06 0.009 - 4e-06 34500 200 2.4894095e-14 2.1e-06 0.009 - 4e-06 34600 200 2.4407576e-14 2.1e-06 0.009 - 4e-06 34700 200 2.4241607e-14 2.1e-06 0.009 - 4e-06 34800 200 2.5678797e-14 2.1e-06 0.009 - 4e-06 34900 200 3.0880003e-14 2.1e-06 0.009 - 4e-06 35000 200 3.3341003e-14 2.1e-06 0.009 - 4e-06 35100 200 1.5611246e-11 2.1e-06 0.009 - 4e-06 35200 200 8.7304571e-13 2.1e-06 0.009 - 4e-06 35300 200 1.28235e-13 2.1e-06 0.009 - 4e-06 35400 200 4.7975116e-13 2.1e-06 0.009 - 4e-06 35500 200 4.0667584e-13 2.1e-06 0.009 - 4e-06 35600 200 1.1230838e-13 2.1e-06 0.009 - 4e-06 35700 200 3.0578739e-14 2.1e-06 0.009 - 4e-06 35800 200 5.2724197e-14 2.1e-06 0.009 - 4e-06 35900 200 5.4930313e-14 2.1e-06 0.009 - 4e-06 36000 200 5.0413822e-14 2.1e-06 0.009 - 4e-06 36100 200 4.2936129e-14 2.1e-06 0.009 - 4e-06 36200 200 4.2946116e-14 2.1e-06 0.009 - 4e-06 36300 200 4.5163485e-14 2.1e-06 0.009 - 4e-06 36400 200 4.6640704e-14 2.1e-06 0.009 - 4e-06 36500 200 4.6581622e-14 2.1e-06 0.009 - 4e-06 36600 200 4.6319151e-14 2.1e-06 0.009 - 4e-06 36700 200 4.5444461e-14 2.1e-06 0.009 - 4e-06 36800 200 4.6152933e-14 2.1e-06 0.009 - 4e-06 36900 200 4.5660145e-14 2.1e-06 0.009 - 4e-06 37000 200 4.479585e-14 2.1e-06 0.009 - 4e-06 37100 200 4.454612e-14 2.1e-06 0.009 - 4e-06 37200 200 4.3595031e-14 2.1e-06 0.009 - 4e-06 37300 200 4.2650848e-14 2.1e-06 0.009 - 4e-06 37400 200 4.3124042e-14 2.1e-06 0.009 - 4e-06 37500 200 4.1053224e-14 2.1e-06 0.009 - 4e-06 37600 200 4.2786157e-14 2.1e-06 0.009 - 4e-06 37700 200 4.3961233e-14 2.1e-06 0.009 - 4e-06 37800 200 4.359215e-14 2.1e-06 0.009 - 4e-06 37900 200 4.3410766e-14 2.1e-06 0.009 - 4e-06 38000 200 3.9866697e-14 2.1e-06 0.009 -Loop time of 4.29106 on 1 procs for 5000 steps with 200 atoms + 4e-06 33000 200 6.1012168e-14 2.1e-06 0.009 + 4e-06 33100 200 6.7902539e-11 2.1e-06 0.009 + 4e-06 33200 200 2.0896758e-11 2.1e-06 0.009 + 4e-06 33300 200 2.5200405e-11 2.1e-06 0.009 + 4e-06 33400 200 2.1747895e-12 2.1e-06 0.009 + 4e-06 33500 200 1.1228817e-11 2.1e-06 0.009 + 4e-06 33600 200 3.3597579e-12 2.1e-06 0.009 + 4e-06 33700 200 1.4808583e-12 2.1e-06 0.009 + 4e-06 33800 200 3.5132295e-12 2.1e-06 0.009 + 4e-06 33900 200 8.2438639e-14 2.1e-06 0.009 + 4e-06 34000 200 1.3267378e-12 2.1e-06 0.009 + 4e-06 34100 200 6.2365031e-13 2.1e-06 0.009 + 4e-06 34200 200 1.1820072e-13 2.1e-06 0.009 + 4e-06 34300 200 5.2797742e-13 2.1e-06 0.009 + 4e-06 34400 200 3.2199555e-14 2.1e-06 0.009 + 4e-06 34500 200 1.553388e-13 2.1e-06 0.009 + 4e-06 34600 200 1.1458173e-13 2.1e-06 0.009 + 4e-06 34700 200 5.8686124e-15 2.1e-06 0.009 + 4e-06 34800 200 7.3486748e-14 2.1e-06 0.009 + 4e-06 34900 200 1.0877367e-14 2.1e-06 0.009 + 4e-06 35000 200 1.5284442e-14 2.1e-06 0.009 + 4e-06 35100 200 2.0294057e-14 2.1e-06 0.009 + 4e-06 35200 200 1.5385334e-17 2.1e-06 0.009 + 4e-06 35300 200 9.5858898e-15 2.1e-06 0.009 + 4e-06 35400 200 3.1985384e-15 2.1e-06 0.009 + 4e-06 35500 200 1.1327574e-15 2.1e-06 0.009 + 4e-06 35600 200 3.3810722e-15 2.1e-06 0.009 + 4e-06 35700 200 1.2867327e-16 2.1e-06 0.009 + 4e-06 35800 200 1.0755232e-15 2.1e-06 0.009 + 4e-06 35900 200 7.3381985e-16 2.1e-06 0.009 + 4e-06 36000 200 3.7750251e-17 2.1e-06 0.009 + 4e-06 36100 200 4.8518794e-16 2.1e-06 0.009 + 4e-06 36200 200 8.361623e-17 2.1e-06 0.009 + 4e-06 36300 200 8.9347649e-17 2.1e-06 0.009 + 4e-06 36400 200 1.4528409e-16 2.1e-06 0.009 + 4e-06 36500 200 8.2328133e-19 2.1e-06 0.009 + 4e-06 36600 200 5.9628413e-17 2.1e-06 0.009 + 4e-06 36700 200 2.857306e-17 2.1e-06 0.009 + 4e-06 36800 200 4.1078269e-18 2.1e-06 0.009 + 4e-06 36900 200 2.4094514e-17 2.1e-06 0.009 + 4e-06 37000 200 2.6153896e-18 2.1e-06 0.009 + 4e-06 37100 200 5.6577297e-18 2.1e-06 0.009 + 4e-06 37200 200 6.5849416e-18 2.1e-06 0.009 + 4e-06 37300 200 4.5596918e-21 2.1e-06 0.009 + 4e-06 37400 200 3.2329813e-18 2.1e-06 0.009 + 4e-06 37500 200 1.123288e-18 2.1e-06 0.009 + 4e-06 37600 200 3.4227094e-19 2.1e-06 0.009 + 4e-06 37700 200 1.1782135e-18 2.1e-06 0.009 + 4e-06 37800 200 6.9535961e-20 2.1e-06 0.009 + 4e-06 37900 200 3.4055174e-19 2.1e-06 0.009 + 4e-06 38000 200 2.8968649e-19 2.1e-06 0.009 +Loop time of 2.65906 on 1 procs for 5000 steps with 200 atoms 99.6% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 2.6156 | 2.6156 | 2.6156 | 0.0 | 60.95 -Neigh | 0.017028 | 0.017028 | 0.017028 | 0.0 | 0.40 -Comm | 0.00059632 | 0.00059632 | 0.00059632 | 0.0 | 0.01 -Output | 0.00055782 | 0.00055782 | 0.00055782 | 0.0 | 0.01 -Modify | 1.6547 | 1.6547 | 1.6547 | 0.0 | 38.56 -Other | | 0.002613 | | | 0.06 +Pair | 1.5595 | 1.5595 | 1.5595 | 0.0 | 58.65 +Neigh | 0.012904 | 0.012904 | 0.012904 | 0.0 | 0.49 +Comm | 0.00041333 | 0.00041333 | 0.00041333 | 0.0 | 0.02 +Output | 0.00053486 | 0.00053486 | 0.00053486 | 0.0 | 0.02 +Modify | 1.0844 | 1.0844 | 1.0844 | 0.0 | 40.78 +Other | | 0.001336 | | | 0.05 Nlocal: 200 ave 200 max 200 min Histogram: 1 0 0 0 0 0 0 0 0 0 Nghost: 0 ave 0 max 0 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Neighs: 3145 ave 3145 max 3145 min +Neighs: 3026 ave 3026 max 3026 min Histogram: 1 0 0 0 0 0 0 0 0 0 -Total # of neighbors = 3145 -Ave neighs/atom = 15.725 +Total # of neighbors = 3026 +Ave neighs/atom = 15.13 Neighbor list builds = 83 Dangerous builds not checked -Total wall time: 0:00:26 +Total wall time: 0:00:18 diff --git a/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 index eb49f732e8..1992fb2555 100644 --- a/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 +++ b/examples/granular/log.4Feb25.triaxial.compaction.12.g++.1 @@ -1,4 +1,4 @@ -LAMMPS (4 Feb 2025 - Development - patch_4Feb2025-583-g3d4b57d7fd-modified) +LAMMPS (4 Feb 2025 - Development - patch_5May2020-22356-g0c29a0a0c9-modified) ############################### SIMULATION SETTINGS ################################################### atom_style sphere 1 @@ -19,7 +19,7 @@ Reading data file ... 1 by 1 by 1 MPI processor grid reading atoms ... 12 atoms - read_data CPU = 0.003 seconds + read_data CPU = 0.029 seconds fix integr all nve/sphere # create pair group for contact area outputs @@ -38,7 +38,8 @@ variable PoissonsRatio equal 0.3 variable YieldStress equal 50e6 variable SurfaceEnergy equal 0.0 variable psi_b equal 0.5 -variable damp equal 1.0 +variable damp equal 0.2 +variable damp_type equal 1 # linear_history = k_t, x_gamma,t, mu_s variable kt equal 2/7*${YoungsModulus}*${atomRadius} @@ -47,16 +48,17 @@ variable kt equal 2/7*1000000000*0.5 variable xgammat equal 0.0 variable mu_s equal 0.5 -pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 ${xgammat} ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 ${mu_s} -pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 +pair_coeff * * mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history ${kt} ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 ${xgammat} ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 ${mu_s} +pair_coeff * * mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 ######################################### ADD IN PLANES ################################################ @@ -80,29 +82,30 @@ region plane_xy_pos plane 0 0 1.5 0 0 -1 side in move NULL NULL v_plane_disp_ne region plane_xy_neg plane 0 0 -${halfBoxWidth} 0 0 1 side in move NULL NULL v_plane_disp units box region plane_xy_neg plane 0 0 -1.5 0 0 1 side in move NULL NULL v_plane_disp units box -variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} " -granular mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history ${kt} ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 ${xgammat} ${mu_s} -granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 ${mu_s} -granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 +variable wall_contact_string string "granular mdr ${YoungsModulus} ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} " +granular mdr 1000000000 ${PoissonsRatio} ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 ${YieldStress} ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 ${SurfaceEnergy} ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 ${psi_b} ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 ${damp} damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr ${damp_type} tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history ${kt} ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 ${xgammat} ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 ${mu_s} +granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 fix plane_yz_pos all wall/gran/region ${wall_contact_string} region plane_yz_pos contacts -fix plane_yz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_yz_pos contacts +fix plane_yz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_yz_pos contacts fix plane_yz_neg all wall/gran/region ${wall_contact_string} region plane_yz_neg contacts -fix plane_yz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_yz_neg contacts +fix plane_yz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_yz_neg contacts fix plane_xz_pos all wall/gran/region ${wall_contact_string} region plane_xz_pos contacts -fix plane_xz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xz_pos contacts +fix plane_xz_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xz_pos contacts fix plane_xz_neg all wall/gran/region ${wall_contact_string} region plane_xz_neg contacts -fix plane_xz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xz_neg contacts +fix plane_xz_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xz_neg contacts fix plane_xy_pos all wall/gran/region ${wall_contact_string} region plane_xy_pos contacts -fix plane_xy_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xy_pos contacts +fix plane_xy_pos all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xy_pos contacts fix plane_xy_neg all wall/gran/region ${wall_contact_string} region plane_xy_neg contacts -fix plane_xy_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 1 damping mdr tangential linear_history 142857142.857143 0 0.5 region plane_xy_neg contacts +fix plane_xy_neg all wall/gran/region granular mdr 1000000000 0.3 50000000 0 0.5 0.2 damping mdr 1 tangential linear_history 142857142.857143 0 0.5 region plane_xy_neg contacts compute plane_xy_neg_force all reduce sum f_plane_xy_neg[4] variable plane_xy_neg_force equal c_plane_xy_neg_force @@ -171,8 +174,9 @@ Your simulation uses code contributions which should be cited: author = {Zunker, William and Dunatunga, Sachith and Thakur, Subhash and Tang, Pingjun and Kamrin, Ken}, title = {Experimentally validated DEM for large deformation powder compaction: mechanically-derived contact model and screening of non-physical contacts}, + journal = {Powder Technology}, year = {2025}, - journal = {engrXiv}, + pages = {120972}, } CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE-CITE @@ -193,7 +197,7 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 74.54 | 74.54 | 74.54 Mbytes Dt Step Atoms KinEng c_1 Volume 1e-06 0 12 0 0 8000 -Loop time of 8.47e-07 on 1 procs for 0 steps with 12 atoms +Loop time of 8.28e-07 on 1 procs for 0 steps with 12 atoms 0.0% CPU use with 1 MPI tasks x no OpenMP threads @@ -205,7 +209,7 @@ Neigh | 0 | 0 | 0 | 0.0 | 0.00 Comm | 0 | 0 | 0 | 0.0 | 0.00 Output | 0 | 0 | 0 | 0.0 | 0.00 Modify | 0 | 0 | 0 | 0.0 | 0.00 -Other | | 8.47e-07 | | |100.00 +Other | | 8.28e-07 | | |100.00 Nlocal: 12 ave 12 max 12 min Histogram: 1 0 0 0 0 0 0 0 0 0 @@ -253,518 +257,518 @@ Neighbor list info ... Per MPI rank memory allocation (min/avg/max) = 75.17 | 75.17 | 75.17 Mbytes Dt Step Atoms KinEng c_1 Volume 1e-06 0 12 0 0 8000 - 1e-06 100 12 0.37627896 0 8000 - 1e-06 200 12 4.1791248 0 8000 - 1e-06 300 12 14.842751 0 8000 - 1e-06 400 12 36.772259 0 8000 - 1e-06 500 12 77.630616 0 8000 - 1e-06 600 12 145.73848 0 8000 - 1e-06 700 12 250.50491 0 8000 - 1e-06 800 12 402.70153 0 8000 - 1e-06 900 12 614.51551 0 8000 - 1e-06 1000 12 899.53232 0 8000 - 1e-06 1100 12 1272.6697 0 8000 - 1e-06 1200 12 1750.0701 0 8000 - 1e-06 1300 12 2348.9536 0 8000 - 1e-06 1400 12 3087.4362 0 8000 - 1e-06 1500 12 3984.3134 0 8000 - 1e-06 1600 12 5058.8155 0 8000 - 1e-06 1700 12 6330.3362 0 8000 - 1e-06 1800 12 7818.1411 0 8000 - 1e-06 1900 12 9541.0592 0 8000 - 1e-06 2000 12 11498.791 0.0047810266 8000 - 1e-06 2100 12 13704.573 0.10811492 8000 - 1e-06 2200 12 16174.974 0.63000368 8000 - 1e-06 2300 12 18921.112 2.1626376 8000 - 1e-06 2400 12 21953.925 5.2698517 8000 - 1e-06 2500 12 25281.497 10.484444 8000 - 1e-06 2600 12 28908.645 18.482248 8000 - 1e-06 2700 12 32837.664 30.036339 8000 - 1e-06 2800 12 37068.237 46.017479 8000 - 1e-06 2900 12 41597.382 67.391786 8000 - 1e-06 3000 12 46419.434 95.215596 8000 - 1e-06 3100 12 51526.06 130.62752 8000 - 1e-06 3200 12 56906.565 174.8377 8000 - 1e-06 3300 12 62550.059 229.11444 8000 - 1e-06 3400 12 68444.395 294.66357 8000 - 1e-06 3500 12 74576.632 372.08886 8000 - 1e-06 3600 12 80933.178 461.43595 8000 - 1e-06 3700 12 87499.829 562.23674 8000 - 1e-06 3800 12 94261.901 673.47838 8000 - 1e-06 3900 12 101204.31 793.60705 8000 - 1e-06 4000 12 108311.58 920.56829 8000 - 1e-06 4100 12 115567.86 1051.8828 8000 - 1e-06 4200 12 122956.81 1184.754 8000 - 1e-06 4300 12 130461.5 1316.2004 8000 - 1e-06 4400 12 138064.33 1443.2052 8000 - 1e-06 4500 12 145746.82 1562.8719 8000 - 1e-06 4600 12 153422.95 1670.3394 8000 - 1e-06 4700 12 161051.84 1763.0999 8000 - 1e-06 4800 12 168667.52 1842.4996 8000 - 1e-06 4900 12 176255.36 1908.409 8000 - 1e-06 5000 12 183795.82 1961.1714 8000 - 1e-06 5100 12 191266.94 2001.7002 8000 - 1e-06 5200 12 198645 2031.4642 8000 - 1e-06 5300 12 205905.03 2052.4189 8000 - 1e-06 5400 12 213021.06 2066.906 8000 - 1e-06 5500 12 219828.33 2076.3201 8000 - 1e-06 5600 12 226088.26 2080.385 8000 - 1e-06 5700 12 231986.18 2088.93 8000 - 1e-06 5800 12 237570.94 2108.0119 8000 - 1e-06 5900 12 242837.17 2141.5471 8000 - 1e-06 6000 12 247775.44 2192.6781 8000 - 1e-06 6100 12 252375.51 2263.7885 8000 - 1e-06 6200 12 256627.89 2356.5013 8000 - 1e-06 6300 12 260524.71 2471.6922 8000 - 1e-06 6400 12 264060.29 2609.528 8000 - 1e-06 6500 12 267231.53 2769.5274 8000 - 1e-06 6600 12 270038.2 2950.6395 8000 - 1e-06 6700 12 272483.11 3151.335 8000 - 1e-06 6800 12 274572.24 3369.7006 8000 - 1e-06 6900 12 276314.75 3603.531 8000 - 1e-06 7000 12 277722.99 3850.4128 8000 - 1e-06 7100 12 278812.52 4107.7948 8000 - 1e-06 7200 12 279602.05 4373.0439 8000 - 1e-06 7300 12 280113.55 4643.4856 8000 - 1e-06 7400 12 280372.7 4916.43 8000 - 1e-06 7500 12 280411.71 5189.1887 8000 - 1e-06 7600 12 280270.18 5459.0844 8000 - 1e-06 7700 12 279999.69 5723.4596 8000 - 1e-06 7800 12 279696.94 5979.6896 8000 - 1e-06 7900 12 279705.93 6225.2029 8000 - 1e-06 8000 12 279677 6457.5689 8000 - 1e-06 8100 12 279607.39 6683.3974 8000 - 1e-06 8200 12 279535.86 6906.911 8000 - 1e-06 8300 12 279515.96 7125.9155 8000 - 1e-06 8400 12 279726.3 7338.4626 8000 - 1e-06 8500 12 279905.61 7528.2253 8000 - 1e-06 8600 12 279994.55 7695.3391 8000 - 1e-06 8700 12 280109.97 7846.4954 8000 - 1e-06 8800 12 280280.9 7992.1243 8000 - 1e-06 8900 12 280526.73 8146.1487 8000 - 1e-06 9000 12 280875.16 8309.0778 8000 - 1e-06 9100 12 281361.17 8473.1301 8000 - 1e-06 9200 12 282015.74 8638.5101 8000 - 1e-06 9300 12 282868.61 8807.2007 8000 - 1e-06 9400 12 283949.43 8980.8606 8000 - 1e-06 9500 12 285287.01 9160.6973 8000 - 1e-06 9600 12 286908.48 9347.3851 8000 - 1e-06 9700 12 288808.95 9540.3891 8000 - 1e-06 9800 12 291008.88 9739.3515 8000 - 1e-06 9900 12 293533.31 9944.1548 8000 - 1e-06 10000 12 296392.46 10153.993 8000 - 1e-06 10100 12 299589.23 10366.149 8000 - 1e-06 10200 12 303120.5 10580.26 8000 - 1e-06 10300 12 306976.5 10797.104 8000 - 1e-06 10400 12 311140.59 11018.1 8000 - 1e-06 10500 12 315589.46 11245.316 8000 - 1e-06 10600 12 320293.56 11481.375 8000 - 1e-06 10700 12 325217.67 11729.284 8000 - 1e-06 10800 12 330321.65 11992.189 8000 - 1e-06 10900 12 335561.34 12273.086 8000 - 1e-06 11000 12 340889.49 12574.505 8000 - 1e-06 11100 12 346256.88 12898.214 8000 - 1e-06 11200 12 351613.36 13244.969 8000 - 1e-06 11300 12 356921.74 13613.584 8000 - 1e-06 11400 12 362263.57 14000.802 8000 - 1e-06 11500 12 367685.46 14407.905 8000 - 1e-06 11600 12 373173.46 14833.769 8000 - 1e-06 11700 12 378713.19 15276.703 8000 - 1e-06 11800 12 384258.42 15728.278 8000 - 1e-06 11900 12 389798.27 16183.88 8000 - 1e-06 12000 12 395067.85 16636.846 8000 - 1e-06 12100 12 400198.63 17088.171 8000 - 1e-06 12200 12 405211.55 17537.364 8000 - 1e-06 12300 12 410112.47 17984.343 8000 - 1e-06 12400 12 414906.33 18429.831 8000 - 1e-06 12500 12 419598.71 18875.613 8000 - 1e-06 12600 12 424192.44 19324.904 8000 - 1e-06 12700 12 428565.91 19783.784 8000 - 1e-06 12800 12 432825.92 20255.392 8000 - 1e-06 12900 12 437005.65 20738.975 8000 - 1e-06 13000 12 441133.84 21226.416 8000 - 1e-06 13100 12 445218.44 21720.281 8000 - 1e-06 13200 12 449263.02 22225.116 8000 - 1e-06 13300 12 453268.59 22746.27 8000 - 1e-06 13400 12 457229.62 23288.917 8000 - 1e-06 13500 12 461141.35 23859.236 8000 - 1e-06 13600 12 464999.54 24464.127 8000 - 1e-06 13700 12 468798.7 25110.47 8000 - 1e-06 13800 12 472500.62 25806.135 8000 - 1e-06 13900 12 476074.74 26564.004 8000 - 1e-06 14000 12 479545.35 27389.059 8000 - 1e-06 14100 12 482914.85 28284.54 8000 - 1e-06 14200 12 486185.47 29252.687 8000 - 1e-06 14300 12 489361.15 30294.757 8000 - 1e-06 14400 12 492273.69 31409.091 8000 - 1e-06 14500 12 494514.18 32573.659 8000 - 1e-06 14600 12 496511.76 33785.467 8000 - 1e-06 14700 12 498362.32 35051.794 8000 - 1e-06 14800 12 500126.95 36382.324 8000 - 1e-06 14900 12 501872.73 37788.434 8000 - 1e-06 15000 12 503658.95 39269.921 8000 - 1e-06 15100 12 505524.32 40815.737 8000 - 1e-06 15200 12 507507.74 42410.397 8000 - 1e-06 15300 12 509052.44 44020.642 8000 - 1e-06 15400 12 510424.85 45607.21 8000 - 1e-06 15500 12 511477.14 47150.907 8000 - 1e-06 15600 12 511930.85 48638.383 8000 - 1e-06 15700 12 512124.38 50030.203 8000 - 1e-06 15800 12 512194.05 51293.423 8000 - 1e-06 15900 12 512175.22 52402.955 8000 - 1e-06 16000 12 512095.42 53340.637 8000 - 1e-06 16100 12 511970.22 54097.278 8000 - 1e-06 16200 12 511797.58 54671.217 8000 - 1e-06 16300 12 511596.19 55067.665 8000 - 1e-06 16400 12 511390.31 55298.281 8000 - 1e-06 16500 12 511203.2 55383.204 8000 - 1e-06 16600 12 511056.43 55352.575 8000 - 1e-06 16700 12 510973.55 55240.989 8000 - 1e-06 16800 12 510979.82 55085.771 8000 - 1e-06 16900 12 511018.94 54944.912 8000 - 1e-06 17000 12 510839.23 54871.084 8000 - 1e-06 17100 12 510670.95 54882.14 8000 - 1e-06 17200 12 510592.26 55012.23 8000 - 1e-06 17300 12 510473.65 55293.657 8000 - 1e-06 17400 12 509821.33 55718.974 8000 - 1e-06 17500 12 508425.2 56251.107 8000 - 1e-06 17600 12 506922.69 56913.254 8000 - 1e-06 17700 12 505432.36 57751.093 8000 - 1e-06 17800 12 504007.07 58820.863 8000 - 1e-06 17900 12 502565.91 60215.42 8000 - 1e-06 18000 12 501138.89 61987.521 8000 - 1e-06 18100 12 499028.8 64137.707 8000 - 1e-06 18200 12 493241.81 66656.007 8000 - 1e-06 18300 12 486709.22 69522.002 8000 - 1e-06 18400 12 480004.21 72703.075 8000 - 1e-06 18500 12 473373.17 76162.035 8000 - 1e-06 18600 12 466967.02 79858.627 8000 - 1e-06 18700 12 460896.76 83749.858 8000 - 1e-06 18800 12 455246.73 87789.78 8000 - 1e-06 18900 12 450058.54 91935.918 8000 - 1e-06 19000 12 445381.99 96175.252 8000 - 1e-06 19100 12 441278.15 100523.08 8000 - 1e-06 19200 12 437763.14 104946.19 8000 - 1e-06 19300 12 434836.79 109405.67 8000 - 1e-06 19400 12 432488.77 113863.34 8000 - 1e-06 19500 12 430699.83 118281.43 8000 - 1e-06 19600 12 429442.98 122622.26 8000 - 1e-06 19700 12 428684.66 126847.95 8000 - 1e-06 19800 12 428328.48 130917.63 8000 - 1e-06 19900 12 428196.55 134775.59 8000 - 1e-06 20000 12 427597.88 138354.14 8000 - 1e-06 20100 12 425748.44 141440.79 8000 - 1e-06 20200 12 423827.82 143975.56 8000 - 1e-06 20300 12 422029.53 145951.68 8000 - 1e-06 20400 12 420416.81 147364.79 8000 - 1e-06 20500 12 419027.95 148273.8 8000 - 1e-06 20600 12 417858.85 148716.68 8000 - 1e-06 20700 12 416878.1 148666.56 8000 - 1e-06 20800 12 416057.47 148096.03 8000 - 1e-06 20900 12 415366.73 146981.92 8000 - 1e-06 21000 12 414775.28 145311.94 8000 - 1e-06 21100 12 414254.77 143086.56 8000 - 1e-06 21200 12 413734.06 140320.07 8000 - 1e-06 21300 12 412373.7 137040.42 8000 - 1e-06 21400 12 410695.21 133289.46 8000 - 1e-06 21500 12 408430.75 129131.69 8000 - 1e-06 21600 12 405927.7 124609.43 8000 - 1e-06 21700 12 403251.27 119786.82 8000 - 1e-06 21800 12 400435.71 114740.64 8000 - 1e-06 21900 12 397484.88 109586.68 8000 - 1e-06 22000 12 394308.48 104582.2 8000 - 1e-06 22100 12 390933.42 99878.117 8000 - 1e-06 22200 12 387369.16 95602.908 8000 - 1e-06 22300 12 383599.37 91871.749 8000 - 1e-06 22400 12 379598.34 88800.942 8000 - 1e-06 22500 12 375344.08 86475.879 8000 - 1e-06 22600 12 370860.89 84903.263 8000 - 1e-06 22700 12 366151.23 84105.325 8000 - 1e-06 22800 12 361209.31 84104.321 8000 - 1e-06 22900 12 356040.22 84897.625 8000 - 1e-06 23000 12 350662.58 86460.188 8000 - 1e-06 23100 12 345116.82 88752.422 8000 - 1e-06 23200 12 339495.95 91790.621 8000 - 1e-06 23300 12 333687.3 95431.883 8000 - 1e-06 23400 12 327700.18 99552.952 8000 - 1e-06 23500 12 321587.6 104041.28 8000 - 1e-06 23600 12 315413.29 108778.56 8000 - 1e-06 23700 12 309232.19 113641.68 8000 - 1e-06 23800 12 303140 118515.28 8000 - 1e-06 23900 12 297243.14 123286.42 8000 - 1e-06 24000 12 291647.45 127852.5 8000 - 1e-06 24100 12 286443.56 132128.25 8000 - 1e-06 24200 12 281738.47 136042.29 8000 - 1e-06 24300 12 277598.16 139537.18 8000 - 1e-06 24400 12 274126.59 142570.51 8000 - 1e-06 24500 12 271212.37 145112.95 8000 - 1e-06 24600 12 268528.37 147123.47 8000 - 1e-06 24700 12 266518.1 148576.54 8000 - 1e-06 24800 12 265271.22 149482.64 8000 - 1e-06 24900 12 264825.89 149868.7 8000 - 1e-06 25000 12 265195.27 149778.11 8000 - 1e-06 25100 12 266383.27 149277.13 8000 - 1e-06 25200 12 268349.03 148416.99 8000 - 1e-06 25300 12 270306.65 147210.83 8000 - 1e-06 25400 12 272540.67 145679.8 8000 - 1e-06 25500 12 275074.7 143905.2 8000 - 1e-06 25600 12 277868.98 141980.52 8000 - 1e-06 25700 12 280861.82 139998.04 8000 - 1e-06 25800 12 283988.43 138050.21 8000 - 1e-06 25900 12 287187.75 136227 8000 - 1e-06 26000 12 290378.71 134578.07 8000 - 1e-06 26100 12 293523.52 133120.1 8000 - 1e-06 26200 12 296607.69 131949.25 8000 - 1e-06 26300 12 299624.93 131155.87 8000 - 1e-06 26400 12 302615.41 130771.8 8000 - 1e-06 26500 12 305572.83 130791.04 8000 - 1e-06 26600 12 308487.65 131181.94 8000 - 1e-06 26700 12 311349.47 131876.78 8000 - 1e-06 26800 12 314152.42 132778.86 8000 - 1e-06 26900 12 316889.29 133767.68 8000 - 1e-06 27000 12 319555.95 134708.52 8000 - 1e-06 27100 12 322120.91 135461.05 8000 - 1e-06 27200 12 324555.84 135890.05 8000 - 1e-06 27300 12 326829.66 135875.78 8000 - 1e-06 27400 12 328889.23 135312.91 8000 - 1e-06 27500 12 330281.69 133716.24 8000 - 1e-06 27600 12 329638.28 131054.91 8000 - 1e-06 27700 12 328037.36 127321.07 8000 - 1e-06 27800 12 325917.33 122660.17 8000 - 1e-06 27900 12 323405.93 117289.76 8000 - 1e-06 28000 12 320546.78 111541.78 8000 - 1e-06 28100 12 317368.1 105721.12 8000 - 1e-06 28200 12 313916.1 100042.75 8000 - 1e-06 28300 12 310233.7 94704.867 8000 - 1e-06 28400 12 306354.19 89876.573 8000 - 1e-06 28500 12 302311.92 85693.914 8000 - 1e-06 28600 12 298136.83 82229.878 8000 - 1e-06 28700 12 293861.39 79475.257 8000 - 1e-06 28800 12 289522.82 77321.299 8000 - 1e-06 28900 12 285166.39 75606.038 8000 - 1e-06 29000 12 280832.9 74150.094 8000 - 1e-06 29100 12 276597.93 72751.053 8000 - 1e-06 29200 12 272488.85 71238.957 8000 - 1e-06 29300 12 268566.35 69513.495 8000 - 1e-06 29400 12 264945.51 67531.391 8000 - 1e-06 29500 12 261654.36 65280.325 8000 - 1e-06 29600 12 258609.63 62770.995 8000 - 1e-06 29700 12 255839.5 60094.223 8000 - 1e-06 29800 12 253400.35 57359.541 8000 - 1e-06 29900 12 251293.26 54686.718 8000 - 1e-06 30000 12 249489.3 52206.293 8000 - 1e-06 30100 12 247933.05 50046.862 8000 - 1e-06 30200 12 246671.31 48361.721 8000 - 1e-06 30300 12 245727.43 47234.492 8000 - 1e-06 30400 12 245089.53 46668.443 8000 - 1e-06 30500 12 244732.88 46634.46 8000 - 1e-06 30600 12 244634.04 47078.65 8000 - 1e-06 30700 12 244776.41 47932.487 8000 - 1e-06 30800 12 245144.95 49123.892 8000 - 1e-06 30900 12 245702.52 50587.15 8000 - 1e-06 31000 12 246438.58 52268.799 8000 - 1e-06 31100 12 247320.85 54174.572 8000 - 1e-06 31200 12 248299.92 56314.047 8000 - 1e-06 31300 12 249329.77 58655.775 8000 - 1e-06 31400 12 250368.76 61154.112 8000 - 1e-06 31500 12 251379.78 63756.764 8000 - 1e-06 31600 12 252311.71 66409.538 8000 - 1e-06 31700 12 252527.59 69055.013 8000 - 1e-06 31800 12 252438.03 71645.91 8000 - 1e-06 31900 12 252149.26 74149.007 8000 - 1e-06 32000 12 251697.31 76539.619 8000 - 1e-06 32100 12 251102.37 78801.8 8000 - 1e-06 32200 12 250377.5 80923.81 8000 - 1e-06 32300 12 249388.7 82875.3 8000 - 1e-06 32400 12 248054.75 84570.827 8000 - 1e-06 32500 12 246510.48 85977.951 8000 - 1e-06 32600 12 244788.85 87069.778 8000 - 1e-06 32700 12 242926.09 87820.435 8000 - 1e-06 32800 12 240951.82 88208.457 8000 - 1e-06 32900 12 238923.34 88216.633 8000 - 1e-06 33000 12 236972.84 87811.784 8000 - 1e-06 33100 12 235176.94 86991.249 8000 - 1e-06 33200 12 233594.14 85783.149 8000 - 1e-06 33300 12 232256.48 84231.2 8000 - 1e-06 33400 12 231063.68 82397.369 8000 - 1e-06 33500 12 229814.73 80366.279 8000 - 1e-06 33600 12 228715.08 78221.16 8000 - 1e-06 33700 12 227846.27 76046.828 8000 - 1e-06 33800 12 227241.85 73932.693 8000 - 1e-06 33900 12 226942.55 71944.948 8000 - 1e-06 34000 12 226979.34 70148.331 8000 - 1e-06 34100 12 227374.73 68624.913 8000 - 1e-06 34200 12 228140.68 67389 8000 - 1e-06 34300 12 229286.23 66436.221 8000 - 1e-06 34400 12 230818.8 65748.265 8000 - 1e-06 34500 12 232718.67 65274.126 8000 - 1e-06 34600 12 234956.45 64949.901 8000 - 1e-06 34700 12 237495.47 64705.586 8000 - 1e-06 34800 12 240298.79 64471.768 8000 - 1e-06 34900 12 243327.46 64186.278 8000 - 1e-06 35000 12 246540.11 63799.369 8000 - 1e-06 35100 12 249891.89 63272.741 8000 - 1e-06 35200 12 253331.8 62590.115 8000 - 1e-06 35300 12 256810.15 61755.192 8000 - 1e-06 35400 12 260282.81 60790.037 8000 - 1e-06 35500 12 263711.24 59733.295 8000 - 1e-06 35600 12 267063.76 58636.285 8000 - 1e-06 35700 12 270321.08 57558.359 8000 - 1e-06 35800 12 273471.7 56562.046 8000 - 1e-06 35900 12 276025.36 55655.191 8000 - 1e-06 36000 12 277671.27 54780.068 8000 - 1e-06 36100 12 278702.08 54044.977 8000 - 1e-06 36200 12 279135.29 53482.141 8000 - 1e-06 36300 12 278950.85 53096.328 8000 - 1e-06 36400 12 278091.84 52852.785 8000 - 1e-06 36500 12 276595.93 52726.318 8000 - 1e-06 36600 12 274484.66 52702.496 8000 - 1e-06 36700 12 271787.05 52743.065 8000 - 1e-06 36800 12 268570.57 52802.129 8000 - 1e-06 36900 12 264883.91 52837.56 8000 - 1e-06 37000 12 260770.78 52813.294 8000 - 1e-06 37100 12 256294.93 52703.248 8000 - 1e-06 37200 12 251520.81 52496.031 8000 - 1e-06 37300 12 246514.92 52198.643 8000 - 1e-06 37400 12 241336.35 51838.499 8000 - 1e-06 37500 12 236051.19 51466.475 8000 - 1e-06 37600 12 230530.99 51158.037 8000 - 1e-06 37700 12 224831.9 51005.878 8000 - 1e-06 37800 12 219195 51087.112 8000 - 1e-06 37900 12 213774.51 51464.55 8000 - 1e-06 38000 12 208719.8 52178.179 8000 - 1e-06 38100 12 204173.16 53238.452 8000 - 1e-06 38200 12 200268.52 54621.477 8000 - 1e-06 38300 12 197150.81 56266.704 8000 - 1e-06 38400 12 194900.92 58092.885 8000 - 1e-06 38500 12 193569.8 59999.47 8000 - 1e-06 38600 12 193173.44 61875.452 8000 - 1e-06 38700 12 193689.15 63611.808 8000 - 1e-06 38800 12 195056.93 65114.049 8000 - 1e-06 38900 12 197179.13 66310.945 8000 - 1e-06 39000 12 199964.06 67173.129 8000 - 1e-06 39100 12 203313.78 67704.561 8000 - 1e-06 39200 12 206537.34 67923.159 8000 - 1e-06 39300 12 209698.91 67870.023 8000 - 1e-06 39400 12 212990.74 67598.734 8000 - 1e-06 39500 12 216350.18 67172.426 8000 - 1e-06 39600 12 219678.83 66655.657 8000 - 1e-06 39700 12 222844.21 66084.261 8000 - 1e-06 39800 12 225879.54 65489.967 8000 - 1e-06 39900 12 228750 64901.658 8000 - 1e-06 40000 12 231432.52 64333.74 8000 - 1e-06 40100 12 233916.24 63787.895 8000 - 1e-06 40200 12 236200.24 63256.3 8000 - 1e-06 40300 12 238290.68 62725.161 8000 - 1e-06 40400 12 240198.17 62177.851 8000 - 1e-06 40500 12 241937.05 61597.51 8000 - 1e-06 40600 12 243521.73 60967.618 8000 - 1e-06 40700 12 244888.47 60271.31 8000 - 1e-06 40800 12 245447.64 59435.777 8000 - 1e-06 40900 12 245685.9 58426.609 8000 - 1e-06 41000 12 245713.15 57255.612 8000 - 1e-06 41100 12 245574.53 55939.057 8000 - 1e-06 41200 12 245295.74 54497.409 8000 - 1e-06 41300 12 244893.38 52955.91 8000 - 1e-06 41400 12 244382.52 51349.735 8000 - 1e-06 41500 12 243831.69 49814.42 8000 - 1e-06 41600 12 243254.37 48400.984 8000 - 1e-06 41700 12 242477.85 47069.283 8000 - 1e-06 41800 12 241513.72 45827.072 8000 - 1e-06 41900 12 239756.07 44524.57 8000 - 1e-06 42000 12 237373.8 43055.987 8000 - 1e-06 42100 12 234744.81 41643.015 8000 - 1e-06 42200 12 231931.52 40312.339 8000 - 1e-06 42300 12 228935.92 39072.939 8000 - 1e-06 42400 12 225746.23 37930.778 8000 - 1e-06 42500 12 222348.89 36895.022 8000 - 1e-06 42600 12 218698.5 35981.801 8000 - 1e-06 42700 12 214647.12 35216.043 8000 - 1e-06 42800 12 210245.47 34620.785 8000 - 1e-06 42900 12 205531.71 34205.699 8000 - 1e-06 43000 12 200578.63 33994.95 8000 - 1e-06 43100 12 195456.13 33986.177 8000 - 1e-06 43200 12 190228.82 34157.583 8000 - 1e-06 43300 12 184952.07 34469.117 8000 - 1e-06 43400 12 179670.45 34866.761 8000 - 1e-06 43500 12 174418.49 35289.81 8000 - 1e-06 43600 12 169223.1 35679.916 8000 - 1e-06 43700 12 164106.46 35990.914 8000 - 1e-06 43800 12 159087.52 36198.071 8000 - 1e-06 43900 12 154186.33 36296.826 8000 - 1e-06 44000 12 149426.96 36300.354 8000 - 1e-06 44100 12 144835.14 36235.093 8000 - 1e-06 44200 12 140411 36133.354 8000 - 1e-06 44300 12 136182.81 36025.46 8000 - 1e-06 44400 12 132191.02 35932.385 8000 - 1e-06 44500 12 128477.69 35860.362 8000 - 1e-06 44600 12 125084.47 35799.083 8000 - 1e-06 44700 12 122052.38 35722.674 8000 - 1e-06 44800 12 119423.36 35591.653 8000 - 1e-06 44900 12 117231.38 35361.568 8000 - 1e-06 45000 12 115498.71 34993.601 8000 - 1e-06 45100 12 114234.68 34464.293 8000 - 1e-06 45200 12 113435.12 33772.471 8000 - 1e-06 45300 12 113082.91 32941.872 8000 - 1e-06 45400 12 113268.89 32017.499 8000 - 1e-06 45500 12 114094.16 31061.868 8000 - 1e-06 45600 12 115590.36 30141.335 8000 - 1e-06 45700 12 117815.57 29316.931 8000 - 1e-06 45800 12 120811.47 28631.895 8000 - 1e-06 45900 12 124575.14 28113.464 8000 - 1e-06 46000 12 129078.74 27763.791 8000 - 1e-06 46100 12 134338.42 27558.943 8000 - 1e-06 46200 12 140371.84 27456.007 8000 - 1e-06 46300 12 147179.46 27401.261 8000 - 1e-06 46400 12 154720.12 27350.633 8000 - 1e-06 46500 12 162903.78 27280.725 8000 - 1e-06 46600 12 171569.61 27160.074 8000 - 1e-06 46700 12 180503.28 26959.29 8000 - 1e-06 46800 12 189437.05 26679.422 8000 - 1e-06 46900 12 198196.23 26336.443 8000 - 1e-06 47000 12 206520.98 25964.312 8000 - 1e-06 47100 12 214102.44 25606.132 8000 - 1e-06 47200 12 220554.38 25312.112 8000 - 1e-06 47300 12 225530.25 25128.211 8000 - 1e-06 47400 12 228814.64 25087.25 8000 - 1e-06 47500 12 230374.48 25204.456 8000 - 1e-06 47600 12 230169.61 25476.535 8000 - 1e-06 47700 12 228279.91 25884.284 8000 - 1e-06 47800 12 224903.35 26398.057 8000 - 1e-06 47900 12 220331.08 26984.898 8000 - 1e-06 48000 12 214896.98 27615.915 8000 - 1e-06 48100 12 208954.59 28272.416 8000 - 1e-06 48200 12 202876.52 28949.711 8000 - 1e-06 48300 12 197002.89 29657.821 8000 - 1e-06 48400 12 191715.64 30417.951 8000 - 1e-06 48500 12 187427.74 31259.165 8000 - 1e-06 48600 12 184340.37 32206.982 8000 - 1e-06 48700 12 182293.26 33278.236 8000 - 1e-06 48800 12 181185.81 34481.276 8000 - 1e-06 48900 12 181101.89 35801.056 8000 - 1e-06 49000 12 182147.18 37201.316 8000 - 1e-06 49100 12 184365.23 38617.38 8000 - 1e-06 49200 12 187357.35 39915.206 8000 - 1e-06 49300 12 190910.82 40926.844 8000 - 1e-06 49400 12 195007.02 41662.043 8000 - 1e-06 49500 12 199572.66 42126.903 8000 - 1e-06 49600 12 204382.72 42280.987 8000 - 1e-06 49700 12 209699.49 42088.752 8000 - 1e-06 49800 12 215597.68 41583.342 8000 - 1e-06 49900 12 222033.85 40867.693 8000 -Loop time of 1.45978 on 1 procs for 49900 steps with 12 atoms + 1e-06 100 12 0.063728867 0 8000 + 1e-06 200 12 0.79328888 0 8000 + 1e-06 300 12 3.1671095 0 8000 + 1e-06 400 12 8.7248683 0 8000 + 1e-06 500 12 20.158012 0 8000 + 1e-06 600 12 41.157061 0 8000 + 1e-06 700 12 76.628872 0 8000 + 1e-06 800 12 132.88829 0 8000 + 1e-06 900 12 217.80403 0 8000 + 1e-06 1000 12 340.91325 0 8000 + 1e-06 1100 12 513.50254 0 8000 + 1e-06 1200 12 748.65202 0 8000 + 1e-06 1300 12 1061.2394 0 8000 + 1e-06 1400 12 1467.9017 0 8000 + 1e-06 1500 12 1986.9524 0 8000 + 1e-06 1600 12 2638.2542 0 8000 + 1e-06 1700 12 3443.0464 0 8000 + 1e-06 1800 12 4423.728 0 8000 + 1e-06 1900 12 5603.6004 0 8000 + 1e-06 2000 12 7006.5697 0 8000 + 1e-06 2100 12 8656.8153 0 8000 + 1e-06 2200 12 10575.061 0.00041930161 8000 + 1e-06 2300 12 12776.34 0.031472922 8000 + 1e-06 2400 12 15285.834 0.16547279 8000 + 1e-06 2500 12 18123.472 0.48824818 8000 + 1e-06 2600 12 21306.73 1.1172148 8000 + 1e-06 2700 12 24850.635 2.2101203 8000 + 1e-06 2800 12 28767.448 3.9742876 8000 + 1e-06 2900 12 33066.341 6.6765245 8000 + 1e-06 3000 12 37753.104 10.653677 8000 + 1e-06 3100 12 42829.905 16.323673 8000 + 1e-06 3200 12 48295.143 24.196804 8000 + 1e-06 3300 12 54143.784 34.886968 8000 + 1e-06 3400 12 60367.427 49.122473 8000 + 1e-06 3500 12 66954.459 67.756017 8000 + 1e-06 3600 12 73890.367 91.773371 8000 + 1e-06 3700 12 81158.051 122.30029 8000 + 1e-06 3800 12 88738.15 160.60714 8000 + 1e-06 3900 12 96609.374 208.11075 8000 + 1e-06 4000 12 104748.82 266.37305 8000 + 1e-06 4100 12 113132.27 337.09603 8000 + 1e-06 4200 12 121734.46 422.11267 8000 + 1e-06 4300 12 130529.26 523.37361 8000 + 1e-06 4400 12 139489.96 642.8869 8000 + 1e-06 4500 12 148590.48 781.76659 8000 + 1e-06 4600 12 157805.54 939.73777 8000 + 1e-06 4700 12 167102.78 1115.3765 8000 + 1e-06 4800 12 176408.3 1304.8823 8000 + 1e-06 4900 12 185727.22 1506.1791 8000 + 1e-06 5000 12 195037.08 1715.5141 8000 + 1e-06 5100 12 204311.37 1928.3496 8000 + 1e-06 5200 12 213522.05 2139.6607 8000 + 1e-06 5300 12 222640.01 2344.2078 8000 + 1e-06 5400 12 231635.3 2536.8271 8000 + 1e-06 5500 12 240477.26 2712.7272 8000 + 1e-06 5600 12 249036.18 2865.4067 8000 + 1e-06 5700 12 257225.21 2990.2307 8000 + 1e-06 5800 12 265107.22 3088.4777 8000 + 1e-06 5900 12 272662.78 3160.202 8000 + 1e-06 6000 12 279867.43 3206.6334 8000 + 1e-06 6100 12 286696.38 3230.2607 8000 + 1e-06 6200 12 293126.06 3234.7442 8000 + 1e-06 6300 12 299135.09 3224.7366 8000 + 1e-06 6400 12 304704.84 3205.6378 8000 + 1e-06 6500 12 309820.07 3183.3082 8000 + 1e-06 6600 12 314469.34 3163.76 8000 + 1e-06 6700 12 318645.43 3152.8517 8000 + 1e-06 6800 12 322345.74 3156.004 8000 + 1e-06 6900 12 325572.61 3177.9574 8000 + 1e-06 7000 12 328333.69 3222.5849 8000 + 1e-06 7100 12 330642.36 3292.7692 8000 + 1e-06 7200 12 332518.34 3390.3494 8000 + 1e-06 7300 12 333988.86 3516.133 8000 + 1e-06 7400 12 335091.17 3669.9688 8000 + 1e-06 7500 12 335881.45 3850.8676 8000 + 1e-06 7600 12 336541.99 4057.1561 8000 + 1e-06 7700 12 337100.25 4286.6487 8000 + 1e-06 7800 12 337436.07 4536.819 8000 + 1e-06 7900 12 337576.23 4804.9572 8000 + 1e-06 8000 12 337553.74 5088.3001 8000 + 1e-06 8100 12 337412.69 5384.125 8000 + 1e-06 8200 12 337266.12 5689.8034 8000 + 1e-06 8300 12 337141.16 6002.815 8000 + 1e-06 8400 12 336990.23 6320.7444 8000 + 1e-06 8500 12 336832.35 6645.3584 8000 + 1e-06 8600 12 336684.67 6980.6347 8000 + 1e-06 8700 12 336479.86 7317.4769 8000 + 1e-06 8800 12 336286.29 7653.1265 8000 + 1e-06 8900 12 336134.3 7982.859 8000 + 1e-06 9000 12 336043.31 8307.1796 8000 + 1e-06 9100 12 336035 8626.669 8000 + 1e-06 9200 12 336134.55 8942.2162 8000 + 1e-06 9300 12 336370.73 9254.9724 8000 + 1e-06 9400 12 336775.97 9566.1537 8000 + 1e-06 9500 12 337386.26 9876.5005 8000 + 1e-06 9600 12 338238.87 10185.038 8000 + 1e-06 9700 12 339373.93 10490.42 8000 + 1e-06 9800 12 340832.84 10792.816 8000 + 1e-06 9900 12 342649.99 11091.69 8000 + 1e-06 10000 12 344857.32 11386.232 8000 + 1e-06 10100 12 347498.52 11676.525 8000 + 1e-06 10200 12 350625.53 11966.038 8000 + 1e-06 10300 12 354228.27 12250.382 8000 + 1e-06 10400 12 358314.64 12529.915 8000 + 1e-06 10500 12 362887.71 12806.586 8000 + 1e-06 10600 12 367944.26 13083.935 8000 + 1e-06 10700 12 373508.47 13375.901 8000 + 1e-06 10800 12 379544.75 13682.748 8000 + 1e-06 10900 12 385955.58 13992.431 8000 + 1e-06 11000 12 392687 14307.793 8000 + 1e-06 11100 12 399676.01 14631.631 8000 + 1e-06 11200 12 406851.99 14966.316 8000 + 1e-06 11300 12 414139.37 15312.299 8000 + 1e-06 11400 12 421458.35 15668.76 8000 + 1e-06 11500 12 428725.85 16034.567 8000 + 1e-06 11600 12 435860.63 16408.01 8000 + 1e-06 11700 12 442914.03 16784.22 8000 + 1e-06 11800 12 449956.98 17165.7 8000 + 1e-06 11900 12 456943.52 17548.894 8000 + 1e-06 12000 12 463832.6 17927.761 8000 + 1e-06 12100 12 470563.99 18302.718 8000 + 1e-06 12200 12 477048.89 18678.218 8000 + 1e-06 12300 12 483212.97 19059.367 8000 + 1e-06 12400 12 489085.23 19458.596 8000 + 1e-06 12500 12 494661.19 19885.306 8000 + 1e-06 12600 12 499940 20344.66 8000 + 1e-06 12700 12 504927.83 20838.53 8000 + 1e-06 12800 12 509641.24 21366.554 8000 + 1e-06 12900 12 514117.28 21934.019 8000 + 1e-06 13000 12 518378.2 22538.416 8000 + 1e-06 13100 12 522458.77 23167.62 8000 + 1e-06 13200 12 525853.3 23780.032 8000 + 1e-06 13300 12 528815.22 24345.078 8000 + 1e-06 13400 12 531513.34 24883.702 8000 + 1e-06 13500 12 534014.75 25400.482 8000 + 1e-06 13600 12 536357.43 25891.923 8000 + 1e-06 13700 12 538572.95 26355.972 8000 + 1e-06 13800 12 540657.99 26795.836 8000 + 1e-06 13900 12 542612.1 27223.435 8000 + 1e-06 14000 12 544466.84 27647.413 8000 + 1e-06 14100 12 546241.59 28080.229 8000 + 1e-06 14200 12 547953.9 28538.741 8000 + 1e-06 14300 12 549620.46 29043.928 8000 + 1e-06 14400 12 551260.1 29617.65 8000 + 1e-06 14500 12 552886.91 30280.697 8000 + 1e-06 14600 12 554517.93 31050.292 8000 + 1e-06 14700 12 556175.17 31938.659 8000 + 1e-06 14800 12 557897.11 32951.814 8000 + 1e-06 14900 12 559696.65 34092.387 8000 + 1e-06 15000 12 561564.33 35360.561 8000 + 1e-06 15100 12 563512.54 36749.828 8000 + 1e-06 15200 12 565557.63 38246.838 8000 + 1e-06 15300 12 567718.92 39832.256 8000 + 1e-06 15400 12 569910.41 41477.599 8000 + 1e-06 15500 12 572038.38 43132.458 8000 + 1e-06 15600 12 573913.47 44763.446 8000 + 1e-06 15700 12 575651.62 46334.905 8000 + 1e-06 15800 12 577306.75 47812.828 8000 + 1e-06 15900 12 578897.86 49166.374 8000 + 1e-06 16000 12 580431.98 50370.863 8000 + 1e-06 16100 12 581917.67 51410.025 8000 + 1e-06 16200 12 583392.37 52290.363 8000 + 1e-06 16300 12 584896.54 53001.616 8000 + 1e-06 16400 12 586445.21 53535.481 8000 + 1e-06 16500 12 588052.51 53896.917 8000 + 1e-06 16600 12 589732.17 54102.867 8000 + 1e-06 16700 12 591496.83 54180.423 8000 + 1e-06 16800 12 593357.37 54163.728 8000 + 1e-06 16900 12 595249.77 54088.894 8000 + 1e-06 17000 12 597130.72 53987.792 8000 + 1e-06 17100 12 598744.15 53852.584 8000 + 1e-06 17200 12 600057.69 53662.064 8000 + 1e-06 17300 12 601263.08 53505.031 8000 + 1e-06 17400 12 602411.57 53452.104 8000 + 1e-06 17500 12 603541.22 53553.609 8000 + 1e-06 17600 12 604067.01 53875.668 8000 + 1e-06 17700 12 602571.09 54490.575 8000 + 1e-06 17800 12 600292.75 55434.526 8000 + 1e-06 17900 12 597386.86 56736.273 8000 + 1e-06 18000 12 593981.08 58424.745 8000 + 1e-06 18100 12 590178.8 60527.06 8000 + 1e-06 18200 12 586056.65 63073.313 8000 + 1e-06 18300 12 581695.18 66084.237 8000 + 1e-06 18400 12 577195.63 69560.379 8000 + 1e-06 18500 12 572657.32 73490.56 8000 + 1e-06 18600 12 568173.86 77853.568 8000 + 1e-06 18700 12 563830.46 82617.321 8000 + 1e-06 18800 12 559701.49 87738.316 8000 + 1e-06 18900 12 555848.76 93162.955 8000 + 1e-06 19000 12 552088.23 98803.436 8000 + 1e-06 19100 12 548185.32 104427.42 8000 + 1e-06 19200 12 544535.46 110064.18 8000 + 1e-06 19300 12 541228.34 115757.05 8000 + 1e-06 19400 12 538293.89 121467.69 8000 + 1e-06 19500 12 535108.7 127127.41 8000 + 1e-06 19600 12 531413.61 132495.98 8000 + 1e-06 19700 12 527729.51 137678.56 8000 + 1e-06 19800 12 524151.76 142754.02 8000 + 1e-06 19900 12 520715.23 147730.68 8000 + 1e-06 20000 12 517436.17 152621.73 8000 + 1e-06 20100 12 514316.17 157423.95 8000 + 1e-06 20200 12 511400.64 162074.69 8000 + 1e-06 20300 12 508692.38 166497.97 8000 + 1e-06 20400 12 506153.1 170617.84 8000 + 1e-06 20500 12 503717.78 174351.25 8000 + 1e-06 20600 12 501293.63 177615.72 8000 + 1e-06 20700 12 498966.36 180365.82 8000 + 1e-06 20800 12 496760.02 182555.39 8000 + 1e-06 20900 12 494705.8 184132.07 8000 + 1e-06 21000 12 492841.84 185052.2 8000 + 1e-06 21100 12 491215.97 185288.72 8000 + 1e-06 21200 12 489677.84 184786.05 8000 + 1e-06 21300 12 488104.26 183535.77 8000 + 1e-06 21400 12 486394.75 181560.76 8000 + 1e-06 21500 12 484603.38 178874.58 8000 + 1e-06 21600 12 482731.75 175610.89 8000 + 1e-06 21700 12 480707.38 172071.04 8000 + 1e-06 21800 12 478504.9 168244.44 8000 + 1e-06 21900 12 476099.5 164130.08 8000 + 1e-06 22000 12 473401.48 159927.13 8000 + 1e-06 22100 12 470370.26 155762.08 8000 + 1e-06 22200 12 467067.88 151634.35 8000 + 1e-06 22300 12 463485.76 147589.77 8000 + 1e-06 22400 12 459593.94 143696.49 8000 + 1e-06 22500 12 455376.67 140035.23 8000 + 1e-06 22600 12 450819.48 136692.31 8000 + 1e-06 22700 12 445945.91 133704.47 8000 + 1e-06 22800 12 440758.89 131179.35 8000 + 1e-06 22900 12 435302.31 129342.22 8000 + 1e-06 23000 12 429598.98 128282.87 8000 + 1e-06 23100 12 423606.11 127995.47 8000 + 1e-06 23200 12 417364.51 128494.32 8000 + 1e-06 23300 12 410931.48 129772.21 8000 + 1e-06 23400 12 404376.34 131791.95 8000 + 1e-06 23500 12 397794.05 134484.8 8000 + 1e-06 23600 12 390990.06 137778.07 8000 + 1e-06 23700 12 384162.26 141638.59 8000 + 1e-06 23800 12 377636.5 145932.03 8000 + 1e-06 23900 12 371606.04 150514.72 8000 + 1e-06 24000 12 366266.24 155257.47 8000 + 1e-06 24100 12 361786.35 160026.32 8000 + 1e-06 24200 12 358332.56 164701.26 8000 + 1e-06 24300 12 356060.82 169171.06 8000 + 1e-06 24400 12 355078.48 173360.16 8000 + 1e-06 24500 12 355450.93 177217.02 8000 + 1e-06 24600 12 357219.84 180708.91 8000 + 1e-06 24700 12 360415.01 183807.52 8000 + 1e-06 24800 12 365023.77 186489.43 8000 + 1e-06 24900 12 371003.31 188744.64 8000 + 1e-06 25000 12 377719.96 190508.83 8000 + 1e-06 25100 12 385044.02 191723.21 8000 + 1e-06 25200 12 392909.32 192416.99 8000 + 1e-06 25300 12 401135.52 192645.59 8000 + 1e-06 25400 12 409539.24 192477.65 8000 + 1e-06 25500 12 417291.42 191761.92 8000 + 1e-06 25600 12 424737.36 190597.14 8000 + 1e-06 25700 12 431913.53 189106.01 8000 + 1e-06 25800 12 438736.08 187391.23 8000 + 1e-06 25900 12 445137.75 185551.39 8000 + 1e-06 26000 12 451066.87 183681.98 8000 + 1e-06 26100 12 456506.74 181876.3 8000 + 1e-06 26200 12 461444.38 180210.36 8000 + 1e-06 26300 12 465927.86 178746.53 8000 + 1e-06 26400 12 470133.57 177568.71 8000 + 1e-06 26500 12 474134.12 176672.99 8000 + 1e-06 26600 12 477972.05 176033.42 8000 + 1e-06 26700 12 481533.44 175580.73 8000 + 1e-06 26800 12 484262.56 175093.24 8000 + 1e-06 26900 12 486070.74 174178.51 8000 + 1e-06 27000 12 487322.68 173184.75 8000 + 1e-06 27100 12 488010.07 172084.41 8000 + 1e-06 27200 12 488079.27 170808.69 8000 + 1e-06 27300 12 487463.01 169291.88 8000 + 1e-06 27400 12 486083.88 167484.29 8000 + 1e-06 27500 12 483861.52 165357.96 8000 + 1e-06 27600 12 480726.55 162915.35 8000 + 1e-06 27700 12 476628.16 160197.08 8000 + 1e-06 27800 12 471546.66 157277.97 8000 + 1e-06 27900 12 465514.41 154256.68 8000 + 1e-06 28000 12 458577.33 151265.67 8000 + 1e-06 28100 12 450810.58 148472.95 8000 + 1e-06 28200 12 442311.34 146058.64 8000 + 1e-06 28300 12 433200.29 144179.21 8000 + 1e-06 28400 12 423625.66 142953.04 8000 + 1e-06 28500 12 413765.24 142450.35 8000 + 1e-06 28600 12 403817.87 142689.67 8000 + 1e-06 28700 12 393989.03 143646.16 8000 + 1e-06 28800 12 384484.33 145259.76 8000 + 1e-06 28900 12 375502.5 147428.86 8000 + 1e-06 29000 12 367250.91 150041.97 8000 + 1e-06 29100 12 359903.16 153002.45 8000 + 1e-06 29200 12 353678.89 156213.09 8000 + 1e-06 29300 12 348513.14 159524.58 8000 + 1e-06 29400 12 344408.06 162793.23 8000 + 1e-06 29500 12 341354.25 165860.66 8000 + 1e-06 29600 12 339292.66 168560.48 8000 + 1e-06 29700 12 338131.77 170723.76 8000 + 1e-06 29800 12 337633.87 172131.92 8000 + 1e-06 29900 12 337374.11 172433.2 8000 + 1e-06 30000 12 337379.48 171680.35 8000 + 1e-06 30100 12 337530.24 169927.53 8000 + 1e-06 30200 12 337706.33 167168.98 8000 + 1e-06 30300 12 337790.98 163426.76 8000 + 1e-06 30400 12 337697.64 158781.65 8000 + 1e-06 30500 12 337366.76 153367.47 8000 + 1e-06 30600 12 336755.07 147361.71 8000 + 1e-06 30700 12 335854.47 140976.25 8000 + 1e-06 30800 12 334662.2 134438.92 8000 + 1e-06 30900 12 333206.26 127982.95 8000 + 1e-06 31000 12 331464.93 121911.39 8000 + 1e-06 31100 12 329488.62 116351.57 8000 + 1e-06 31200 12 327373.17 111369.57 8000 + 1e-06 31300 12 325228.82 107014.37 8000 + 1e-06 31400 12 323169.4 103330.69 8000 + 1e-06 31500 12 321071.03 100385.5 8000 + 1e-06 31600 12 319031.38 98193.648 8000 + 1e-06 31700 12 317126.27 96712.557 8000 + 1e-06 31800 12 315438.37 95876.196 8000 + 1e-06 31900 12 313815.51 95565.683 8000 + 1e-06 32000 12 312239.38 95585.612 8000 + 1e-06 32100 12 310926.28 95828.27 8000 + 1e-06 32200 12 309948.5 96173.311 8000 + 1e-06 32300 12 309370.35 96442.454 8000 + 1e-06 32400 12 309201.18 96472.304 8000 + 1e-06 32500 12 309383.35 96140.953 8000 + 1e-06 32600 12 309865.73 95349.932 8000 + 1e-06 32700 12 310615.88 94029.061 8000 + 1e-06 32800 12 311624.15 92145.895 8000 + 1e-06 32900 12 312897.69 89717.564 8000 + 1e-06 33000 12 314451.54 86812.433 8000 + 1e-06 33100 12 316227.53 83544.302 8000 + 1e-06 33200 12 318247.7 80051.39 8000 + 1e-06 33300 12 320540.3 76478.862 8000 + 1e-06 33400 12 323095.15 72955.915 8000 + 1e-06 33500 12 325858.6 69576.683 8000 + 1e-06 33600 12 328744.8 66391.967 8000 + 1e-06 33700 12 331653.91 63413.798 8000 + 1e-06 33800 12 334464.83 60630.152 8000 + 1e-06 33900 12 337044.79 58019.718 8000 + 1e-06 34000 12 339236.01 55565.231 8000 + 1e-06 34100 12 340903.65 53265.034 8000 + 1e-06 34200 12 341925.23 51135.512 8000 + 1e-06 34300 12 342206.93 49222.627 8000 + 1e-06 34400 12 341649.35 47586.207 8000 + 1e-06 34500 12 340176.56 46291.105 8000 + 1e-06 34600 12 337667.96 45393.826 8000 + 1e-06 34700 12 333648.9 44922.723 8000 + 1e-06 34800 12 328322.97 44898.764 8000 + 1e-06 34900 12 321776.97 45316.954 8000 + 1e-06 35000 12 314135.31 46151.059 8000 + 1e-06 35100 12 305598.53 47348.476 8000 + 1e-06 35200 12 296352.23 48877.862 8000 + 1e-06 35300 12 286690.37 50727.291 8000 + 1e-06 35400 12 276916.56 52890.03 8000 + 1e-06 35500 12 267324.34 55346.515 8000 + 1e-06 35600 12 258272.27 58117.818 8000 + 1e-06 35700 12 250043.55 61209.498 8000 + 1e-06 35800 12 242858.64 64607.799 8000 + 1e-06 35900 12 236841.89 68268.869 8000 + 1e-06 36000 12 232039.2 72109.967 8000 + 1e-06 36100 12 228474.09 76010.069 8000 + 1e-06 36200 12 226115.66 79808.944 8000 + 1e-06 36300 12 224858.91 83318.088 8000 + 1e-06 36400 12 224574.55 86340.123 8000 + 1e-06 36500 12 225062.39 88691.698 8000 + 1e-06 36600 12 226104.86 90211.829 8000 + 1e-06 36700 12 227493.83 90797.861 8000 + 1e-06 36800 12 229033.4 90446.128 8000 + 1e-06 36900 12 230503.16 89238.368 8000 + 1e-06 37000 12 231859.26 87294.45 8000 + 1e-06 37100 12 233083.51 84767.219 8000 + 1e-06 37200 12 234235.94 81827.155 8000 + 1e-06 37300 12 235402.6 78655.588 8000 + 1e-06 37400 12 236702.37 75432.209 8000 + 1e-06 37500 12 238271.62 72343.239 8000 + 1e-06 37600 12 240191.8 69493.919 8000 + 1e-06 37700 12 242533.8 66949.307 8000 + 1e-06 37800 12 245357.31 64751.161 8000 + 1e-06 37900 12 248707.62 62935.998 8000 + 1e-06 38000 12 252613.72 61551.838 8000 + 1e-06 38100 12 257052.41 60672.572 8000 + 1e-06 38200 12 261959.48 60392.157 8000 + 1e-06 38300 12 267252.31 60809.22 8000 + 1e-06 38400 12 272813.05 62005.004 8000 + 1e-06 38500 12 278498.77 64020.387 8000 + 1e-06 38600 12 284150.51 66835.207 8000 + 1e-06 38700 12 289604.09 70354.609 8000 + 1e-06 38800 12 294696.3 74392.688 8000 + 1e-06 38900 12 299233.72 78587.64 8000 + 1e-06 39000 12 303148.91 82674.175 8000 + 1e-06 39100 12 306708.36 86536.948 8000 + 1e-06 39200 12 309600.62 89862.067 8000 + 1e-06 39300 12 311700.43 92456.711 8000 + 1e-06 39400 12 312846.09 94218.029 8000 + 1e-06 39500 12 312996.55 95123.249 8000 + 1e-06 39600 12 311853.31 95204.167 8000 + 1e-06 39700 12 309573.91 94589.061 8000 + 1e-06 39800 12 306120.98 93445.743 8000 + 1e-06 39900 12 301697.58 91905.478 8000 + 1e-06 40000 12 296465.51 90172.857 8000 + 1e-06 40100 12 290548.45 88402.41 8000 + 1e-06 40200 12 284112.93 86721.642 8000 + 1e-06 40300 12 277419.21 85394.11 8000 + 1e-06 40400 12 270601.67 84327.103 8000 + 1e-06 40500 12 263782.18 83363.209 8000 + 1e-06 40600 12 257075.79 82350.637 8000 + 1e-06 40700 12 250587.81 81169.87 8000 + 1e-06 40800 12 244408.86 79765.108 8000 + 1e-06 40900 12 238613.12 78159.356 8000 + 1e-06 41000 12 233263.11 76444.561 8000 + 1e-06 41100 12 228410.45 74765.108 8000 + 1e-06 41200 12 224097.82 73288.059 8000 + 1e-06 41300 12 220360.61 72170.137 8000 + 1e-06 41400 12 217228.06 71527.798 8000 + 1e-06 41500 12 214724.04 71415.43 8000 + 1e-06 41600 12 212866.32 71815.969 8000 + 1e-06 41700 12 211661 72645.932 8000 + 1e-06 41800 12 211103.8 73762.785 8000 + 1e-06 41900 12 211177.1 74986.705 8000 + 1e-06 42000 12 211607.62 76028.195 8000 + 1e-06 42100 12 212363.62 76700.039 8000 + 1e-06 42200 12 213529.03 76938.547 8000 + 1e-06 42300 12 215008.35 76693.739 8000 + 1e-06 42400 12 216674.6 75984.606 8000 + 1e-06 42500 12 218453.89 74873.786 8000 + 1e-06 42600 12 220270.22 73459.542 8000 + 1e-06 42700 12 222044.1 71860.203 8000 + 1e-06 42800 12 223693.34 70197.611 8000 + 1e-06 42900 12 225131.14 68583.075 8000 + 1e-06 43000 12 226264.5 67108.382 8000 + 1e-06 43100 12 227001.96 65842.14 8000 + 1e-06 43200 12 227259.44 64830.806 8000 + 1e-06 43300 12 226966.5 64102.73 8000 + 1e-06 43400 12 226072.23 63673.107 8000 + 1e-06 43500 12 224550.01 63547.892 8000 + 1e-06 43600 12 222400.27 63725.546 8000 + 1e-06 43700 12 219649.08 64198.122 8000 + 1e-06 43800 12 216345.77 64940.248 8000 + 1e-06 43900 12 212561.67 65898.806 8000 + 1e-06 44000 12 208386.13 66994.934 8000 + 1e-06 44100 12 203921.52 68131.378 8000 + 1e-06 44200 12 199278.14 69204.386 8000 + 1e-06 44300 12 194569.44 70118.481 8000 + 1e-06 44400 12 189909.06 70810.594 8000 + 1e-06 44500 12 185407.95 71268.155 8000 + 1e-06 44600 12 181166.51 71493.826 8000 + 1e-06 44700 12 177276.76 71524.448 8000 + 1e-06 44800 12 173823.45 71423.226 8000 + 1e-06 44900 12 170886.41 71262.132 8000 + 1e-06 45000 12 168528.37 71107.616 8000 + 1e-06 45100 12 166817.96 70991.562 8000 + 1e-06 45200 12 165820.31 70920.666 8000 + 1e-06 45300 12 165574.99 70863.13 8000 + 1e-06 45400 12 166019.37 70710.029 8000 + 1e-06 45500 12 167147.87 70350.412 8000 + 1e-06 45600 12 169082.77 69657.821 8000 + 1e-06 45700 12 171945.43 68520.345 8000 + 1e-06 45800 12 175909.9 66883.643 8000 + 1e-06 45900 12 181195.22 64747.392 8000 + 1e-06 46000 12 188023.1 62178.63 8000 + 1e-06 46100 12 196442.27 59308.946 8000 + 1e-06 46200 12 206276.92 56311.64 8000 + 1e-06 46300 12 217187.2 53375.161 8000 + 1e-06 46400 12 228713.53 50677.575 8000 + 1e-06 46500 12 240278.4 48364.725 8000 + 1e-06 46600 12 251273.01 46535.827 8000 + 1e-06 46700 12 261407.3 45239.704 8000 + 1e-06 46800 12 270264.36 44479.416 8000 + 1e-06 46900 12 277578.87 44223.038 8000 + 1e-06 47000 12 283258 44417.235 8000 + 1e-06 47100 12 287156.44 45000.19 8000 + 1e-06 47200 12 289242.87 45911.176 8000 + 1e-06 47300 12 289597.36 47095.056 8000 + 1e-06 47400 12 288380.97 48501.691 8000 + 1e-06 47500 12 285805.13 50081.427 8000 + 1e-06 47600 12 282130.22 51780.572 8000 + 1e-06 47700 12 277128.82 53385.936 8000 + 1e-06 47800 12 271407.61 54873.773 8000 + 1e-06 47900 12 265556.17 56217.287 8000 + 1e-06 48000 12 260082.32 57338.782 8000 + 1e-06 48100 12 255399.15 58166.789 8000 + 1e-06 48200 12 251785.89 58653.934 8000 + 1e-06 48300 12 249277.86 58789.891 8000 + 1e-06 48400 12 247494.11 58609.44 8000 + 1e-06 48500 12 245660.12 58192.865 8000 + 1e-06 48600 12 242968.44 57656.856 8000 + 1e-06 48700 12 238968.69 57140.878 8000 + 1e-06 48800 12 233565.17 56788.953 8000 + 1e-06 48900 12 227411.99 56720.334 8000 + 1e-06 49000 12 221053.64 57003.014 8000 + 1e-06 49100 12 215153.96 57629.419 8000 + 1e-06 49200 12 210402.16 58574.859 8000 + 1e-06 49300 12 207216.41 59750.238 8000 + 1e-06 49400 12 205860.43 61020.818 8000 + 1e-06 49500 12 206382.26 62237.849 8000 + 1e-06 49600 12 208600.44 63264.958 8000 + 1e-06 49700 12 212280.2 63999.734 8000 + 1e-06 49800 12 217167.6 64388.533 8000 + 1e-06 49900 12 223002.61 64430.977 8000 +Loop time of 0.997677 on 1 procs for 49900 steps with 12 atoms -99.5% CPU use with 1 MPI tasks x no OpenMP threads +99.2% CPU use with 1 MPI tasks x no OpenMP threads MPI task timing breakdown: Section | min time | avg time | max time |%varavg| %total --------------------------------------------------------------- -Pair | 0.34189 | 0.34189 | 0.34189 | 0.0 | 23.42 +Pair | 0.24529 | 0.24529 | 0.24529 | 0.0 | 24.59 Neigh | 0 | 0 | 0 | 0.0 | 0.00 -Comm | 0.0023579 | 0.0023579 | 0.0023579 | 0.0 | 0.16 -Output | 0.0038476 | 0.0038476 | 0.0038476 | 0.0 | 0.26 -Modify | 1.1002 | 1.1002 | 1.1002 | 0.0 | 75.37 -Other | | 0.01145 | | | 0.78 +Comm | 0.0019929 | 0.0019929 | 0.0019929 | 0.0 | 0.20 +Output | 0.0024977 | 0.0024977 | 0.0024977 | 0.0 | 0.25 +Modify | 0.74056 | 0.74056 | 0.74056 | 0.0 | 74.23 +Other | | 0.007341 | | | 0.74 Nlocal: 12 ave 12 max 12 min Histogram: 1 0 0 0 0 0 0 0 0 0 diff --git a/src/GRANULAR/fix_granular_mdr.cpp b/src/GRANULAR/fix_granular_mdr.cpp index 8d9a0f116a..fcdc3b2b17 100644 --- a/src/GRANULAR/fix_granular_mdr.cpp +++ b/src/GRANULAR/fix_granular_mdr.cpp @@ -154,16 +154,16 @@ void FixGranularMDR::setup_pre_force(int /*vflag*/) norm_model2 = dynamic_cast(fix->model->normal_model); - if (norm_model && norm_model2 && fabs(norm_model->E - norm_model2->E) > EPSILON) + if (norm_model && norm_model2 && fabs(norm_model->get_emod() - norm_model2->get_emod()) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Young's modulus in pair style, {}, does not agree with value {} in fix gran/wall/region", - norm_model->E, norm_model2->E); - if (fabs(norm_model->nu - norm_model2->nu) > EPSILON) + norm_model->get_emod(), norm_model2->get_emod()); + if (fabs(norm_model->get_poiss() - norm_model2->get_poiss()) > EPSILON) error->all( FLERR, Error::NOLASTLINE, "Poisson's ratio in pair style, {}, does not agree with value {} in fix gran/wall/region", - norm_model->nu, norm_model2->nu); + norm_model->get_poiss(), norm_model2->get_poiss()); if (fabs(norm_model->Y - norm_model2->Y) > EPSILON) error->all( FLERR, Error::NOLASTLINE, diff --git a/src/GRANULAR/gran_sub_mod_damping.cpp b/src/GRANULAR/gran_sub_mod_damping.cpp index b68a720413..5420895c32 100644 --- a/src/GRANULAR/gran_sub_mod_damping.cpp +++ b/src/GRANULAR/gran_sub_mod_damping.cpp @@ -196,7 +196,8 @@ GranSubModDampingMDR::GranSubModDampingMDR(GranularModel *gm, LAMMPS *lmp) : void GranSubModDampingMDR::coeffs_to_local() { damp_type = coeffs[0]; // damping type 1 = mdr stiffness or 2 = velocity - if (damp_type != 1 && damp_type != 2) error->all(FLERR, "Illegal MDR normal model, damping type must an integer equal to 1 or 2"); + if (damp_type != 1 && damp_type != 2) + error->all(FLERR, "Illegal MDR damping model, damping type must an integer equal to 1 or 2"); } /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_damping.h b/src/GRANULAR/gran_sub_mod_damping.h index 274c3d9e29..ac1363f64f 100644 --- a/src/GRANULAR/gran_sub_mod_damping.h +++ b/src/GRANULAR/gran_sub_mod_damping.h @@ -42,7 +42,6 @@ namespace Granular_NS { protected: double damp_prefactor; double damp; - int damp_type; // damping type is only used by normal mdr model }; /* ---------------------------------------------------------------------- */ @@ -102,6 +101,9 @@ namespace Granular_NS { void coeffs_to_local() override; void init() override; double calculate_forces() override; + + protected: + int damp_type; }; /* ---------------------------------------------------------------------- */ diff --git a/src/GRANULAR/gran_sub_mod_normal.cpp b/src/GRANULAR/gran_sub_mod_normal.cpp index 68cb853d9d..b0f04cfa40 100644 --- a/src/GRANULAR/gran_sub_mod_normal.cpp +++ b/src/GRANULAR/gran_sub_mod_normal.cpp @@ -446,6 +446,7 @@ GranSubModNormalMDR::GranSubModNormalMDR(GranularModel *gm, LAMMPS *lmp) : size_history = 27; nsvector = 1; fix_mdr_flag = 0; + material_properties = 1; id_fix = nullptr; nondefault_history_transfer = 1; @@ -468,23 +469,23 @@ GranSubModNormalMDR::~GranSubModNormalMDR() void GranSubModNormalMDR::coeffs_to_local() { - E = coeffs[0]; // Young's modulus - nu = coeffs[1]; // Poisson's ratio + Emod = coeffs[0]; // Young's modulus + poiss = coeffs[1]; // Poisson's ratio Y = coeffs[2]; // yield stress gamma = coeffs[3]; // effective surface energy psi_b = coeffs[4]; // bulk response trigger based on ratio of remaining free area: A_{free}/A_{total} damp = coeffs[5]; // coefficent of restitution - if (E <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); - if (nu < 0.0 || nu > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); + if (Emod <= 0.0) error->all(FLERR, "Illegal MDR normal model, Young's modulus must be greater than 0"); + if (poiss < 0.0 || poiss > 0.5) error->all(FLERR, "Illegal MDR normal model, Poisson's ratio must be between 0 and 0.5"); if (Y < 0.0) error->all(FLERR, "Illegal MDR normal model, yield stress must be greater than or equal to 0"); if (gamma < 0.0) error->all(FLERR, "Illegal MDR normal model, effective surface energy must be greater than or equal to 0"); if (psi_b < 0.0 || psi_b > 1.0) error->all(FLERR, "Illegal MDR normal model, psi_b must be between 0 and 1.0"); if (damp < 0.0) error->all(FLERR, "Illegal MDR normal model, damping coefficent must be greater than or equal to 0"); - G = E / (2.0 * (1.0 + nu)); // shear modulus - kappa = E / (3.0 * (1.0 - 2.0 * nu)); // bulk modulus - Eeff = E / (1.0 - pow(nu, 2.0)); // composite plane strain modulus + G = Emod / (2.0 * (1.0 + poiss)); // shear modulus + kappa = Emod / (3.0 * (1.0 - 2.0 * poiss)); // bulk modulus + Eeff = Emod / (1.0 - pow(poiss, 2.0)); // composite plane strain modulus // precomputing factors @@ -613,15 +614,15 @@ double GranSubModNormalMDR::calculate_forces() // itag and jtag persist after neighbor list builds, use tags to compare to match // contact history variables consistently across steps for a particle pair. if ((contactSide == 0 && itag_true > jtag_true) || (contactSide != 0 && itag_true < jtag_true)) { - gm->i = i_true; - gm->j = j_true; - gm->radi = radi_true; - gm->radj = radj_true; + gm->i = i_true; + gm->j = j_true; + gm->radi = radi_true; + gm->radj = radj_true; } else { - gm->i = j_true; - gm->j = i_true; - gm->radi = radj_true; - gm->radj = radi_true; + gm->i = j_true; + gm->j = i_true; + gm->radi = radj_true; + gm->radj = radi_true; } // determine the two maximum experienced geometric overlaps on either side of rigid flat @@ -757,7 +758,7 @@ double GranSubModNormalMDR::calculate_forces() // depth of particle center const double zR = R - (deltamax_MDR - deltae1Dmax); - deltaR = 2 * amaxsq * (-1 + nu) - (-1 + 2 * nu) * zR * (-zR + sqrt(amaxsq + pow(zR, 2))); + deltaR = 2 * amaxsq * (-1 + poiss) - (-1 + 2 * poiss) * zR * (-zR + sqrt(amaxsq + pow(zR, 2))); deltaR *= Fmax / (MY_2PI * amaxsq * G * sqrt(amaxsq + pow(zR, 2))); // transformed elastic displacement @@ -961,7 +962,7 @@ double GranSubModNormalMDR::calculate_forces() a_damp = a_damp/2.0; damp_scale = sqrt(gm->meff * 2.0 * Eeff2particle * a_damp); double *deltao_offset = &history[DELTAO_0]; - const double wfm = std::exp(10.7*(*deltao_offset)/Rinitial[gm->i] - 10.0) + 1.0; // wall force magnifier + const double wfm = std::exp(10.7 * (*deltao_offset) / Rinitial[gm->i] - 10.0) + 1.0; // wall force magnifier F = wij * F0 * wfm; } else { damp_scale = sqrt(gm->meff * 2.0 * Eeff * a_damp); diff --git a/src/GRANULAR/gran_sub_mod_normal.h b/src/GRANULAR/gran_sub_mod_normal.h index 8142d88cea..9805bd81c0 100644 --- a/src/GRANULAR/gran_sub_mod_normal.h +++ b/src/GRANULAR/gran_sub_mod_normal.h @@ -143,7 +143,7 @@ namespace Granular_NS { void coeffs_to_local() override; void init() override; double calculate_forces() override; - double E, nu, Y, gamma, psi_b; // specified coeffs + double Y, gamma, psi_b; // specified coeffs protected: double G, kappa, Eeff; // derived coeffs From d2d7248e3a515130ceb11538d361d6e45db8b242 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 9 Apr 2025 20:41:08 -0400 Subject: [PATCH 145/396] import original version 3.11.3 files --- src/nlohmann/json.hpp | 24765 ++++++++++++++++++++++++++++++++++++ src/nlohmann/json_fwd.hpp | 176 + 2 files changed, 24941 insertions(+) create mode 100644 src/nlohmann/json.hpp create mode 100644 src/nlohmann/json_fwd.hpp diff --git a/src/nlohmann/json.hpp b/src/nlohmann/json.hpp new file mode 100644 index 0000000000..8b72ea6539 --- /dev/null +++ b/src/nlohmann/json.hpp @@ -0,0 +1,24765 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple +#include // char_traits + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template

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%0A}+^{=vRUNNSk;)|E{(Zl^wqdobeV^_I}15cw! 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 z z3ZaAQy{^ra=8zRzK}I$MpT8)L0{7{iZeE1W{6zek%hX}(qtInNP2WDQczXiubB51i zG`(b}=-~0}tCYw>Twl4e=;4A=Q&&dkdQ{o>)JQGx!gZOMdSXAy>2xgP5`&MKt>SDH z`8wvLT_?U?DwBm{VrQ-DEKy-VmEetDvqi^MsySThEpqeD_gl?9n+bhNlFz|0GbN|$ z-Tb#6c%y?37YnTBqBEx~_l>pb@SGx(gM#V5`c?0R<6uziqpQyN$kfwtShZW)bxC#% zJ5KpqyjpT8N06YO;gp0Q$$FkaAyN1>_K|(}E8ShDH+F4qN^HW4Jcmc*GA_XlgIeFV zTG1fxzVObTj^81qQRuJ7NHvB4OXLvRF__#CMzm)=I}mhY$9w={V$w9^2y}Rk7evLy z;2a04xCro{_zK6_o*WWfyxn5OTr{ty<-P>u_~AiP(}6vjuOr{ye*E>s3sk>iqL@)~ z!6B%rt5YUJCPmQpqHX>o8PhJ_XkOcVmm;agx8@+Gl(agW7jvG5ns)qa)>r|G+-N82 zD;~m#u?NB39Yk$wxL6pmK_0EV3%JY&UimWunC62sh{M!=3&&N39*b22Wbf&3GC}U_ zxJ5Jv76wsbmpe2t4Zw+w2nCMWJ8CZ@IwPxnu6}XN9>5&*uSa7ih~;H~tcN+CJ>SY` zksEJ&A3R0(KdGMU6{&BJIfkmc1@QJAZ~Iv-B%Nau=n!=TudhHT21EII>5Zv?j2Q#(0o7Ly%j-dB~Sr7G*D+RQc%EE)z=;v0@ z|FZ1EEgR*<+>C~G{gb6{s3|!Epd)%8PJz(WVnL(2tbhE|m>c~_IBu9J&Q%`)Pa9O; z(*(y9ml+eG*t-E>y_^A7#t<`F_2DibRv(o(tETAHAl|N8d~Sm1b+$&MA7OOfyL#;xgXLWVEn$%NZF7g*$0RM%%ehtA~8z* z{yi8be`5Mab91kw#gFcGro@BLZt0jzDML*v;Ex|K`Ai6_OPl!6jPYh_;<8UHxN?EY zPEOg;%&%PkGB1CwEUGssabRsv+@T*B0=^}old)(pl&WcP-g{w@&!5RiB#!GsIGFMY zq$jTm7pcl%z-UW0ODpC7h85u|%>s}VbTC)rhV*d+*npCslkx$-nX}=_#s^xy)6bXa zFwI)z)_@5Fyrb1WH~|O{ie(U>(3%k$ebnDnO}|_t0cNAZch(eyYFHv(H%mu^S4sxj zkO9uiPTpbE^K04~;9i&W>@4ELZ=Ey&okr#p485nx7pDo3$o5Z*{U*n0jg}7?4E1