Merge pull request #3958 from jrgissing/fix_deposit-var-keyword

Fix deposit var keyword
This commit is contained in:
Axel Kohlmeyer
2023-11-10 10:56:21 -05:00
committed by GitHub
3 changed files with 129 additions and 15 deletions

View File

@ -17,12 +17,16 @@ Syntax
* M = insert a single atom or molecule every M steps
* seed = random # seed (positive integer)
* one or more keyword/value pairs may be appended to args
* keyword = *region* or *id* or *global* or *local* or *near* or *gaussian* or *attempt* or *rate* or *vx* or *vy* or *vz* or *target* or *mol* or *molfrac* or *rigid* or *shake* or *orient* or *units*
* keyword = *region* or *var* or *set* or *id* or *global* or *local* or *near* or *gaussian* or *attempt* or *rate* or *vx* or *vy* or *vz* or *target* or *mol* or *molfrac* or *rigid* or *shake* or *orient* or *units*
.. parsed-literal::
*region* value = region-ID
region-ID = ID of region to use as insertion volume
*var* value = name = variable name to evaluate for test of atom creation
*set* values = dim name
dim = *x* or *y* or *z*
name = name of variable to set with x, y, or z atom position
*id* value = *max* or *next*
max = atom ID for new atom(s) is max ID of all current atoms plus one
next = atom ID for new atom(s) increments by one for every deposition
@ -193,17 +197,19 @@ simulation that is "nearby" the chosen x,y position. In this context,
particles is less than the *delta* setting.
Once a trial x,y,z position has been selected, the insertion is only
performed if no current atom in the simulation is within a distance R
of any atom in the new particle, including the effect of periodic
boundary conditions if applicable. R is defined by the *near*
keyword. Note that the default value for R is 0.0, which will allow
atoms to strongly overlap if you are inserting where other atoms are
present. This distance test is performed independently for each atom
in an inserted molecule, based on the randomly rotated configuration
of the molecule. If this test fails, a new random position within the
insertion volume is chosen and another trial is made. Up to Q
attempts are made. If the particle is not successfully inserted,
LAMMPS prints a warning message.
performed if both the *near* and *var* keywords are satisfied (see below).
If either the *near* or the *var* keyword is not satisfied, a new random
position within the insertion volume is chosen and another trial is made.
Up to Q attempts are made. If one or more particle insertions are not
successful, LAMMPS prints a warning message.
The *near* keyword ensures that no current atom in the simulation is within
a distance R of any atom in the new particle, including the effect of
periodic boundary conditions if applicable. Note that the default value
for R is 0.0, which will allow atoms to strongly overlap if you are
inserting where other atoms are present. This distance test is performed
independently for each atom in an inserted molecule, based on the randomly
rotated configuration of the molecule.
.. note::
@ -214,6 +220,24 @@ LAMMPS prints a warning message.
existing particle. LAMMPS will issue a warning if R is smaller than
this value, based on the radii of existing and inserted particles.
The *var* and *set* keywords can be used together to provide a criterion
for accepting or rejecting the addition of an individual atom, based on its
coordinates. The *name* specified for the *var* keyword is the name of an
:doc:`equal-style variable <variable>` that should evaluate to a zero or
non-zero value based on one or two or three variables that will store the
*x*, *y*, or *z* coordinates of an atom (one variable per coordinate). If
used, these other variables must be :doc:`internal-style variables
<variable>` defined in the input script; their initial numeric value can be
anything. They must be internal-style variables, because this command
resets their values directly. The *set* keyword is used to identify the
names of these other variables, one variable for the *x*-coordinate of a
created atom, one for *y*, and one for *z*. When an atom is created, its
:math:`(x,y,z)` coordinates become the values for any *set* variable that
is defined. The *var* variable is then evaluated. If the returned value
is 0.0, the atom is not created. If it is non-zero, the atom is created.
For an example of how to use these keywords, see the
:doc:`create_atoms <create_atoms>`command.
The *rate* option moves the insertion volume in the z direction (3d)
or y direction (2d). This enables particles to be inserted from a
successively higher height over time. Note that this parameter is

View File

