forked from lijiext/lammps
Merge pull request #603 from jrgissing/Ncreate_atoms
add exactly N particles to available lattice points
This commit is contained in:
commit
9d06430894
|
@ -286,6 +286,9 @@ Doc page with :doc:`WARNING messages <Errors_warnings>`
|
|||
*Attempting to rescale a 0.0 temperature*
|
||||
Cannot rescale a temperature that is already 0.0.
|
||||
|
||||
*Attempting to insert more particles than available lattice points*
|
||||
Self-explanatory.
|
||||
|
||||
*Bad FENE bond*
|
||||
Two atoms in a FENE bond have become so far apart that the bond cannot
|
||||
be computed.
|
||||
|
|
|
@ -683,6 +683,9 @@ This will most likely cause errors in kinetic fluctuations.
|
|||
*Slab correction not needed for MSM*
|
||||
Slab correction is intended to be used with Ewald or PPPM and is not needed by MSM.
|
||||
|
||||
*Specifying an 'subset' value of '0' is equivalent to no 'subset' keyword*
|
||||
Self-explanatory.
|
||||
|
||||
*System is not charge neutral, net charge = %g*
|
||||
The total charge on all atoms on the system is not 0.0.
|
||||
For some KSpace solvers this is only a warning.
|
||||
|
|
|
@ -27,7 +27,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 *remap* or *var* or *set* or *units*
|
||||
* keyword = *mol* or *basis* or *ratio* or *subset* or *remap* or *var* or *set* or *rotate* or *units*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
@ -37,6 +37,12 @@ Syntax
|
|||
*basis* values = M itype
|
||||
M = which basis atom
|
||||
itype = atom type (1-N) to assign to this basis atom
|
||||
*ratio* values = frac seed
|
||||
frac = fraction of lattice sites (0 to 1) to populate randomly
|
||||
seed = random # seed (positive integer)
|
||||
*subset* values = Nsubset seed
|
||||
Nsubset = # of lattice sites to populate randomly
|
||||
seed = random # seed (positive integer)
|
||||
*remap* value = *yes* or *no*
|
||||
*var* value = name = variable name to evaluate for test of atom creation
|
||||
*set* values = dim name
|
||||
|
@ -59,6 +65,7 @@ Examples
|
|||
|
||||
create_atoms 1 box
|
||||
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 1 box var v set x xpos set y ypos
|
||||
|
||||
|
@ -214,6 +221,19 @@ command for specifics on how basis atoms are defined for the unit cell
|
|||
of the lattice. By default, all created atoms are assigned the
|
||||
argument *type* as their atom type.
|
||||
|
||||
The *ratio* and *subset* keywords can be used in conjunction with the
|
||||
*box* or *region* styles to limit the total number of particles
|
||||
inserted. The lattice defines a set of *Nlatt* eligible sites for
|
||||
inserting particles, which may be limited by the *region* style or the
|
||||
*var* and *set* keywords. For the *ratio* keyword only the specified
|
||||
fraction of them (0 <= *frac* <= 1) will be assigned particles. For
|
||||
the *subset* keyword only the specified *Nsubset* of them will be
|
||||
assigned particles. In both cases the assigned lattice sites are
|
||||
chosen randomly. An iterative algorithm is used which insures the
|
||||
correct number of particles are inserted, in a perfectly random
|
||||
fashion. Which lattice sites are selected will change with the number
|
||||
of processors used.
|
||||
|
||||
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
|
||||
|
|
|
@ -14,7 +14,7 @@ Syntax
|
|||
* style = *atom* or *type* or *mol* or *group* or *region*
|
||||
* ID = atom ID range or type range or mol ID range or group ID or region ID
|
||||
* one or more keyword/value pairs may be appended
|
||||
* keyword = *type* or *type/fraction* or *mol* or *x* or *y* or *z* or *charge* or *dipole* or *dipole/random* or *quat* or *spin* or *spin/random* or *quat* or *quat/random* or *diameter* or *shape* or *length* or *tri* or *theta* or *theta/random* or *angmom* or *omega* or *mass* or *density* or *density/disc* or *volume* or *image* or *bond* or *angle* or *dihedral* or *improper* or *meso/e* or *meso/cv* or *meso/rho* or *smd/contact/radius* or *smd/mass/density* or *dpd/theta* or *edpd/temp* or *edpd/cv* or *cc* or *i\_name* or *d\_name*
|
||||
* keyword = *type* or *type/fraction* or *type/ratio* or *type/subset* or *mol* or *x* or *y* or *z* or *charge* or *dipole* or *dipole/random* or *quat* or *spin* or *spin/random* or *quat* or *quat/random* or *diameter* or *shape* or *length* or *tri* or *theta* or *theta/random* or *angmom* or *omega* or *mass* or *density* or *density/disc* or *volume* or *image* or *bond* or *angle* or *dihedral* or *improper* or *meso/e* or *meso/cv* or *meso/rho* or *smd/contact/radius* or *smd/mass/density* or *dpd/theta* or *edpd/temp* or *edpd/cv* or *cc* or *i\_name* or *d\_name*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
@ -22,7 +22,15 @@ Syntax
|
|||
value can be an atom-style variable (see below)
|
||||
*type/fraction* values = type fraction seed
|
||||
type = new atom type
|
||||
fraction = fraction of selected atoms to set to new atom type
|
||||
fraction = approximate fraction of selected atoms to set to new atom type
|
||||
seed = random # seed (positive integer)
|
||||
*type/ratio* values = type fraction seed
|
||||
type = new atom type
|
||||
fraction = exact fraction of selected atoms to set to new atom type
|
||||
seed = random # seed (positive integer)
|
||||
*type/subset* values = type Nsubset seed
|
||||
type = new atom type
|
||||
Nsubset = exact number of selected atoms to set to new atom type
|
||||
seed = random # seed (positive integer)
|
||||
*mol* value = molecule ID
|
||||
value can be an atom-style variable (see below)
|
||||
|
@ -184,15 +192,16 @@ This 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 <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.
|
||||
keywords allow an :doc:`atom-style or atomfile-style variable
|
||||
<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 <thermo_style>` command
|
||||
|
@ -220,23 +229,36 @@ command.
|
|||
|
||||
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 requested fraction, 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.
|
||||
to be exactly the specified fraction (0 <= *fraction* <= 1), but
|
||||
should be statistically close. Random numbers are used in such a way
|
||||
that a particular atom is changed or not changed, regardless of how
|
||||
many processors are being used. This keyword does not allow use of an
|
||||
atom-style variable.
|
||||
|
||||
Keyword *mol* sets the molecule ID for all selected atoms. The :doc:`atom style <atom_style>` being used must support the use of molecule
|
||||
IDs.
|
||||
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 insures 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.
|
||||
|
||||
Keywords *x*\ , *y*\ , *z*\ , and *charge* set the coordinates or charge of
|
||||
all selected atoms. For *charge*\ , the :doc:`atom style <atom_style>`
|
||||
being used must support the use of atomic charge. Keywords *vx*\ , *vy*\ ,
|
||||
and *vz* set the velocities of all selected atoms.
|
||||
Keyword *mol* sets the molecule ID for all selected atoms. The
|
||||
:doc:`atom style <atom_style>` being used must support the use of
|
||||
molecule IDs.
|
||||
|
||||
Keywords *x*\ , *y*\ , *z*\ , and *charge* set the coordinates or
|
||||
charge of all selected atoms. For *charge*\ , the :doc:`atom style
|
||||
<atom_style>` being used must support the use of atomic
|
||||
charge. Keywords *vx*\ , *vy*\ , and *vz* set the velocities of all
|
||||
selected atoms.
|
||||
|
||||
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.
|
||||
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
|
||||
|
|
|
@ -1,334 +0,0 @@
|
|||
"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
|
||||
|
||||
:link(lws,http://lammps.sandia.gov)
|
||||
:link(ld,Manual.html)
|
||||
:link(lc,Commands_all.html)
|
||||
|
||||
:line
|
||||
|
||||
create_atoms command :h3
|
||||
|
||||
[Syntax:]
|
||||
|
||||
create_atoms type style args keyword values ... :pre
|
||||
|
||||
type = atom type (1-Ntypes) of atoms to create (offset for molecule creation) :ulb,l
|
||||
style = {box} or {region} or {single} or {random} :l
|
||||
{box} args = none
|
||||
{region} args = region-ID
|
||||
region-ID = particles will only be created if contained in the region
|
||||
{single} args = x y z
|
||||
x,y,z = coordinates of a single particle (distance units)
|
||||
{random} args = N seed region-ID
|
||||
N = number of particles to create
|
||||
seed = random # seed (positive integer)
|
||||
region-ID = create atoms within this region, use NULL for entire simulation box :pre
|
||||
zero or more keyword/value pairs may be appended :l
|
||||
keyword = {mol} or {basis} or {remap} or {var} or {set} or {units} :l
|
||||
{mol} value = template-ID seed
|
||||
template-ID = ID of molecule template specified in a separate "molecule"_molecule.html command
|
||||
seed = random # seed (positive integer)
|
||||
{basis} values = M itype
|
||||
M = which basis atom
|
||||
itype = atom type (1-N) to assign to this basis atom
|
||||
{remap} value = {yes} or {no}
|
||||
{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
|
||||
{rotate} values = theta Rx Ry Rz
|
||||
theta = rotation angle for single molecule (degrees)
|
||||
Rx,Ry,Rz = rotation vector for single molecule
|
||||
{units} value = {lattice} or {box}
|
||||
{lattice} = the geometry is defined in lattice units
|
||||
{box} = the geometry is defined in simulation box units :pre
|
||||
:ule
|
||||
|
||||
[Examples:]
|
||||
|
||||
create_atoms 1 box
|
||||
create_atoms 3 region regsphere basis 2 3
|
||||
create_atoms 3 single 0 0 5
|
||||
create_atoms 1 box var v set x xpos set y ypos :pre
|
||||
|
||||
[Description:]
|
||||
|
||||
This command creates atoms (or molecules) on a lattice, or a single
|
||||
atom (or molecule), or a random collection of atoms (or molecules), as
|
||||
an alternative to reading in their coordinates explicitly via a
|
||||
"read_data"_read_data.html or "read_restart"_read_restart.html
|
||||
command. A simulation box must already exist, which is typically
|
||||
created via the "create_box"_create_box.html command. Before using
|
||||
this command, a lattice must also be defined using the
|
||||
"lattice"_lattice.html command, unless you specify the {single} style
|
||||
with units = box or the {random} style. For the remainder of this doc
|
||||
page, a created atom or molecule is referred to as a "particle".
|
||||
|
||||
If created particles are individual atoms, they are assigned the
|
||||
specified atom {type}, though this can be altered via the {basis}
|
||||
keyword as discussed below. If molecules are being created, the type
|
||||
of each atom in the created molecule is specified in the file read by
|
||||
the "molecule"_molecule.html command, and those values are added to
|
||||
the specified atom {type}. E.g. if {type} = 2, and the file specifies
|
||||
atom types 1,2,3, then each created molecule will have atom types
|
||||
3,4,5.
|
||||
|
||||
For the {box} style, the create_atoms command fills the entire
|
||||
simulation box with particles on the lattice. If your simulation box
|
||||
is periodic, you should insure its size is a multiple of the lattice
|
||||
spacings, to avoid unwanted atom overlaps at the box boundaries. If
|
||||
your box is periodic and a multiple of the lattice spacing in a
|
||||
particular dimension, LAMMPS is careful to put exactly one particle at
|
||||
the boundary (on either side of the box), not zero or two.
|
||||
|
||||
For the {region} style, a geometric volume is filled with particles on
|
||||
the lattice. This volume what is inside the simulation box and is
|
||||
also consistent with the region volume. See the "region"_region.html
|
||||
command for details. Note that a region can be specified so that its
|
||||
"volume" is either inside or outside a geometric boundary. Also note
|
||||
that if your region is the same size as a periodic simulation box (in
|
||||
some dimension), LAMMPS does not implement the same logic described
|
||||
above as for the {box} style, to insure exactly one particle at
|
||||
periodic boundaries. if this is what you desire, you should either
|
||||
use the {box} style, or tweak the region size to get precisely the
|
||||
particles you want.
|
||||
|
||||
For the {single} style, a single particle is added to the system at
|
||||
the specified coordinates. This can be useful for debugging purposes
|
||||
or to create a tiny system with a handful of particles at specified
|
||||
positions.
|
||||
|
||||
For the {random} style, N particles are added to the system at
|
||||
randomly generated coordinates, which can be useful for generating an
|
||||
amorphous system. The particles are created one by one using the
|
||||
specified random number {seed}, resulting in the same set of particles
|
||||
coordinates, independent of how many processors are being used in the
|
||||
simulation. If the {region-ID} argument is specified as NULL, then
|
||||
the created particles will be anywhere in the simulation box. If a
|
||||
{region-ID} is specified, a geometric volume is filled which is both
|
||||
inside the simulation box and is also consistent with the region
|
||||
volume. See the "region"_region.html command for details. Note that
|
||||
a region can be specified so that its "volume" is either inside or
|
||||
outside a geometric boundary.
|
||||
|
||||
NOTE: Particles generated by the {random} style will typically be
|
||||
highly overlapped which will cause many interatomic potentials to
|
||||
compute large energies and forces. Thus you should either perform an
|
||||
"energy minimization"_minimize.html or run dynamics with "fix
|
||||
nve/limit"_fix_nve_limit.html to equilibrate such a system, before
|
||||
running normal dynamics.
|
||||
|
||||
Note that this command adds particles to those that already exist.
|
||||
This means it can be used to add particles to a system previously read
|
||||
in from a data or restart file. Or the create_atoms command can be
|
||||
used multiple times, to add multiple sets of particles to the
|
||||
simulation. For example, grain boundaries can be created, by
|
||||
interleaving create_atoms with "lattice"_lattice.html commands
|
||||
specifying different orientations. By using the create_atoms command
|
||||
in conjunction with the "delete_atoms"_delete_atoms.html command,
|
||||
reasonably complex geometries can be created, or a protein can be
|
||||
solvated with a surrounding box of water molecules.
|
||||
|
||||
In all these cases, care should be taken to insure that new atoms do
|
||||
not overlap existing atoms inappropriately, especially if molecules
|
||||
are being added. The "delete_atoms"_delete_atoms.html command can be
|
||||
used to remove overlapping atoms or molecules.
|
||||
|
||||
NOTE: You cannot use any of the styles explained above to create atoms
|
||||
that are outside the simulation box; they will just be ignored by
|
||||
LAMMPS. This is true even if you are using shrink-wrapped box
|
||||
boundaries, as specified by the "boundary"_boundary.html command.
|
||||
However, you can first use the "change_box"_change_box.html command to
|
||||
temporarily expand the box, then add atoms via create_atoms, then
|
||||
finally use change_box command again if needed to re-shrink-wrap the
|
||||
new atoms. See the "change_box"_change_box.html doc page for an
|
||||
example of how to do this, using the create_atoms {single} style to
|
||||
insert a new atom outside the current simulation box.
|
||||
|
||||
:line
|
||||
|
||||
Individual atoms are inserted by this command, unless the {mol}
|
||||
keyword is used. It specifies a {template-ID} previously defined
|
||||
using the "molecule"_molecule.html command, which reads a file that
|
||||
defines the molecule. The coordinates, atom types, charges, etc, as
|
||||
well as any bond/angle/etc and special neighbor information for the
|
||||
molecule can be specified in the molecule file. See the
|
||||
"molecule"_molecule.html command for details. The only settings
|
||||
required to be in this file are the coordinates and types of atoms in
|
||||
the molecule.
|
||||
|
||||
Using a lattice to add molecules, e.g. via the {box} or {region} or
|
||||
{single} styles, is exactly the same as adding atoms on lattice
|
||||
points, except that entire molecules are added at each point, i.e. on
|
||||
the point defined by each basis atom in the unit cell as it tiles the
|
||||
simulation box or region. This is done by placing the geometric
|
||||
center of the molecule at the lattice point, and giving the molecule a
|
||||
random orientation about the point. The random {seed} specified with
|
||||
the {mol} keyword is used for this operation, and the random numbers
|
||||
generated by each processor are different. This means the coordinates
|
||||
of individual atoms (in the molecules) will be different when running
|
||||
on different numbers of processors, unlike when atoms are being
|
||||
created in parallel.
|
||||
|
||||
Also note that because of the random rotations, it may be important to
|
||||
use a lattice with a large enough spacing that adjacent molecules will
|
||||
not overlap, regardless of their relative orientations.
|
||||
|
||||
NOTE: If the "create_box"_create_box.html command is used to create
|
||||
the simulation box, followed by the create_atoms command with its
|
||||
{mol} option for adding molecules, then you typically need to use the
|
||||
optional keywords allowed by the "create_box"_create_box.html command
|
||||
for extra bonds (angles,etc) or extra special neighbors. This is
|
||||
because by default, the "create_box"_create_box.html command sets up a
|
||||
non-molecular system which doesn't allow molecules to be added.
|
||||
|
||||
:line
|
||||
|
||||
This is the meaning of the other allowed keywords.
|
||||
|
||||
The {basis} keyword is only used when atoms (not molecules) are being
|
||||
created. It specifies an atom type that will be assigned to specific
|
||||
basis atoms as they are created. See the "lattice"_lattice.html
|
||||
command for specifics on how basis atoms are defined for the unit cell
|
||||
of the lattice. By default, all created atoms are assigned the
|
||||
argument {type} as their atom type.
|
||||
|
||||
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
|
||||
dimensions are periodic. If it is set to {no}, no remapping is done
|
||||
and no particle is created if its position is outside the box.
|
||||
|
||||
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 "equal-style variable"_variable.html which
|
||||
should evaluate to a zero or non-zero value based on one or two or
|
||||
three variables which will store the x, y, or z coordinates of an atom
|
||||
(one variable per coordinate). If used, these other variables must be
|
||||
"internal-style variables"_variable.html 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 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.
|
||||
|
||||
As an example, these commands can be used in a 2d simulation, to
|
||||
create a sinusoidal surface. Note that the surface is "rough" due to
|
||||
individual lattice points being "above" or "below" the mathematical
|
||||
expression for the sinusoidal curve. If a finer lattice were used,
|
||||
the sinusoid would appear to be "smoother". Also note the use of the
|
||||
"xlat" and "ylat" "thermo_style"_thermo_style.html keywords which
|
||||
converts lattice spacings to distance. Click on the image for a
|
||||
larger version.
|
||||
|
||||
dimension 2
|
||||
variable x equal 100
|
||||
variable y equal 25
|
||||
lattice hex 0.8442
|
||||
region box block 0 $x 0 $y -0.5 0.5
|
||||
create_box 1 box :pre
|
||||
|
||||
variable xx internal 0.0
|
||||
variable yy internal 0.0
|
||||
variable v equal "(0.2*v_y*ylat * cos(v_xx/xlat * 2.0*PI*4.0/v_x) + 0.5*v_y*ylat - v_yy) > 0.0"
|
||||
create_atoms 1 box var v set x xx set y yy
|
||||
write_dump all atom sinusoid.lammpstrj :pre
|
||||
|
||||
:c,image(JPG/sinusoid_small.jpg,JPG/sinusoid.jpg)
|
||||
|
||||
The {rotate} keyword allows specification of the orientation
|
||||
at which molecules are inserted. The axis of rotation is
|
||||
determined by the rotation vector (Rx,Ry,Rz) that goes through the
|
||||
insertion point. The specified {theta} determines the angle of
|
||||
rotation around that axis. Note that the direction of rotation for
|
||||
the atoms around the rotation axis is consistent with the right-hand
|
||||
rule: if your right-hand's thumb points along {R}, then your fingers
|
||||
wrap around the axis in the direction of rotation.
|
||||
|
||||
The {units} keyword determines the meaning of the distance units used
|
||||
to specify the coordinates of the one particle created by the {single}
|
||||
style. A {box} value selects standard distance units as defined by
|
||||
the "units"_units.html command, e.g. Angstroms for units = real or
|
||||
metal. A {lattice} value means the distance units are in lattice
|
||||
spacings.
|
||||
|
||||
:line
|
||||
|
||||
Atom IDs are assigned to created atoms in the following way. The
|
||||
collection of created atoms are assigned consecutive IDs that start
|
||||
immediately following the largest atom ID existing before the
|
||||
create_atoms command was invoked. This is done by the processor's
|
||||
communicating the number of atoms they each own, the first processor
|
||||
numbering its atoms from 1 to N1, the second processor from N1+1 to
|
||||
N2, etc. Where N1 = number of atoms owned by the first processor, N2
|
||||
= number owned by the second processor, etc. Thus when the same
|
||||
simulation is performed on different numbers of processors, there is
|
||||
no guarantee a particular created atom will be assigned the same ID in
|
||||
both simulations. If molecules are being created, molecule IDs are
|
||||
assigned to created molecules in a similar fashion.
|
||||
|
||||
Aside from their ID, atom type, and xyz position, other properties of
|
||||
created atoms are set to default values, depending on which quantities
|
||||
are defined by the chosen "atom style"_atom_style.html. See the "atom
|
||||
style"_atom_style.html command for more details. See the
|
||||
"set"_set.html and "velocity"_velocity.html commands for info on how
|
||||
to change these values.
|
||||
|
||||
charge = 0.0
|
||||
dipole moment magnitude = 0.0
|
||||
diameter = 1.0
|
||||
shape = 0.0 0.0 0.0
|
||||
density = 1.0
|
||||
volume = 1.0
|
||||
velocity = 0.0 0.0 0.0
|
||||
angular velocity = 0.0 0.0 0.0
|
||||
angular momentum = 0.0 0.0 0.0
|
||||
quaternion = (1,0,0,0)
|
||||
bonds, angles, dihedrals, impropers = none :ul
|
||||
|
||||
If molecules are being created, these defaults can be overridden by
|
||||
values specified in the file read by the "molecule"_molecule.html
|
||||
command. E.g. the file typically defines bonds (angles,etc) between
|
||||
atoms in the molecule, and can optionally define charges on each atom.
|
||||
|
||||
Note that the {sphere} atom style sets the default particle diameter
|
||||
to 1.0 as well as the density. This means the mass for the particle
|
||||
is not 1.0, but is PI/6 * diameter^3 = 0.5236.
|
||||
|
||||
Note that the {ellipsoid} atom style sets the default particle shape
|
||||
to (0.0 0.0 0.0) and the density to 1.0 which means it is a point
|
||||
particle, not an ellipsoid, and has a mass of 1.0.
|
||||
|
||||
Note that the {peri} style sets the default volume and density to 1.0
|
||||
and thus also set the mass for the particle to 1.0.
|
||||
|
||||
The "set"_set.html command can be used to override many of these
|
||||
default settings.
|
||||
|
||||
:line
|
||||
|
||||
[Restrictions:]
|
||||
|
||||
An "atom_style"_atom_style.html must be previously defined to use this
|
||||
command.
|
||||
|
||||
A rotation vector specified for a single molecule must be in
|
||||
the z-direction for a 2d model.
|
||||
|
||||
[Related commands:]
|
||||
|
||||
"lattice"_lattice.html, "region"_region.html, "create_box"_create_box.html,
|
||||
"read_data"_read_data.html, "read_restart"_read_restart.html
|
||||
|
||||
[Default:]
|
||||
|
||||
The default for the {basis} keyword is that all created atoms are
|
||||
assigned the argument {type} as their atom type (when single atoms are
|
||||
being created). The other defaults are {remap} = no, {rotate} =
|
||||
random, and {units} = lattice.
|
|
@ -19,6 +19,8 @@
|
|||
#include "error.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "comm.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define DELTA 16384
|
||||
|
@ -108,6 +110,19 @@ int AtomVec::grow_nmax_bonus(int nmax_bonus)
|
|||
return nmax_bonus;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
roundup N so it is a multiple of DELTA
|
||||
error if N exceeds 32-bit int, since will be used as arg to grow()
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
bigint AtomVec::roundup(bigint n)
|
||||
{
|
||||
if (n % DELTA) n = n/DELTA * DELTA + DELTA;
|
||||
if (n > MAXSMALLINT)
|
||||
error->one(FLERR,"Too many atoms created on one or more procs");
|
||||
return n;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
unpack one line from Velocities section of data file
|
||||
------------------------------------------------------------------------- */
|
||||
|
|
|
@ -57,6 +57,7 @@ class AtomVec : protected Pointers {
|
|||
|
||||
virtual void grow(int) = 0;
|
||||
virtual void grow_reset() = 0;
|
||||
bigint roundup(bigint);
|
||||
virtual void copy(int, int, int) = 0;
|
||||
virtual void clear_bonus() {}
|
||||
virtual void force_clear(int, size_t) {}
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author (ratio and subset) : Jake Gissinger (U Colorado)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "create_atoms.h"
|
||||
#include <mpi.h>
|
||||
#include <cstring>
|
||||
|
@ -32,15 +36,19 @@
|
|||
#include "math_extra.h"
|
||||
#include "math_const.h"
|
||||
#include "error.h"
|
||||
#include "memory.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define BIG 1.0e30
|
||||
#define EPSILON 1.0e-6
|
||||
#define LB_FACTOR 1.1
|
||||
|
||||
enum{BOX,REGION,SINGLE,RANDOM};
|
||||
enum{ATOM,MOLECULE};
|
||||
enum{COUNT,INSERT,INSERT_SELECTED};
|
||||
enum{NONE,RATIO,SUBSET};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
@ -50,6 +58,9 @@ CreateAtoms::CreateAtoms(LAMMPS *lmp) : Pointers(lmp) {}
|
|||
|
||||
void CreateAtoms::command(int narg, char **arg)
|
||||
{
|
||||
MPI_Comm_rank(world,&me);
|
||||
MPI_Comm_size(world,&nprocs);
|
||||
|
||||
if (domain->box_exist == 0)
|
||||
error->all(FLERR,"Create_atoms command before simulation box is defined");
|
||||
if (modify->nfix_restart_peratom)
|
||||
|
@ -107,6 +118,8 @@ void CreateAtoms::command(int narg, char **arg)
|
|||
varflag = 0;
|
||||
vstr = xstr = ystr = zstr = NULL;
|
||||
quatone[0] = quatone[1] = quatone[2] = 0.0;
|
||||
subsetflag = NONE;
|
||||
int subsetseed;
|
||||
|
||||
nbasis = domain->lattice->nbasis;
|
||||
basistype = new int[nbasis];
|
||||
|
@ -132,7 +145,7 @@ void CreateAtoms::command(int narg, char **arg)
|
|||
int imol = atom->find_molecule(arg[iarg+1]);
|
||||
if (imol == -1) error->all(FLERR,"Molecule template ID for "
|
||||
"create_atoms does not exist");
|
||||
if (atom->molecules[imol]->nset > 1 && comm->me == 0)
|
||||
if (atom->molecules[imol]->nset > 1 && me == 0)
|
||||
error->warning(FLERR,"Molecule template for "
|
||||
"create_atoms has multiple molecules");
|
||||
mode = MOLECULE;
|
||||
|
@ -187,6 +200,22 @@ void CreateAtoms::command(int narg, char **arg)
|
|||
MathExtra::norm3(axisone);
|
||||
MathExtra::axisangle_to_quat(axisone,thetaone,quatone);
|
||||
iarg += 5;
|
||||
} else if (strcmp(arg[iarg],"ratio") == 0) {
|
||||
if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command");
|
||||
subsetflag = RATIO;
|
||||
subsetfrac = force->numeric(FLERR,arg[iarg+1]);
|
||||
subsetseed = force->inumeric(FLERR,arg[iarg+2]);
|
||||
if (subsetfrac <= 0.0 || subsetfrac > 1.0 || subsetseed <= 0)
|
||||
error->all(FLERR,"Illegal create_atoms command");
|
||||
iarg += 3;
|
||||
} else if (strcmp(arg[iarg],"subset") == 0) {
|
||||
if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command");
|
||||
subsetflag = SUBSET;
|
||||
nsubset = force->bnumeric(FLERR,arg[iarg+1]);
|
||||
subsetseed = force->inumeric(FLERR,arg[iarg+2]);
|
||||
if (nsubset <= 0 || subsetseed <= 0)
|
||||
error->all(FLERR,"Illegal create_atoms command");
|
||||
iarg += 3;
|
||||
} else error->all(FLERR,"Illegal create_atoms command");
|
||||
}
|
||||
|
||||
|
@ -221,9 +250,12 @@ void CreateAtoms::command(int narg, char **arg)
|
|||
|
||||
// molecule random number generator, different for each proc
|
||||
|
||||
ranmol = new RanMars(lmp,molseed+comm->me);
|
||||
ranmol = new RanMars(lmp,molseed+me);
|
||||
}
|
||||
|
||||
ranlatt = NULL;
|
||||
if (subsetflag != NONE) ranlatt = new RanMars(lmp,subsetseed+me);
|
||||
|
||||
// error check and further setup for variable test
|
||||
|
||||
if (!vstr && (xstr || ystr || zstr))
|
||||
|
@ -512,6 +544,8 @@ void CreateAtoms::command(int narg, char **arg)
|
|||
// clean up
|
||||
|
||||
delete ranmol;
|
||||
delete ranlatt;
|
||||
|
||||
if (domain->lattice) delete [] basistype;
|
||||
delete [] vstr;
|
||||
delete [] xstr;
|
||||
|
@ -536,7 +570,7 @@ void CreateAtoms::command(int narg, char **arg)
|
|||
MPI_Barrier(world);
|
||||
double time2 = MPI_Wtime();
|
||||
|
||||
if (comm->me == 0) {
|
||||
if (me == 0) {
|
||||
if (screen) {
|
||||
fprintf(screen,"Created " BIGINT_FORMAT " atoms\n",
|
||||
atom->natoms-natoms_previous);
|
||||
|
@ -757,7 +791,6 @@ void CreateAtoms::add_lattice()
|
|||
// which can lead to missing atoms in rare cases
|
||||
// extra decrement of lo if min < 0, since static_cast(-1.5) = -1
|
||||
|
||||
int ilo,ihi,jlo,jhi,klo,khi;
|
||||
ilo = static_cast<int> (xmin) - 1;
|
||||
jlo = static_cast<int> (ymin) - 1;
|
||||
klo = static_cast<int> (zmin) - 1;
|
||||
|
@ -769,14 +802,73 @@ void CreateAtoms::add_lattice()
|
|||
if (ymin < 0.0) jlo--;
|
||||
if (zmin < 0.0) klo--;
|
||||
|
||||
// iterate on 3d periodic lattice of unit cells using loop bounds
|
||||
// iterate on nbasis atoms in each unit cell
|
||||
// convert lattice coords to box coords
|
||||
// add atom or molecule (on each basis point) if it meets all criteria
|
||||
// count lattice sites on each proc
|
||||
|
||||
nlatt_overflow = 0;
|
||||
loop_lattice(COUNT);
|
||||
|
||||
// nadd = # of atoms each proc will insert (estimated if subsetflag)
|
||||
|
||||
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");
|
||||
|
||||
bigint nadd;
|
||||
|
||||
if (subsetflag == NONE) {
|
||||
if (nprocs == 1) nadd = nlatt;
|
||||
else nadd = static_cast<bigint> (LB_FACTOR * nlatt);
|
||||
} else {
|
||||
bigint bnlatt = nlatt;
|
||||
bigint bnlattall;
|
||||
MPI_Allreduce(&bnlatt,&bnlattall,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
||||
if (subsetflag == RATIO)
|
||||
nsubset = static_cast<bigint> (subsetfrac * bnlattall);
|
||||
if (nsubset > bnlattall)
|
||||
error->all(FLERR,"Create_atoms subset size > # of lattice sites");
|
||||
if (nprocs == 1) nadd = nsubset;
|
||||
else nadd = static_cast<bigint> (LB_FACTOR * nsubset/bnlattall * nlatt);
|
||||
}
|
||||
|
||||
// allocate atom arrays to size N, rounded up by AtomVec->DELTA
|
||||
|
||||
bigint nbig = atom->avec->roundup(nadd + atom->nlocal);
|
||||
int n = static_cast<int> (nbig);
|
||||
atom->avec->grow(n);
|
||||
|
||||
// add atoms or molecules
|
||||
// if no subset: add to all lattice sites
|
||||
// if subset: count lattice sites, select random subset, then add
|
||||
|
||||
if (subsetflag == NONE) loop_lattice(INSERT);
|
||||
else {
|
||||
memory->create(flag,nlatt,"create_atoms:flag");
|
||||
memory->create(next,nlatt,"create_atoms:next");
|
||||
ranlatt->select_subset(nsubset,nlatt,flag,next);
|
||||
loop_lattice(INSERT_SELECTED);
|
||||
memory->destroy(flag);
|
||||
memory->destroy(next);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
iterate on 3d periodic lattice of unit cells using loop bounds
|
||||
iterate on nbasis atoms in each unit cell
|
||||
convert lattice coords to box coords
|
||||
check if lattice point meets all criteria to be added
|
||||
perform action on atom or molecule (on each basis point) if meets all criteria
|
||||
actions = add, count, add if flagged
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void CreateAtoms::loop_lattice(int action)
|
||||
{
|
||||
int i,j,k,m;
|
||||
|
||||
const double * const * const basis = domain->lattice->basis;
|
||||
|
||||
int i,j,k,m;
|
||||
nlatt = 0;
|
||||
|
||||
for (k = klo; k <= khi; k++) {
|
||||
for (j = jlo; j <= jhi; j++) {
|
||||
for (i = ilo; i <= ihi; i++) {
|
||||
|
@ -812,19 +904,31 @@ void CreateAtoms::add_lattice()
|
|||
coord[1] < sublo[1] || coord[1] >= subhi[1] ||
|
||||
coord[2] < sublo[2] || coord[2] >= subhi[2]) continue;
|
||||
|
||||
// add the atom or entire molecule to my list of atoms
|
||||
// this proc owns the lattice site
|
||||
// perform action: add, just count, add if flagged
|
||||
// add = add an atom or entire molecule to my list of atoms
|
||||
|
||||
if (mode == ATOM) atom->avec->create_atom(basistype[m],x);
|
||||
else if (quatone[0] == 0 && quatone[1] == 0 && quatone[2] == 0)
|
||||
add_molecule(x);
|
||||
else add_molecule(x,quatone);
|
||||
if (action == INSERT) {
|
||||
if (mode == ATOM) atom->avec->create_atom(basistype[m],x);
|
||||
else if (quatone[0] == 0 && quatone[1] == 0 && quatone[2] == 0)
|
||||
add_molecule(x);
|
||||
else add_molecule(x,quatone);
|
||||
} else if (action == COUNT) {
|
||||
if (nlatt == MAXSMALLINT) nlatt_overflow = 1;
|
||||
} else if (action == INSERT_SELECTED && flag[nlatt]) {
|
||||
if (mode == ATOM) atom->avec->create_atom(basistype[m],x);
|
||||
else if (quatone[0] == 0 && quatone[1] == 0 && quatone[2] == 0)
|
||||
add_molecule(x);
|
||||
else add_molecule(x,quatone);
|
||||
}
|
||||
|
||||
nlatt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
add a randomly rotated molecule with its center at center
|
||||
if quat_user set, perform requested rotation
|
||||
|
|
|
@ -30,17 +30,30 @@ class CreateAtoms : protected Pointers {
|
|||
void command(int, char **);
|
||||
|
||||
private:
|
||||
int me,nprocs;
|
||||
int ntype,style,mode,nregion,nbasis,nrandom,seed;
|
||||
int remapflag;
|
||||
int subsetflag;
|
||||
bigint nsubset;
|
||||
double subsetfrac;
|
||||
int *basistype;
|
||||
double xone[3],quatone[4];
|
||||
int remapflag;
|
||||
|
||||
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;
|
||||
|
||||
int nlatt; // number of owned lattice sites
|
||||
int nlatt_overflow; // 1 if local nlatt exceeds a 32-bit int
|
||||
|
||||
int *flag; // flag subset of particles to insert on lattice
|
||||
int *next;
|
||||
|
||||
class Molecule *onemol;
|
||||
class RanMars *ranmol;
|
||||
class RanMars *ranlatt;
|
||||
|
||||
int triclinic;
|
||||
double sublo[3],subhi[3]; // epsilon-extended proc sub-box for adding atoms
|
||||
|
@ -48,8 +61,9 @@ class CreateAtoms : protected Pointers {
|
|||
void add_single();
|
||||
void add_random();
|
||||
void add_lattice();
|
||||
void loop_lattice(int);
|
||||
void add_molecule(double *, double * = NULL);
|
||||
int vartest(double *); // evaluate a variable with new atom position
|
||||
int vartest(double *); // evaluate a variable with new atom position
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -152,4 +166,12 @@ E: No overlap of box and region for create_atoms
|
|||
|
||||
Self-explanatory.
|
||||
|
||||
E: Attempting to insert more particles than available lattice points
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
W: Specifying an 'subset' value of '0' is equivalent to no 'subset' keyword
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
*/
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
enum{ADD,SUBTRACT};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
RanMars::RanMars(LAMMPS *lmp, int seed) : Pointers(lmp),
|
||||
|
@ -149,7 +151,7 @@ double RanMars::besselexp(double theta, double alpha, double cp)
|
|||
{
|
||||
double first,v1,v2;
|
||||
|
||||
if (theta < 0.0 || alpha < 0.0 || alpha > 1.0)
|
||||
if (theta < 0.0 || alpha < 0.0 || alpha < 1.0)
|
||||
error->all(FLERR,"Invalid Bessel exponential distribution parameters");
|
||||
|
||||
v1 = uniform();
|
||||
|
@ -166,3 +168,131 @@ double RanMars::besselexp(double theta, double alpha, double cp)
|
|||
|
||||
return first;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
select random subset of size Ntarget out of Ntotal items
|
||||
Ntotal = sum of Nmine across all procs
|
||||
mark,next = vectors of length Nmine
|
||||
return mark = 0 for unselected item, 1 for selected item
|
||||
next = work vector used to store linked lists for 2 active sets of items
|
||||
IMPORTANT: this method must be called simultaneously by all procs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void RanMars::select_subset(bigint ntarget, int nmine, int *mark, int *next)
|
||||
{
|
||||
int mode,index,oldindex,newvalue,nflip,which,niter;
|
||||
int active[2],first[2],last[2];
|
||||
int newactive[2],newfirst[2],newlast[2];
|
||||
bigint nmark,nactive,nactiveall,nflipall,bnflip;
|
||||
bigint activeall[2],bsum[3],bsumall[3];
|
||||
double thresh;
|
||||
|
||||
active[0] = nmine;
|
||||
active[1] = 0;
|
||||
first[0] = 0;
|
||||
first[1] = -1;
|
||||
last[0] = nmine-1;
|
||||
last[1] = -1;
|
||||
|
||||
bigint bnmine = nmine;
|
||||
bigint bnall;
|
||||
MPI_Allreduce(&bnmine,&bnall,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
||||
activeall[0] = bnall;
|
||||
|
||||
for (int i = 0; i < nmine; i++) mark[i] = 0;
|
||||
for (int i = 0; i < nmine; i++) next[i] = i+1;
|
||||
next[nmine-1] = -1;
|
||||
|
||||
nmark = 0;
|
||||
niter = 0;
|
||||
|
||||
while (nmark != ntarget) {
|
||||
|
||||
// choose to ADD or SUBTRACT from current nmark
|
||||
// thresh = desired flips / size of active set
|
||||
// nactive = size of current active set, only for debug output below
|
||||
|
||||
if (ntarget-nmark > 0) {
|
||||
mode = ADD;
|
||||
// nactive = active[mode];
|
||||
thresh = 1.0 * (ntarget-nmark) / activeall[mode];
|
||||
} else {
|
||||
mode = SUBTRACT;
|
||||
// nactive = active[mode];
|
||||
thresh = 1.0 * (nmark-ntarget) / activeall[mode];
|
||||
}
|
||||
|
||||
// bound thresh for RNG accuracy
|
||||
|
||||
thresh = MAX(thresh,0.01);
|
||||
thresh = MIN(thresh,0.99);
|
||||
|
||||
// new empty active sets for next iteration
|
||||
|
||||
newactive[0] = newactive[1] = 0;
|
||||
newfirst[0] = newfirst[1] = -1;
|
||||
newlast[0] = newlast[1] = -1;
|
||||
|
||||
// index = first value in ADD or SUBTRACT set
|
||||
|
||||
if (mode == ADD) newvalue = 1;
|
||||
else if (mode == SUBTRACT) newvalue = 0;
|
||||
index = first[mode];
|
||||
|
||||
// flip marks from 0 -> 1 (ADD) or 1 -> 0 (SUBTRACT)
|
||||
// loop over active set via next vector = linked list
|
||||
// flip each value based on RN < thresh
|
||||
|
||||
nflip = 0;
|
||||
while (index >= 0) {
|
||||
if (uniform() < thresh) {
|
||||
mark[index] = newvalue;
|
||||
nflip++;
|
||||
}
|
||||
oldindex = index;
|
||||
index = next[index];
|
||||
|
||||
// oldindex can now be appended to a new active set
|
||||
// which = which of two new active sets to append to
|
||||
|
||||
which = mark[oldindex];
|
||||
newactive[which]++;
|
||||
if (newfirst[which] < 0) newfirst[which] = oldindex;
|
||||
if (newlast[which] >= 0) next[newlast[which]] = oldindex;
|
||||
newlast[which] = oldindex;
|
||||
next[oldindex] = -1;
|
||||
|
||||
// set active sets for next iteration to the new ones
|
||||
// next vector is already updated
|
||||
|
||||
active[0] = newactive[0];
|
||||
active[1] = newactive[1];
|
||||
first[0] = newfirst[0];
|
||||
first[1] = newfirst[1];
|
||||
last[0] = newlast[0];
|
||||
last[1] = newlast[1];
|
||||
}
|
||||
|
||||
// update nmark and activeall
|
||||
|
||||
bsum[0] = nflip;
|
||||
bsum[1] = active[0];
|
||||
bsum[2] = active[1];
|
||||
bsum[3] = nactive;
|
||||
MPI_Allreduce(&bsum,&bsumall,4,MPI_LMP_BIGINT,MPI_SUM,world);
|
||||
nflipall = bsumall[0];
|
||||
activeall[0] = bsumall[1];
|
||||
activeall[1] = bsumall[2];
|
||||
nactiveall = bsumall[3];
|
||||
|
||||
if (mode == ADD) nmark += nflipall;
|
||||
else if (mode == SUBTRACT) nmark -= nflipall;
|
||||
|
||||
niter++;
|
||||
|
||||
// DEBUG output of stats
|
||||
|
||||
//if (comm->me == 0) printf("%d %ld %ld %g %ld\n",
|
||||
// niter,nmark,nactiveall,thresh,nflipall);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class RanMars : protected Pointers {
|
|||
double gaussian(double mu, double sigma);
|
||||
double rayleigh(double sigma);
|
||||
double besselexp(double theta, double alpha, double cp);
|
||||
void select_subset(bigint, int, int *, int *);
|
||||
|
||||
private:
|
||||
int save;
|
||||
|
|
|
@ -440,6 +440,12 @@ void ReadData::command(int narg, char **arg)
|
|||
|
||||
atom->allocate_type_arrays();
|
||||
atom->deallocate_topology();
|
||||
|
||||
// allocate atom arrays to N, rounded up by AtomVec->DELTA
|
||||
|
||||
bigint nbig = n;
|
||||
nbig = atom->avec->roundup(nbig);
|
||||
n = static_cast<int> (nbig);
|
||||
atom->avec->grow(n);
|
||||
|
||||
domain->boxlo[0] = boxlo[0]; domain->boxhi[0] = boxhi[0];
|
||||
|
|
|
@ -165,6 +165,12 @@ void ReadRestart::command(int narg, char **arg)
|
|||
|
||||
atom->allocate_type_arrays();
|
||||
atom->deallocate_topology();
|
||||
|
||||
// allocate atom arrays to size N, rounded up by AtomVec->DELTA
|
||||
|
||||
bigint nbig = n;
|
||||
nbig = atom->avec->roundup(nbig);
|
||||
n = static_cast<int> (nbig);
|
||||
atom->avec->grow(n);
|
||||
n = atom->nmax;
|
||||
|
||||
|
@ -211,13 +217,17 @@ void ReadRestart::command(int narg, char **arg)
|
|||
memory->create(buf,assignedChunkSize,"read_restart:buf");
|
||||
mpiio->read((headerOffset+assignedChunkOffset),assignedChunkSize,buf);
|
||||
mpiio->close();
|
||||
if (!nextra) { // We can actually calculate number of atoms from assignedChunkSize
|
||||
|
||||
// can calculate number of atoms from assignedChunkSize
|
||||
|
||||
if (!nextra) {
|
||||
atom->nlocal = 1; // temporarily claim there is one atom...
|
||||
int perAtomSize = avec->size_restart(); // ...so we can get its size
|
||||
atom->nlocal = 0; // restore nlocal to zero atoms
|
||||
int atomCt = (int) (assignedChunkSize / perAtomSize);
|
||||
if (atomCt > atom->nmax) avec->grow(atomCt);
|
||||
}
|
||||
|
||||
m = 0;
|
||||
while (m < assignedChunkSize) m += avec->unpack_restart(&buf[m]);
|
||||
}
|
||||
|
|
|
@ -223,6 +223,12 @@ void Replicate::command(int narg, char **arg)
|
|||
else n = static_cast<int> (LB_FACTOR * atom->natoms / nprocs);
|
||||
|
||||
atom->allocate_type_arrays();
|
||||
|
||||
// allocate atom arrays to size N, rounded up by AtomVec->DELTA
|
||||
|
||||
bigint nbig = n;
|
||||
nbig = atom->avec->roundup(nbig);
|
||||
n = static_cast<int> (nbig);
|
||||
atom->avec->grow(n);
|
||||
n = atom->nmax;
|
||||
|
||||
|
|
136
src/set.cpp
136
src/set.cpp
|
@ -30,6 +30,7 @@
|
|||
#include "input.h"
|
||||
#include "variable.h"
|
||||
#include "random_park.h"
|
||||
#include "random_mars.h"
|
||||
#include "math_extra.h"
|
||||
#include "math_const.h"
|
||||
#include "memory.h"
|
||||
|
@ -41,7 +42,8 @@ using namespace MathConst;
|
|||
|
||||
enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT};
|
||||
|
||||
enum{TYPE,TYPE_FRACTION,MOLECULE,X,Y,Z,CHARGE,MASS,SHAPE,LENGTH,TRI,
|
||||
enum{TYPE,TYPE_FRACTION,TYPE_RATIO,TYPE_SUBSET,
|
||||
MOLECULE,X,Y,Z,CHARGE,MASS,SHAPE,LENGTH,TRI,
|
||||
DIPOLE,DIPOLE_RANDOM,SPIN,SPIN_RANDOM,QUAT,QUAT_RANDOM,
|
||||
THETA,THETA_RANDOM,ANGMOM,OMEGA,
|
||||
DIAMETER,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER,
|
||||
|
@ -109,6 +111,34 @@ void Set::command(int narg, char **arg)
|
|||
setrandom(TYPE_FRACTION);
|
||||
iarg += 4;
|
||||
|
||||
} else if (strcmp(arg[iarg],"type/ratio") == 0) {
|
||||
if (iarg+4 > narg) error->all(FLERR,"Illegal set command");
|
||||
newtype = force->inumeric(FLERR,arg[iarg+1]);
|
||||
fraction = force->numeric(FLERR,arg[iarg+2]);
|
||||
ivalue = force->inumeric(FLERR,arg[iarg+3]);
|
||||
if (newtype <= 0 || newtype > atom->ntypes)
|
||||
error->all(FLERR,"Invalid value in set command");
|
||||
if (fraction < 0.0 || fraction > 1.0)
|
||||
error->all(FLERR,"Invalid value in set command");
|
||||
if (ivalue <= 0)
|
||||
error->all(FLERR,"Invalid random number seed in set command");
|
||||
setrandom(TYPE_RATIO);
|
||||
iarg += 4;
|
||||
|
||||
} else if (strcmp(arg[iarg],"type/subset") == 0) {
|
||||
if (iarg+4 > narg) error->all(FLERR,"Illegal set command");
|
||||
newtype = force->inumeric(FLERR,arg[iarg+1]);
|
||||
nsubset = force->bnumeric(FLERR,arg[iarg+2]);
|
||||
ivalue = force->inumeric(FLERR,arg[iarg+3]);
|
||||
if (newtype <= 0 || newtype > atom->ntypes)
|
||||
error->all(FLERR,"Invalid value in set command");
|
||||
if (nsubset < 0)
|
||||
error->all(FLERR,"Invalid value in set command");
|
||||
if (ivalue <= 0)
|
||||
error->all(FLERR,"Invalid random number seed in set command");
|
||||
setrandom(TYPE_SUBSET);
|
||||
iarg += 4;
|
||||
|
||||
} else if (strcmp(arg[iarg],"mol") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
|
||||
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) varparse(arg[iarg+1],1);
|
||||
|
@ -1001,23 +1031,72 @@ void Set::setrandom(int keyword)
|
|||
AtomVecTri *avec_tri = (AtomVecTri *) atom->style_match("tri");
|
||||
AtomVecBody *avec_body = (AtomVecBody *) atom->style_match("body");
|
||||
|
||||
RanPark *random = new RanPark(lmp,1);
|
||||
double **x = atom->x;
|
||||
int seed = ivalue;
|
||||
|
||||
// set fraction of atom types to newtype
|
||||
RanPark *ranpark = new RanPark(lmp,1);
|
||||
RanMars *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]) {
|
||||
random->reset(seed,x[i]);
|
||||
if (random->uniform() > fraction) continue;
|
||||
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<bigint> (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
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (select[i] && flag[i]) {
|
||||
atom->type[i] = newtype;
|
||||
count++;
|
||||
}
|
||||
|
||||
// clean up
|
||||
|
||||
memory->destroy(flag);
|
||||
memory->destroy(work);
|
||||
|
||||
// set dipole moments to random orientations in 3d or 2d
|
||||
// dipole length is determined by dipole type array
|
||||
|
||||
|
@ -1030,10 +1109,10 @@ void Set::setrandom(int keyword)
|
|||
if (domain->dimension == 3) {
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (select[i]) {
|
||||
random->reset(seed,x[i]);
|
||||
mu[i][0] = random->uniform() - 0.5;
|
||||
mu[i][1] = random->uniform() - 0.5;
|
||||
mu[i][2] = random->uniform() - 0.5;
|
||||
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;
|
||||
|
@ -1046,9 +1125,9 @@ void Set::setrandom(int keyword)
|
|||
} else {
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (select[i]) {
|
||||
random->reset(seed,x[i]);
|
||||
mu[i][0] = random->uniform() - 0.5;
|
||||
mu[i][1] = random->uniform() - 0.5;
|
||||
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);
|
||||
|
@ -1072,10 +1151,10 @@ void Set::setrandom(int keyword)
|
|||
if (domain->dimension == 3) {
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (select[i]) {
|
||||
random->reset(seed,x[i]);
|
||||
sp[i][0] = random->uniform() - 0.5;
|
||||
sp[i][1] = random->uniform() - 0.5;
|
||||
sp[i][2] = random->uniform() - 0.5;
|
||||
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;
|
||||
|
@ -1088,9 +1167,9 @@ void Set::setrandom(int keyword)
|
|||
} else {
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (select[i]) {
|
||||
random->reset(seed,x[i]);
|
||||
sp[i][0] = random->uniform() - 0.5;
|
||||
sp[i][1] = random->uniform() - 0.5;
|
||||
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);
|
||||
|
@ -1120,12 +1199,12 @@ void Set::setrandom(int keyword)
|
|||
else
|
||||
error->one(FLERR,"Cannot set quaternion for atom that has none");
|
||||
|
||||
random->reset(seed,x[i]);
|
||||
s = random->uniform();
|
||||
ranpark->reset(seed,x[i]);
|
||||
s = ranpark->uniform();
|
||||
t1 = sqrt(1.0-s);
|
||||
t2 = sqrt(s);
|
||||
theta1 = 2.0*MY_PI*random->uniform();
|
||||
theta2 = 2.0*MY_PI*random->uniform();
|
||||
theta1 = 2.0*MY_PI*ranpark->uniform();
|
||||
theta2 = 2.0*MY_PI*ranpark->uniform();
|
||||
quat[0] = cos(theta2)*t2;
|
||||
quat[1] = sin(theta1)*t1;
|
||||
quat[2] = cos(theta1)*t1;
|
||||
|
@ -1144,8 +1223,8 @@ void Set::setrandom(int keyword)
|
|||
else
|
||||
error->one(FLERR,"Cannot set quaternion for atom that has none");
|
||||
|
||||
random->reset(seed,x[i]);
|
||||
theta2 = MY_PI*random->uniform();
|
||||
ranpark->reset(seed,x[i]);
|
||||
theta2 = MY_PI*ranpark->uniform();
|
||||
quat[0] = cos(theta2);
|
||||
quat[1] = 0.0;
|
||||
quat[2] = 0.0;
|
||||
|
@ -1162,14 +1241,15 @@ void Set::setrandom(int keyword)
|
|||
if (select[i]) {
|
||||
if (atom->line[i] < 0)
|
||||
error->one(FLERR,"Cannot set theta for atom that is not a line");
|
||||
random->reset(seed,x[i]);
|
||||
avec_line->bonus[atom->line[i]].theta = MY_2PI*random->uniform();
|
||||
ranpark->reset(seed,x[i]);
|
||||
avec_line->bonus[atom->line[i]].theta = MY_2PI*ranpark->uniform();
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete random;
|
||||
delete ranpark;
|
||||
delete ranmars;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
|
|
@ -34,8 +34,9 @@ class Set : protected Pointers {
|
|||
int *select;
|
||||
int style,ivalue,newtype,count,index_custom;
|
||||
int ximage,yimage,zimage,ximageflag,yimageflag,zimageflag;
|
||||
double dvalue,xvalue,yvalue,zvalue,wvalue,fraction;
|
||||
int cc_index;
|
||||
bigint nsubset;
|
||||
double dvalue,xvalue,yvalue,zvalue,wvalue,fraction;
|
||||
|
||||
int varflag,varflag1,varflag2,varflag3,varflag4;
|
||||
int ivar1,ivar2,ivar3,ivar4;
|
||||
|
|
Loading…
Reference in New Issue