@ -20,6 +20,7 @@
#include "domain.h"
#include "error.h"
#include "fix.h"
#include "input.h"
#include "lattice.h"
#include "math_const.h"
#include "math_extra.h"
@ -29,6 +30,7 @@
#include "random_park.h"
#include "region.h"
#include "update.h"
#include "variable.h"
#include <cmath>
#include <cstring>
@ -209,6 +211,10 @@ FixDeposit::~FixDeposit()
delete [] idrigid;
delete [] idshake;
delete [] idregion;
delete [] vstr;
delete [] xstr;
delete [] ystr;
delete [] zstr;
memory->destroy(coords);
memory->destroy(imageflags);
}
@ -226,6 +232,8 @@ int FixDeposit::setmask()
void FixDeposit::init()
{
warnflag = 1;
// set index and check validity of region
iregion = domain->get_region_by_id(idregion);
@ -361,6 +369,8 @@ void FixDeposit::pre_exchange()
} while (iregion->match(coord[0],coord[1],coord[2]) == 0);
} else error->all(FLERR,"Unknown particle distribution in fix deposit");
if (varflag && vartest(coord[0],coord[1],coord[2]) == 0) continue;
// adjust vertical coord by offset
if (dimension == 2) coord[1] += offset;
@ -583,8 +593,10 @@ void FixDeposit::pre_exchange()
// warn if not successful b/c too many attempts
if (!success && comm->me == 0)
error->warning(FLERR,"Particle deposition was unsuccessful");
if (warnflag && !success && comm->me == 0) {
error->warning(FLERR,"One or more particle depositions were unsuccessful");
warnflag = 0;
}
// reset global natoms,nbonds,etc
// increment maxtag_all and maxmol_all if necessary
@ -661,6 +673,8 @@ void FixDeposit::options(int narg, char **arg)
iregion = nullptr;
idregion = nullptr;
varflag = 0;
vstr = xstr = ystr = zstr = nullptr;
mode = ATOM;
molfrac = nullptr;
rigidflag = 0;
@ -680,6 +694,7 @@ void FixDeposit::options(int narg, char **arg)
scaleflag = 1;
targetflag = 0;
orientflag = 0;
warnflag = 1;
rx = 0.0;
ry = 0.0;
rz = 0.0;
@ -693,6 +708,27 @@ void FixDeposit::options(int narg, char **arg)
idregion = utils::strdup(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg], "var") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "fix deposit var", error);
delete[] vstr;
vstr = utils::strdup(arg[iarg + 1]);
varflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg], "set") == 0) {
if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "fix deposit set", error);
if (strcmp(arg[iarg + 1], "x") == 0) {
delete[] xstr;
xstr = utils::strdup(arg[iarg + 2]);
} else if (strcmp(arg[iarg + 1], "y") == 0) {
delete[] ystr;
ystr = utils::strdup(arg[iarg + 2]);
} else if (strcmp(arg[iarg + 1], "z") == 0) {
delete[] zstr;
zstr = utils::strdup(arg[iarg + 2]);
} else
error->all(FLERR, "Unknown fix deposit set option {}", arg[iarg + 2]);
iarg += 3;
} else if (strcmp(arg[iarg],"mol") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
int imol = atom->find_molecule(arg[iarg+1]);
@ -815,6 +851,39 @@ void FixDeposit::options(int narg, char **arg)
iarg += 4;
} else error->all(FLERR,"Illegal fix deposit command");
}
// error check and further setup for variable test
if (!vstr && (xstr || ystr || zstr))
error->all(FLERR, "Incomplete use of variables in fix deposit command");
if (vstr && (!xstr && !ystr && !zstr))
error->all(FLERR, "Incomplete use of variables in fix deposit command");
if (varflag) {
vvar = input->variable->find(vstr);
if (vvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", vstr);
if (!input->variable->equalstyle(vvar))
error->all(FLERR, "Variable for fix deposit is invalid style");
if (xstr) {
xvar = input->variable->find(xstr);
if (xvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", xstr);
if (!input->variable->internalstyle(xvar))
error->all(FLERR, "Variable for fix deposit is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
if (yvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", ystr);
if (!input->variable->internalstyle(yvar))
error->all(FLERR, "Variable for fix deposit is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
if (zvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", zstr);
if (!input->variable->internalstyle(zvar))
error->all(FLERR, "Variable for fix deposit is invalid style");
}
}
}
/* ----------------------------------------------------------------------
@ -908,3 +977,20 @@ void *FixDeposit::extract(const char *str, int &itype)
return nullptr;
}
/* ----------------------------------------------------------------------
test a generated atom position against variable evaluation
first set x,y,z values in internal variables
------------------------------------------------------------------------- */
int FixDeposit::vartest(double x, double y, double z)
{
if (xstr) input->variable->internal_set(xvar, x);
if (ystr) input->variable->internal_set(yvar, y);
if (zstr) input->variable->internal_set(zvar, z);
double value = input->variable->compute_equal(vvar);
if (value == 0.0) return 0;
return 1;
}

View File

@ -40,7 +40,8 @@ class FixDeposit : public Fix {
private:
int ninsert, ntype, nfreq, seed;
int globalflag, localflag, maxattempt, rateflag, scaleflag, targetflag;
int mode, rigidflag, shakeflag, idnext, distflag, orientflag;
int mode, rigidflag, shakeflag, idnext, distflag, orientflag, warnflag;
int varflag, vvar, xvar, yvar, zvar;
double lo, hi, deltasq, nearsq, rate, sigma;
double vxlo, vxhi, vylo, vyhi, vzlo, vzhi;
double xlo, xhi, ylo, yhi, zlo, zhi, xmid, ymid, zmid;
@ -48,6 +49,8 @@ class FixDeposit : public Fix {
class Region *iregion;
char *idregion;
char *idrigid, *idshake;
char *vstr, *xstr, *ystr, *zstr;
char *xstr_copy, *ystr_copy, *zstr_copy;
class Molecule **onemols;
int nmol, natom_max;
@ -64,6 +67,7 @@ class FixDeposit : public Fix {
void find_maxid();
void options(int, char **);
int vartest(double, double, double); // evaluate a variable with new atom position
};
} // namespace LAMMPS_NS