Merge branch 'reset-molecules' into write-bonus-data
This commit is contained in:
@ -101,7 +101,8 @@ An alphabetic list of all general LAMMPS commands.
|
||||
* :doc:`region <region>`
|
||||
* :doc:`replicate <replicate>`
|
||||
* :doc:`rerun <rerun>`
|
||||
* :doc:`reset_ids <reset_ids>`
|
||||
* :doc:`reset_atom_ids <reset_atom_ids>`
|
||||
* :doc:`reset_mol_ids <reset_mol_ids>`
|
||||
* :doc:`reset_timestep <reset_timestep>`
|
||||
* :doc:`restart <restart>`
|
||||
* :doc:`run <run>`
|
||||
|
||||
@ -88,7 +88,8 @@ Commands
|
||||
region
|
||||
replicate
|
||||
rerun
|
||||
reset_ids
|
||||
reset_atom_ids
|
||||
reset_mol_ids
|
||||
reset_timestep
|
||||
restart
|
||||
run
|
||||
|
||||
@ -15,12 +15,18 @@ Syntax
|
||||
.. parsed-literal::
|
||||
|
||||
compute ID group-ID cluster/atom cutoff
|
||||
compute ID group-ID fragment/atom
|
||||
compute ID group-ID fragment/atom keyword value ...
|
||||
compute ID group-ID aggregate/atom cutoff
|
||||
|
||||
* ID, group-ID are documented in :doc:`compute <compute>` command
|
||||
* *cluster/atom* or *fragment/atom* or *aggregate/atom* = style name of this compute command
|
||||
* cutoff = distance within which to label atoms as part of same cluster (distance units)
|
||||
* zero or more keyword/value pairs may be appended to *fragment/atom*
|
||||
* keyword = *single*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*single* value = *yes* or *no* to treat single atoms (no bonds) as fragments
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
@ -29,27 +35,36 @@ Examples
|
||||
|
||||
compute 1 all cluster/atom 3.5
|
||||
compute 1 all fragment/atom
|
||||
|
||||
compute 1 all fragment/atom single no
|
||||
compute 1 all aggregate/atom 3.5
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
Define a computation that assigns each atom a cluster, fragment,
|
||||
or aggregate ID.
|
||||
Define a computation that assigns each atom a cluster, fragment, or
|
||||
aggregate ID. Only atoms in the compute group are clustered and
|
||||
assigned cluster IDs. Atoms not in the compute group are assigned an
|
||||
ID = 0.
|
||||
|
||||
A cluster is defined as a set of atoms, each of which is within the
|
||||
cutoff distance from one or more other atoms in the cluster. If an
|
||||
atom has no neighbors within the cutoff distance, then it is a 1-atom
|
||||
cluster.
|
||||
|
||||
A fragment is similarly defined as a set of atoms, each of
|
||||
which has an explicit bond (i.e. defined via a :doc:`data file <read_data>`,
|
||||
the :doc:`create_bonds <create_bonds>` command, or through fixes like
|
||||
:doc:`fix bond/create <fix_bond_create>`, :doc:`fix bond/swap <fix_bond_swap>`,
|
||||
or :doc:`fix bond/break <fix_bond_break>`). The cluster ID or fragment ID
|
||||
of every atom in the cluster will be set to the smallest atom ID of any atom
|
||||
in the cluster or fragment, respectively.
|
||||
A fragment is similarly defined as a set of atoms, each of which has a
|
||||
bond to another atom in the fragment. Bonds can be defined initially
|
||||
via the :doc:`data file <read_data>` or :doc:`create_bonds
|
||||
<create_bonds>` commands, or dynamically by fixes which create or
|
||||
break bonds like :doc:`fix bond/react <fix_bond_react>`, :doc:`fix
|
||||
bond/create <fix_bond_create>`, :doc:`fix bond/swap <fix_bond_swap>`,
|
||||
or :doc:`fix bond/break <fix_bond_break>`. The cluster ID or fragment
|
||||
ID of every atom in the cluster will be set to the smallest atom ID of
|
||||
any atom in the cluster or fragment, respectively.
|
||||
|
||||
For the *fragment/atom* style, the *single* keyword determines whether
|
||||
single atoms (not bonded to another atom) are treated as one-atom
|
||||
fragments or not, based on the *yes* or *no* setting. If the setting
|
||||
is *no* (the default), their fragment IDs are set to 0.
|
||||
|
||||
An aggregate is defined by combining the rules for clusters and
|
||||
fragments, i.e. a set of atoms, where each of it is within the cutoff
|
||||
@ -57,19 +72,11 @@ distance from one or more atoms within a fragment that is part of
|
||||
the same cluster. This measure can be used to track molecular assemblies
|
||||
like micelles.
|
||||
|
||||
Only atoms in the compute group are clustered and assigned cluster
|
||||
IDs. Atoms not in the compute group are assigned a cluster ID = 0.
|
||||
For fragments, only bonds where **both** atoms of the bond are included
|
||||
in the compute group are assigned to fragments, so that only fragments
|
||||
are detected where **all** atoms are in the compute group. Thus atoms
|
||||
may be included in the compute group, yes still have a fragment ID of 0.
|
||||
|
||||
For computes *cluster/atom* and *aggregate/atom* the neighbor list needed
|
||||
to compute this quantity is constructed each time the calculation is
|
||||
performed (i.e. each time a snapshot of atoms is dumped). Thus it can be
|
||||
inefficient to compute/dump this quantity too frequently or to have
|
||||
multiple compute/dump commands, each of a *cluster/atom* or
|
||||
*aggregate/atom* style.
|
||||
For computes *cluster/atom* and *aggregate/atom* a neighbor list
|
||||
needed to compute cluster IDs is constructed each time the compute is
|
||||
invoked. Thus it can be inefficient to compute/dump this quantity too
|
||||
frequently or to have multiple *cluster/atom* or *aggregate/atom*
|
||||
style computes.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -89,6 +96,14 @@ multiple compute/dump commands, each of a *cluster/atom* or
|
||||
:doc:`special_bonds <special_bonds>` command that includes all pairs in
|
||||
the neighbor list.
|
||||
|
||||
.. note::
|
||||
|
||||
For the compute fragment/atom style, each fragment is identified
|
||||
using the current bond topology. This will not account for bonds
|
||||
broken by the :doc:`bond_style quartic <bond_quartic>` command
|
||||
because it does not perform a full update of the bond topology data
|
||||
structures within LAMMPS.
|
||||
|
||||
**Output info:**
|
||||
|
||||
This compute calculates a per-atom vector, which can be accessed by
|
||||
@ -107,4 +122,7 @@ Related commands
|
||||
|
||||
:doc:`compute coord/atom <compute_coord_atom>`
|
||||
|
||||
**Default:** none
|
||||
**Default:**
|
||||
|
||||
The default for fragment/atom is single no.
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@ number of atoms in the system. Note that this is not done for
|
||||
molecular systems (see the :doc:`atom_style <atom_style>` command),
|
||||
regardless of the *compress* setting, since it would foul up the bond
|
||||
connectivity that has already been assigned. However, the
|
||||
:doc:`reset_ids <reset_ids>` command can be used after this command to
|
||||
:doc:`reset_atom_ids <reset_atom_ids>` command can be used after this command to
|
||||
accomplish the same thing.
|
||||
|
||||
Note that the re-assignment of IDs is not really a compression, where
|
||||
@ -157,7 +157,7 @@ using molecule template files via the :doc:`molecule <molecule>` and
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`create_atoms <create_atoms>`, :doc:`reset_ids <reset_ids>`
|
||||
:doc:`create_atoms <create_atoms>`, :doc:`reset_atom_ids <reset_atom_ids>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
.. index:: reset_ids
|
||||
.. index:: reset_atom_ids
|
||||
|
||||
reset_ids command
|
||||
=================
|
||||
reset_atom_ids command
|
||||
======================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
reset_ids keyword values ...
|
||||
reset_atom_ids keyword values ...
|
||||
|
||||
* zero or more keyword/value pairs may be appended
|
||||
* keyword = *sort*
|
||||
@ -22,8 +22,8 @@ Examples
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
reset_ids
|
||||
reset_ids sort yes
|
||||
reset_atom_ids
|
||||
reset_atom_ids sort yes
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
@ -77,7 +77,7 @@ processor have consecutive IDs, as the :doc:`create_atoms
|
||||
that are owned by other processors. The :doc:`comm_modify cutoff <comm_modify>` command can be used to correct this issue.
|
||||
Or you can define a pair style before using this command. If you do
|
||||
the former, you should unset the comm_modify cutoff after using
|
||||
reset_ids so that subsequent communication is not inefficient.
|
||||
reset_atom_ids so that subsequent communication is not inefficient.
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
116
doc/src/reset_mol_ids.rst
Normal file
116
doc/src/reset_mol_ids.rst
Normal file
@ -0,0 +1,116 @@
|
||||
.. index:: reset_mol_ids
|
||||
|
||||
reset_mol_ids command
|
||||
=====================
|
||||
|
||||
Syntax
|
||||
""""""
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
reset_mol_ids group-ID keyword value ...
|
||||
|
||||
* group-ID = ID of group of atoms whose molecule IDs will be reset
|
||||
* zero or more keyword/value pairs may be appended
|
||||
* keyword = *compress* or *offset* or *single*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*compress* value = *yes* or *no*
|
||||
*offset* value = *Noffset* >= -1
|
||||
*single* value = *yes* or *no* to treat single atoms (no bonds) as molecules
|
||||
|
||||
Examples
|
||||
""""""""
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
reset_mol_ids all
|
||||
reset_mol_ids all offset 10 single yes
|
||||
reset_mol_ids solvent compress yes offset 100
|
||||
reset_mol_ids solvent compress no
|
||||
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
Reset molecule IDs for a group of atoms based on current bond
|
||||
connectivity. This will typically create a new set of molecule IDs
|
||||
for atoms in the group. Only molecule IDs for atoms in the specified
|
||||
group are reset; molecule IDs for atoms not in the group are not
|
||||
changed.
|
||||
|
||||
For purposes of this operation, molecules are identified by the current
|
||||
bond connectivity in the system, which may or may not be consistent with
|
||||
the current molecule IDs. A molecule in this context is a set of atoms
|
||||
connected to each other with explicit bonds. The specific algorithm
|
||||
used is the one of :doc:`compute fragment/atom <compute_cluster_atom>`
|
||||
Once the molecules are identified and a new molecule ID computed for
|
||||
each, this command will update the current molecule ID for all atoms in
|
||||
the group with the new molecule ID. Note that if the group excludes
|
||||
atoms within molecules, one (physical) molecule may become two or more
|
||||
(logical) molecules. For example if the group excludes atoms in the
|
||||
middle of a linear chain, then each end of the chain is considered an
|
||||
independent molecule and will be assigned a different molecule ID.
|
||||
|
||||
This can be a useful operation to perform after running reactive
|
||||
molecular dynamics run with :doc:`fix bond/react <fix_bond_react>`,
|
||||
:doc:`fix bond/create <fix_bond_create>`, or :doc:`fix bond/break
|
||||
<fix_bond_break>`, all of which can change molecule topologies. It can
|
||||
also be useful after molecules have been deleted with the
|
||||
:doc:`delete_atoms <delete_atoms>` command or after a simulation which
|
||||
has lost molecules, e.g. via the :doc:`fix evaporate <fix_evaporate>`
|
||||
command.
|
||||
|
||||
The *compress* keyword determines how new molecule IDs are computed. If
|
||||
the setting is *yes* (the default) and there are N molecules in the
|
||||
group, the new molecule IDs will be a set of N contiguous values. See
|
||||
the *offset* keyword for details on selecting the range of these values.
|
||||
If the setting is *no*, the molecule ID of every atom in the molecule
|
||||
will be set to the smallest atom ID of any atom in the molecule.
|
||||
|
||||
The *single* keyword determines whether single atoms (not bonded to
|
||||
another atom) are treated as one-atom molecules or not, based on the
|
||||
*yes* or *no* setting. If the setting is *no* (the default), their
|
||||
molecule IDs are set to 0. This setting can be important if the new
|
||||
molecule IDs will be used as input to other commands such as
|
||||
:doc:`compute chunk/atom molecule <compute_chunk_atom>` or :doc:`fix
|
||||
rigid molecule <fix_rigid>`.
|
||||
|
||||
The *offset* keyword is only used if the *compress* setting is *yes*.
|
||||
Its default value is *Noffset* = -1. In that case, if the specified
|
||||
group is *all*, then the new compressed molecule IDs will range from 1
|
||||
to N. If the specified group is not *all* and the largest molecule ID
|
||||
of atoms outside that group is M, then the new compressed molecule IDs will
|
||||
range from M+1 to M+N, to avoid collision with existing molecule
|
||||
IDs. If an *Noffset* >= 0 is specified, then the new compressed
|
||||
molecule IDs will range from *Noffset*\ +1 to *Noffset*\ +N. If the group
|
||||
is not *all* there may be collisions with the molecule IDs of other atoms.
|
||||
|
||||
.. note::
|
||||
|
||||
The same as explained for the :doc:`compute fragment/atom
|
||||
<compute_cluster_atom>` command, molecules are identified using the
|
||||
current bond topology. This will not account for bonds broken by
|
||||
the :doc:`bond_style quartic <bond_quartic>` command because it
|
||||
does not perform a full update of the bond topology data structures
|
||||
within LAMMPS.
|
||||
|
||||
Restrictions
|
||||
""""""""""""
|
||||
none
|
||||
|
||||
Related commands
|
||||
""""""""""""""""
|
||||
|
||||
:doc:`reset_atom_ids <reset_atom_ids>`, :doc:`fix bond/react <fix_bond_react>`,
|
||||
:doc:`fix bond/create <fix_bond_create>`,
|
||||
:doc:`fix bond/break <fix_bond_break>`,
|
||||
:doc:`fix evaporate <fix_evaporate>`,
|
||||
:doc:`delete_atoms <delete_atoms>`,
|
||||
:doc:`compute fragment/atom <compute_cluster_atom>`
|
||||
|
||||
Default
|
||||
"""""""
|
||||
|
||||
The default keyword settings are compress = yes, single = no, and
|
||||
offset = -1.
|
||||
@ -52,6 +52,7 @@ minimize = {}
|
||||
pair = {}
|
||||
reader = {}
|
||||
region = {}
|
||||
total = 0
|
||||
|
||||
upper = re.compile("[A-Z]+")
|
||||
gpu = re.compile("(.+)/gpu$")
|
||||
@ -60,7 +61,7 @@ kokkos = re.compile("(.+)/kk$")
|
||||
kokkos_skip = re.compile("(.+)/kk/(host|device)$")
|
||||
omp = re.compile("(.+)/omp$")
|
||||
opt = re.compile("(.+)/opt$")
|
||||
removed = re.compile("(.+)Deprecated$")
|
||||
removed = re.compile("(.*)Deprecated$")
|
||||
|
||||
def register_style(list,style,info):
|
||||
if style in list.keys():
|
||||
@ -119,6 +120,7 @@ for h in headers:
|
||||
|
||||
# skip over internal styles w/o explicit documentation
|
||||
style = m[1]
|
||||
total += 1
|
||||
if upper.match(style):
|
||||
continue
|
||||
|
||||
@ -197,12 +199,13 @@ print("""Parsed style names w/o suffixes from C++ tree in %s:
|
||||
Fix styles: %3d Improper styles: %3d
|
||||
Integrate styles: %3d Kspace styles: %3d
|
||||
Minimize styles: %3d Pair styles: %3d
|
||||
Reader styles: %3d Region styles: %3d""" \
|
||||
Reader styles: %3d Region styles: %3d
|
||||
----------------------------------------------------
|
||||
Total number of styles (including suffixes): %d""" \
|
||||
% (src, len(angle), len(atom), len(body), len(bond), \
|
||||
len(command), len(compute), len(dihedral), len(dump), \
|
||||
len(fix), len(improper), len(integrate), len(kspace), \
|
||||
len(minimize), len(pair), len(reader), len(region)))
|
||||
|
||||
len(minimize), len(pair), len(reader), len(region), total))
|
||||
|
||||
counter = 0
|
||||
|
||||
|
||||
@ -2058,6 +2058,7 @@ nodeless
|
||||
nodeset
|
||||
nodesets
|
||||
Noehring
|
||||
Noffset
|
||||
noforce
|
||||
Noid
|
||||
nolib
|
||||
|
||||
1
examples/threebody/CdTeZnSeHgS0.sw
Symbolic link
1
examples/threebody/CdTeZnSeHgS0.sw
Symbolic link
@ -0,0 +1 @@
|
||||
../../potentials/CdTeZnSeHgS0.sw
|
||||
@ -204,6 +204,12 @@ class lammps(object):
|
||||
self.lib.lammps_neighlist_element_neighbors.argtypes = [c_void_p, c_int, c_int, POINTER(c_int), POINTER(c_int), POINTER(POINTER(c_int))]
|
||||
self.lib.lammps_neighlist_element_neighbors.restype = None
|
||||
|
||||
self.lib.lammps_has_error.argtypes = [c_void_p]
|
||||
self.lib.lammps_has_error.restype = c_bool
|
||||
|
||||
self.lib.lammps_get_last_error_message.argtypes = [c_void_p, c_char_p, c_int]
|
||||
self.lib.lammps_get_last_error_message.restype = c_int
|
||||
|
||||
# if no ptr provided, create an instance of LAMMPS
|
||||
# don't know how to pass an MPI communicator from PyPar
|
||||
# but we can pass an MPI communicator from mpi4py v2.0.0 and later
|
||||
|
||||
@ -44,8 +44,7 @@ void AngleDeprecated::settings(int, char **)
|
||||
utils::logmesg(lmp,"\nAngle style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This angle style is no longer available");
|
||||
error->all(FLERR,"This angle style is no longer available");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -44,8 +44,7 @@ void BondDeprecated::settings(int, char **)
|
||||
utils::logmesg(lmp,"\nBond style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This bond style is no longer available");
|
||||
error->all(FLERR,"This bond style is no longer available");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -31,6 +31,5 @@ ComputeDeprecated::ComputeDeprecated(LAMMPS *lmp, int narg, char **arg) :
|
||||
utils::logmesg(lmp,"\nCompute style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This compute style is no longer available");
|
||||
error->all(FLERR,"This compute style is no longer available");
|
||||
}
|
||||
|
||||
@ -23,37 +23,56 @@
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "force.h"
|
||||
#include "group.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "group.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define BIG 1.0e20
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeFragmentAtom::ComputeFragmentAtom(LAMMPS *lmp, int narg, char **arg) :
|
||||
Compute(lmp, narg, arg),
|
||||
fragmentID(NULL)
|
||||
{
|
||||
if (narg != 3) error->all(FLERR,"Illegal compute fragment/atom command");
|
||||
|
||||
if (atom->avec->bonds_allow == 0)
|
||||
error->all(FLERR,"Compute fragment/atom used when bonds are not allowed");
|
||||
|
||||
peratom_flag = 1;
|
||||
size_peratom_cols = 0;
|
||||
comm_forward = 1;
|
||||
comm_reverse = 1;
|
||||
|
||||
// process optional args
|
||||
|
||||
singleflag = 0;
|
||||
|
||||
int iarg = 3;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"single") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal compute fragment/atom command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) singleflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) singleflag = 0;
|
||||
else error->all(FLERR,"Illegal compute fragment/atom command");
|
||||
iarg += 2;
|
||||
} else error->all(FLERR,"Illegal compute fragment/atom command");
|
||||
}
|
||||
|
||||
nmax = 0;
|
||||
stack = NULL;
|
||||
clist = NULL;
|
||||
markflag = NULL;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeFragmentAtom::~ComputeFragmentAtom()
|
||||
{
|
||||
memory->destroy(stack);
|
||||
memory->destroy(clist);
|
||||
memory->destroy(markflag);
|
||||
memory->destroy(fragmentID);
|
||||
}
|
||||
|
||||
@ -63,8 +82,8 @@ void ComputeFragmentAtom::init()
|
||||
{
|
||||
if (atom->tag_enable == 0)
|
||||
error->all(FLERR,"Cannot use compute fragment/atom unless atoms have IDs");
|
||||
if (force->bond == NULL)
|
||||
error->all(FLERR,"Compute fragment/atom requires a bond style to be defined");
|
||||
if (!atom->molecular)
|
||||
error->all(FLERR,"Compute fragment/atom requires a molecular system");
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < modify->ncompute; i++)
|
||||
@ -77,15 +96,24 @@ void ComputeFragmentAtom::init()
|
||||
|
||||
void ComputeFragmentAtom::compute_peratom()
|
||||
{
|
||||
int i,j,k;
|
||||
int i,j,k,m,n;
|
||||
int nstack,ncluster,done,alldone;
|
||||
double newID,cID;
|
||||
tagint *list;
|
||||
|
||||
invoked_peratom = update->ntimestep;
|
||||
|
||||
// grow fragmentID array if necessary
|
||||
// grow work and fragmentID vectors if necessary
|
||||
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(stack);
|
||||
memory->destroy(clist);
|
||||
memory->destroy(markflag);
|
||||
memory->destroy(fragmentID);
|
||||
nmax = atom->nmax;
|
||||
memory->create(stack,nmax,"fragment/atom:stack");
|
||||
memory->create(clist,nmax,"fragment/atom:clist");
|
||||
memory->create(markflag,nmax,"fragment/atom:markflag");
|
||||
memory->create(fragmentID,nmax,"fragment/atom:fragmentID");
|
||||
vector_atom = fragmentID;
|
||||
}
|
||||
@ -97,63 +125,111 @@ void ComputeFragmentAtom::compute_peratom()
|
||||
comm->forward_comm_compute(this);
|
||||
}
|
||||
|
||||
// each atom starts in its own fragment,
|
||||
// owned + ghost atoms start with fragmentID = atomID
|
||||
// atoms not in group have fragmentID = 0
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
tagint *tag = atom->tag;
|
||||
int *mask = atom->mask;
|
||||
int *num_bond = atom->num_bond;
|
||||
int **bond_type = atom->bond_type;
|
||||
tagint **bond_atom = atom->bond_atom;
|
||||
tagint **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int nlocal = atom->nlocal;
|
||||
int nall = nlocal + atom->nghost;
|
||||
|
||||
for (i = 0; i < nlocal + atom->nghost; i++)
|
||||
for (i = 0; i < nall; i++) {
|
||||
if (mask[i] & groupbit) fragmentID[i] = tag[i];
|
||||
else fragmentID[i] = 0;
|
||||
}
|
||||
|
||||
// loop until no more changes on any proc:
|
||||
// loop until no ghost atom fragment ID is changed
|
||||
// acquire fragmentIDs of ghost atoms
|
||||
// loop over my atoms, and check atoms bound to it
|
||||
// if both atoms are in fragment, assign lowest fragmentID to both
|
||||
// iterate until no changes in my atoms
|
||||
// then check if any proc made changes
|
||||
// loop over clusters of atoms, which include ghost atoms
|
||||
// set fragmentIDs for each cluster to min framentID in the clusters
|
||||
// if singleflag = 0 atoms without bonds are assigned fragmentID = 0
|
||||
// iterate until no changes to ghost atom fragmentIDs
|
||||
|
||||
commflag = 1;
|
||||
|
||||
int change,done,anychange;
|
||||
int iteration = 0;
|
||||
|
||||
while (1) {
|
||||
iteration++;
|
||||
|
||||
comm->forward_comm_compute(this);
|
||||
done = 1;
|
||||
|
||||
// reverse communication when bonds are not stored on every processor
|
||||
// set markflag = 0 for all owned atoms, for new iteration
|
||||
|
||||
if (force->newton_bond)
|
||||
comm->reverse_comm_compute(this);
|
||||
for (i = 0; i < nlocal; i++) markflag[i] = 0;
|
||||
|
||||
change = 0;
|
||||
while (1) {
|
||||
done = 1;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
// loop over all owned atoms
|
||||
// each unmarked atom starts a cluster search
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
|
||||
// skip atom I if not in group or already marked
|
||||
// if singleflag = 0 and atom has no bond partners, fragID = 0 and done
|
||||
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
if (markflag[i]) continue;
|
||||
if (!singleflag && (nspecial[i][0] == 0)) {
|
||||
fragmentID[i] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// find one cluster of bond-connected atoms
|
||||
// ncluster = # of owned and ghost atoms in cluster
|
||||
// clist = vector of local indices of the ncluster atoms
|
||||
// stack is used to walk the bond topology
|
||||
|
||||
ncluster = nstack = 0;
|
||||
stack[nstack++] = i;
|
||||
|
||||
while (nstack) {
|
||||
j = stack[--nstack];
|
||||
clist[ncluster++] = j;
|
||||
markflag[j] = 1;
|
||||
|
||||
n = nspecial[j][0];
|
||||
list = special[j];
|
||||
for (m = 0; m < n; m++) {
|
||||
k = atom->map(list[m]);
|
||||
|
||||
// skip bond neighbor K if not in group or already marked
|
||||
|
||||
for (j = 0; j < num_bond[i]; j++) {
|
||||
if (bond_type[i][j] == 0) continue;
|
||||
k = atom->map(bond_atom[i][j]);
|
||||
if (k < 0) continue;
|
||||
if (!(mask[k] & groupbit)) continue;
|
||||
if (fragmentID[i] == fragmentID[k]) continue;
|
||||
if (k < nlocal && markflag[k]) continue;
|
||||
|
||||
fragmentID[i] = fragmentID[k] = MIN(fragmentID[i],fragmentID[k]);
|
||||
done = 0;
|
||||
// owned bond neighbors are added to stack for further walking
|
||||
// ghost bond neighbors are added directly w/out use of stack
|
||||
|
||||
if (k < nlocal) stack[nstack++] = k;
|
||||
else clist[ncluster++] = k;
|
||||
}
|
||||
}
|
||||
if (!done) change = 1;
|
||||
if (done) break;
|
||||
|
||||
// newID = minimum fragment ID in cluster list, including ghost atoms
|
||||
|
||||
newID = BIG;
|
||||
for (m = 0; m < ncluster; m++) {
|
||||
cID = fragmentID[clist[m]];
|
||||
newID = MIN(newID,cID);
|
||||
}
|
||||
|
||||
// set fragmentID = newID for all atoms in cluster, including ghost atoms
|
||||
// not done with iterations if change the fragmentID of a ghost atom
|
||||
|
||||
for (m = 0; m < ncluster; m++) {
|
||||
j = clist[m];
|
||||
if (j >= nlocal && fragmentID[j] != newID) done = 0;
|
||||
fragmentID[j] = newID;
|
||||
}
|
||||
}
|
||||
|
||||
// stop if all procs are done
|
||||
|
||||
MPI_Allreduce(&change,&anychange,1,MPI_INT,MPI_MAX,world);
|
||||
if (!anychange) break;
|
||||
MPI_Allreduce(&done,&alldone,1,MPI_INT,MPI_MIN,world);
|
||||
if (alldone) break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,43 +279,13 @@ void ComputeFragmentAtom::unpack_forward_comm(int n, int first, double *buf)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int ComputeFragmentAtom::pack_reverse_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
buf[m++] = fragmentID[i];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeFragmentAtom::unpack_reverse_comm(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
double x = buf[m++];
|
||||
|
||||
// only overwrite local IDs with values lower than current ones
|
||||
|
||||
fragmentID[j] = MIN(x,fragmentID[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local atom-based array
|
||||
memory usage of local atom-based arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double ComputeFragmentAtom::memory_usage()
|
||||
{
|
||||
double bytes = nmax * sizeof(double);
|
||||
bytes += 3*nmax * sizeof(int);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@ -32,12 +32,11 @@ class ComputeFragmentAtom : public Compute {
|
||||
void compute_peratom();
|
||||
int pack_forward_comm(int, int *, double *, int, int *);
|
||||
void unpack_forward_comm(int, int, double *);
|
||||
int pack_reverse_comm(int, int, double *);
|
||||
void unpack_reverse_comm(int, int *, double *);
|
||||
double memory_usage();
|
||||
|
||||
private:
|
||||
int nmax,commflag;
|
||||
int nmax,commflag,singleflag;
|
||||
int *stack,*clist,*markflag;
|
||||
double *fragmentID;
|
||||
};
|
||||
|
||||
|
||||
@ -16,29 +16,27 @@
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "deprecated.h"
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "input.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
static void writemsg(LAMMPS *lmp, const char *msg, int abend=1)
|
||||
{
|
||||
if (lmp->comm->me == 0) {
|
||||
if (lmp->screen) fputs(msg,lmp->screen);
|
||||
if (lmp->logfile) fputs(msg,lmp->logfile);
|
||||
}
|
||||
if (abend)
|
||||
lmp->error->all(FLERR,"This command is no longer available");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Deprecated::command(int /* narg */, char ** /* arg */)
|
||||
{
|
||||
if (strcmp(input->command,"DEPRECATED") == 0) {
|
||||
writemsg(lmp,"\nCommand 'DEPRECATED' is a dummy command\n\n",0);
|
||||
const std::string cmd = input->command;
|
||||
|
||||
if (cmd == "DEPRECATED") {
|
||||
if (lmp->comm->me == 0)
|
||||
utils::logmesg(lmp,"\nCommand 'DEPRECATED' is a dummy command\n\n");
|
||||
return;
|
||||
} else if (cmd == "reset_ids") {
|
||||
if (lmp->comm->me == 0)
|
||||
utils::logmesg(lmp,"\n'reset_ids' has been renamed to 'reset_atom_ids'\n\n");
|
||||
}
|
||||
error->all(FLERR,"This command is no longer available");
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#ifdef COMMAND_CLASS
|
||||
|
||||
CommandStyle(DEPRECATED,Deprecated)
|
||||
CommandStyle(reset_ids,Deprecated)
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@ -45,6 +45,5 @@ void DihedralDeprecated::settings(int, char **)
|
||||
utils::logmesg(lmp,"\nDihedral style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This dihedral style is no longer available");
|
||||
error->all(FLERR,"This dihedral style is no longer available");
|
||||
}
|
||||
|
||||
@ -31,6 +31,5 @@ DumpDeprecated::DumpDeprecated(LAMMPS *lmp, int narg, char **arg) :
|
||||
utils::logmesg(lmp,"\nDump style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This dump style is no longer available");
|
||||
error->all(FLERR,"This dump style is no longer available");
|
||||
}
|
||||
|
||||
@ -43,6 +43,5 @@ FixDeprecated::FixDeprecated(LAMMPS *lmp, int narg, char **arg) :
|
||||
"compute chunk/atom:\n dim, origin, delta, region, "
|
||||
"bound, discard, units\n\n");
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This fix style is no longer available");
|
||||
error->all(FLERR,"This fix style is no longer available");
|
||||
}
|
||||
|
||||
@ -45,8 +45,7 @@ void ImproperDeprecated::settings(int, char **)
|
||||
utils::logmesg(lmp,"\nImproper style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This improper style is no longer available");
|
||||
error->all(FLERR,"This improper style is no longer available");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -227,7 +227,7 @@ void Input::file()
|
||||
|
||||
// execute the command
|
||||
|
||||
if (execute_command())
|
||||
if (execute_command() && line)
|
||||
error->all(FLERR,fmt::format("Unknown command: {}",line));
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,8 +35,7 @@ void KSpaceDeprecated::settings(int, char **)
|
||||
utils::logmesg(lmp,"\nKSpace style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This kspace style is no longer available");
|
||||
error->all(FLERR,"This kspace style is no longer available");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -50,6 +50,5 @@ void PairDeprecated::settings(int, char **)
|
||||
utils::logmesg(lmp,"\nPair style 'reax' has been removed from LAMMPS "
|
||||
"after the 12 December 2018 version\n\n");
|
||||
}
|
||||
|
||||
lmp->error->all(FLERR,"This pair style is no longer available");
|
||||
error->all(FLERR,"This pair style is no longer available");
|
||||
}
|
||||
|
||||
@ -31,5 +31,5 @@ RegionDeprecated::RegionDeprecated(LAMMPS *lmp, int narg, char **arg) :
|
||||
utils::logmesg(lmp,"\nRegion style 'DEPRECATED' is a dummy style\n\n");
|
||||
return;
|
||||
}
|
||||
lmp->error->all(FLERR,"This region style is no longer available");
|
||||
error->all(FLERR,"This region style is no longer available");
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "reset_ids.h"
|
||||
#include "reset_atom_ids.h"
|
||||
#include <mpi.h>
|
||||
#include <cstring>
|
||||
#include "atom.h"
|
||||
@ -53,11 +53,11 @@ void ResetIDs::command(int narg, char **arg)
|
||||
if (domain->box_exist == 0)
|
||||
error->all(FLERR,"Reset_ids command before simulation box is defined");
|
||||
if (atom->tag_enable == 0)
|
||||
error->all(FLERR,"Cannot use reset_ids unless atoms have IDs");
|
||||
error->all(FLERR,"Cannot use reset_atom_ids unless atoms have IDs");
|
||||
|
||||
for (int i = 0; i < modify->nfix; i++)
|
||||
if (modify->fix[i]->stores_ids)
|
||||
error->all(FLERR,"Cannot use reset_ids when a fix exists that stores atom IDs");
|
||||
error->all(FLERR,"Cannot use reset_atom_ids when a fix exists that stores atom IDs");
|
||||
|
||||
if (comm->me == 0) utils::logmesg(lmp,"Resetting atom IDs ...\n");
|
||||
|
||||
@ -68,12 +68,12 @@ void ResetIDs::command(int narg, char **arg)
|
||||
int iarg = 0;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"sort") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal reset_ids command");
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal reset_atom_ids command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) sortflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) sortflag = 0;
|
||||
else error->all(FLERR,"Illegal reset_ids command");
|
||||
else error->all(FLERR,"Illegal reset_atom_ids command");
|
||||
iarg += 2;
|
||||
} else error->all(FLERR,"Illegal reset_ids command");
|
||||
} else error->all(FLERR,"Illegal reset_atom_ids command");
|
||||
}
|
||||
|
||||
// create an atom map if one doesn't exist already
|
||||
@ -110,7 +110,7 @@ void ResetIDs::command(int narg, char **arg)
|
||||
int nall = nlocal + atom->nghost;
|
||||
|
||||
tagint *oldIDs;
|
||||
memory->create(oldIDs,nlocal,"reset_ids:oldIDs");
|
||||
memory->create(oldIDs,nlocal,"reset_atom_ids:oldIDs");
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
oldIDs[i] = tag[i];
|
||||
@ -129,7 +129,7 @@ void ResetIDs::command(int narg, char **arg)
|
||||
// forward_comm_array acquires new IDs for ghost atoms
|
||||
|
||||
double **newIDs;
|
||||
memory->create(newIDs,nall,1,"reset_ids:newIDs");
|
||||
memory->create(newIDs,nall,1,"reset_atom_ids:newIDs");
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
newIDs[i][0] = ubuf(tag[i]).d;
|
||||
@ -155,7 +155,7 @@ void ResetIDs::command(int narg, char **arg)
|
||||
for (j = 0; j < num_bond[i]; j++) {
|
||||
oldID = bond_atom[i][j];
|
||||
m = atom->map(oldID);
|
||||
if (m >= 0) bond_atom[i][j] = static_cast<tagint> (newIDs[m][0]);
|
||||
if (m >= 0) bond_atom[i][j] = (tagint) ubuf(newIDs[m][0]).i;
|
||||
else badcount++;
|
||||
}
|
||||
}
|
||||
@ -318,6 +318,15 @@ void ResetIDs::sort()
|
||||
|
||||
if (dim == 2) mylo[2] = myhi[2] = 0.0;
|
||||
|
||||
// must ensure that bounding box volume is > 0.0
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (mylo[i] == myhi[i]) {
|
||||
mylo[i] -= 0.5;
|
||||
myhi[i] += 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
MPI_Allreduce(mylo,bboxlo,3,MPI_DOUBLE,MPI_MIN,world);
|
||||
MPI_Allreduce(myhi,bboxhi,3,MPI_DOUBLE,MPI_MAX,world);
|
||||
|
||||
@ -332,7 +341,8 @@ void ResetIDs::sort()
|
||||
// binsize = edge length of a cubic bin
|
||||
// nbin xyz = bin count in each dimension
|
||||
|
||||
bigint nbin_estimate = atom->natoms / PERBIN;
|
||||
bigint nbin_estimate = atom->natoms / PERBIN + 1;
|
||||
|
||||
double vol;
|
||||
if (dim == 2) vol = (bboxhi[0]-bboxlo[0]) * (bboxhi[1]-bboxlo[1]);
|
||||
else vol = (bboxhi[0]-bboxlo[0]) * (bboxhi[1]-bboxlo[1]) * (bboxhi[2]-bboxlo[2]);
|
||||
@ -406,8 +416,8 @@ void ResetIDs::sort()
|
||||
|
||||
char *buf;
|
||||
int nreturn = comm->rendezvous(1,nlocal,(char *) atombuf,sizeof(AtomRvous),
|
||||
0,proclist,
|
||||
sort_bins,0,buf,sizeof(IDRvous),(void *) this);
|
||||
0,proclist,
|
||||
sort_bins,0,buf,sizeof(IDRvous),(void *) this);
|
||||
IDRvous *outbuf = (IDRvous *) buf;
|
||||
|
||||
memory->destroy(proclist);
|
||||
@ -432,8 +442,8 @@ void ResetIDs::sort()
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ResetIDs::sort_bins(int n, char *inbuf,
|
||||
int &flag, int *&proclist, char *&outbuf,
|
||||
void *ptr)
|
||||
int &flag, int *&proclist, char *&outbuf,
|
||||
void *ptr)
|
||||
{
|
||||
int i,ibin,index;
|
||||
|
||||
@ -467,8 +477,8 @@ int ResetIDs::sort_bins(int n, char *inbuf,
|
||||
for (i = 0; i < n; i++) {
|
||||
if (in[i].ibin < binlo || in[i].ibin >= binhi) {
|
||||
//printf("BAD me %d i %d %d ibin %d binlohi %d %d\n",
|
||||
// rptr->comm->me,i,n,in[i].ibin,binlo,binhi);
|
||||
error->one(FLERR,"Bad spatial bin assignment in reset_ids sort");
|
||||
// rptr->comm->me,i,n,in[i].ibin,binlo,binhi);
|
||||
error->one(FLERR,"Bad spatial bin assignment in reset_atom_ids sort");
|
||||
}
|
||||
ibin = in[i].ibin - binlo;
|
||||
if (head[ibin] < 0) head[ibin] = i;
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
#ifdef COMMAND_CLASS
|
||||
|
||||
CommandStyle(reset_ids,ResetIDs)
|
||||
CommandStyle(reset_atom_ids,ResetIDs)
|
||||
|
||||
#else
|
||||
|
||||
@ -70,7 +70,7 @@ E: Illegal ... command
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
E: Cannot use reset_ids unless atoms have IDs
|
||||
E: Cannot use reset_atom_ids unless atoms have IDs
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
214
src/reset_mol_ids.cpp
Normal file
214
src/reset_mol_ids.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
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 author: Jacob Gissinger (jacob.gissinger@colorado.edu)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "reset_mol_ids.h"
|
||||
#include <mpi.h>
|
||||
#include <string>
|
||||
#include "atom.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "group.h"
|
||||
#include "modify.h"
|
||||
#include "compute_fragment_atom.h"
|
||||
#include "compute_chunk_atom.h"
|
||||
#include "utils.h"
|
||||
#include "error.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ResetMolIDs::ResetMolIDs(LAMMPS *lmp) : Pointers(lmp) {}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ResetMolIDs::command(int narg, char **arg)
|
||||
{
|
||||
if (domain->box_exist == 0)
|
||||
error->all(FLERR,"Reset_mol_ids command before simulation box is defined");
|
||||
if (atom->tag_enable == 0)
|
||||
error->all(FLERR,"Cannot use reset_mol_ids unless atoms have IDs");
|
||||
if (atom->molecular != 1)
|
||||
error->all(FLERR,"Can only use reset_mol_ids on molecular systems");
|
||||
|
||||
// process args
|
||||
|
||||
if (narg < 1) error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
int igroup = group->find(arg[0]);
|
||||
if (igroup == -1) error->all(FLERR,"Could not find reset_mol_ids group ID");
|
||||
int groupbit = group->bitmask[igroup];
|
||||
|
||||
int compressflag = 1;
|
||||
int singleflag = 0;
|
||||
tagint offset = -1;
|
||||
|
||||
int iarg = 1;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"compress") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) compressflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) compressflag = 0;
|
||||
else error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"single") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) singleflag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) singleflag = 0;
|
||||
else error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"offset") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
offset = utils::tnumeric(FLERR,arg[iarg+1],1,lmp);
|
||||
if (offset < -1) error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
iarg += 2;
|
||||
} else error->all(FLERR,"Illegal reset_mol_ids command");
|
||||
}
|
||||
|
||||
if (comm->me == 0) utils::logmesg(lmp,"Resetting molecule IDs ...\n");
|
||||
|
||||
// record wall time for resetting molecule IDs
|
||||
|
||||
MPI_Barrier(world);
|
||||
double time1 = MPI_Wtime();
|
||||
|
||||
// create instances of compute fragment/atom, compute reduce (if needed),
|
||||
// and compute chunk/atom. all use the group-ID for this command
|
||||
|
||||
const std::string idfrag = "reset_mol_ids_FRAGMENT_ATOM";
|
||||
if (singleflag)
|
||||
modify->add_compute(fmt::format("{} {} fragment/atom single yes",idfrag,arg[0]));
|
||||
else
|
||||
modify->add_compute(fmt::format("{} {} fragment/atom single no",idfrag,arg[0]));
|
||||
|
||||
const std::string idchunk = "reset_mol_ids_CHUNK_ATOM";
|
||||
if (compressflag)
|
||||
modify->add_compute(fmt::format("{} {} chunk/atom molecule compress yes",
|
||||
idchunk,arg[0]));
|
||||
|
||||
// initialize system since comm->borders() will be invoked
|
||||
|
||||
lmp->init();
|
||||
|
||||
// setup domain, communication
|
||||
// exchange will clear map, borders will reset
|
||||
// this is the map needed to lookup current global IDs for bond topology
|
||||
|
||||
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);
|
||||
|
||||
// invoke peratom method of compute fragment/atom
|
||||
// walks bond connectivity and assigns each atom a fragment ID
|
||||
// if singleflag = 0, atoms w/out bonds will be assigned fragID = 0
|
||||
|
||||
int icompute = modify->find_compute(idfrag);
|
||||
ComputeFragmentAtom *cfa = (ComputeFragmentAtom *) modify->compute[icompute];
|
||||
cfa->compute_peratom();
|
||||
double *fragIDs = cfa->vector_atom;
|
||||
|
||||
// copy fragID to molecule ID for atoms in group
|
||||
|
||||
tagint *molecule = atom->molecule;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit)
|
||||
molecule[i] = static_cast<tagint> (fragIDs[i]);
|
||||
|
||||
// if compressflag = 0, done
|
||||
// set nchunk = -1 since cannot easily determine # of new molecule IDs
|
||||
|
||||
int nchunk = -1;
|
||||
|
||||
// if compressflag = 1, invoke peratom method of compute chunk/atom
|
||||
// will compress new molecule IDs to be contiguous 1 to Nmol
|
||||
// NOTE: use of compute chunk/atom limits Nmol to a 32-bit int
|
||||
|
||||
if (compressflag) {
|
||||
icompute = modify->find_compute(idchunk);
|
||||
ComputeChunkAtom *cca = (ComputeChunkAtom *) modify->compute[icompute];
|
||||
cca->compute_peratom();
|
||||
double *chunkIDs = cca->vector_atom;
|
||||
nchunk = cca->nchunk;
|
||||
|
||||
// if singleflag = 0, check if any single (no-bond) atoms exist
|
||||
// if so, they have fragID = 0, and compression just set their chunkID = 1
|
||||
// singleexist = 0/1 if no/yes single atoms exist with chunkID = 1
|
||||
|
||||
int singleexist = 0;
|
||||
if (!singleflag) {
|
||||
int mysingle = 0;
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit)
|
||||
if (fragIDs[i] == 0.0) mysingle = 1;
|
||||
MPI_Allreduce(&mysingle,&singleexist,1,MPI_INT,MPI_MAX,world);
|
||||
if (singleexist) nchunk--;
|
||||
}
|
||||
|
||||
// if offset < 0 (default), reset it
|
||||
// if group = all, offset = 0
|
||||
// else offset = largest molID of non-group atoms
|
||||
|
||||
if (offset < 0) {
|
||||
if (groupbit != 1) {
|
||||
tagint mymol = 0;
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
if (!(mask[i] & groupbit))
|
||||
mymol = MAX(mymol,molecule[i]);
|
||||
MPI_Allreduce(&mymol,&offset,1,MPI_LMP_TAGINT,MPI_MAX,world);
|
||||
} else offset = 0;
|
||||
}
|
||||
|
||||
// reset molecule ID for all atoms in group
|
||||
// newID = chunkID + offset
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
tagint newid = static_cast<tagint>(chunkIDs[i]);
|
||||
if (singleexist) {
|
||||
if (newid == 1) newid = 0;
|
||||
else newid += offset - 1;
|
||||
} else newid += offset;
|
||||
molecule[i] = newid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
|
||||
modify->delete_compute(idfrag);
|
||||
if (compressflag) modify->delete_compute(idchunk);
|
||||
|
||||
// total time
|
||||
|
||||
MPI_Barrier(world);
|
||||
|
||||
if (comm->me == 0) {
|
||||
if (nchunk < 0)
|
||||
utils::logmesg(lmp,fmt::format(" number of new molecule IDs = unknown\n"));
|
||||
else
|
||||
utils::logmesg(lmp,fmt::format(" number of new molecule IDs = {}\n",nchunk));
|
||||
utils::logmesg(lmp,fmt::format(" reset_mol_ids CPU = {:.3f} seconds\n",
|
||||
MPI_Wtime()-time1));
|
||||
}
|
||||
}
|
||||
60
src/reset_mol_ids.h
Normal file
60
src/reset_mol_ids.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
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
|
||||
|
||||
CommandStyle(reset_mol_ids,ResetMolIDs)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_RESET_MOL_IDS_H
|
||||
#define LMP_RESET_MOL_IDS_H
|
||||
|
||||
#include "pointers.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ResetMolIDs : protected Pointers {
|
||||
public:
|
||||
ResetMolIDs(class LAMMPS *);
|
||||
void command(int, char **);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Reset_mol_ids command before simulation box is defined
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
E: Can only use reset_mol_ids on molecular systems
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
E: Cannot use reset_mol_ids unless molecules have IDs
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
E: Reset_mol_ids missing %d bond topology atom IDs - use comm_modify cutoff
|
||||
|
||||
UNDOCUMENTED
|
||||
|
||||
*/
|
||||
@ -2,3 +2,8 @@
|
||||
add_executable(test_simple_commands test_simple_commands.cpp)
|
||||
target_link_libraries(test_simple_commands PRIVATE lammps GTest::GMock GTest::GTest)
|
||||
add_test(NAME SimpleCommands COMMAND test_simple_commands WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_reset_ids test_reset_ids.cpp)
|
||||
target_compile_definitions(test_reset_ids PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(test_reset_ids PRIVATE lammps GTest::GMock GTest::GTest)
|
||||
add_test(NAME ResetIDs COMMAND test_reset_ids WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
1
unittest/commands/data.fourmol
Symbolic link
1
unittest/commands/data.fourmol
Symbolic link
@ -0,0 +1 @@
|
||||
../force-styles/tests/data.fourmol
|
||||
1
unittest/commands/in.fourmol
Symbolic link
1
unittest/commands/in.fourmol
Symbolic link
@ -0,0 +1 @@
|
||||
../force-styles/tests/in.fourmol
|
||||
562
unittest/commands/test_reset_ids.cpp
Normal file
562
unittest/commands/test_reset_ids.cpp
Normal file
@ -0,0 +1,562 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
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 "atom.h"
|
||||
#include "fmt/format.h"
|
||||
#include "info.h"
|
||||
#include "input.h"
|
||||
#include "lammps.h"
|
||||
#include "output.h"
|
||||
#include "update.h"
|
||||
#include "utils.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <mpi.h>
|
||||
|
||||
// whether to print verbose output (i.e. not capturing LAMMPS screen output).
|
||||
bool verbose = false;
|
||||
|
||||
using LAMMPS_NS::utils::split_words;
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
using ::testing::MatchesRegex;
|
||||
|
||||
#define GETIDX(i) lmp->atom->map(i)
|
||||
|
||||
#define TEST_FAILURE(...) \
|
||||
if (Info::has_exceptions()) { \
|
||||
ASSERT_ANY_THROW({__VA_ARGS__}); \
|
||||
} else { \
|
||||
ASSERT_DEATH({__VA_ARGS__}, ""); \
|
||||
}
|
||||
|
||||
#define STRINGIFY(val) XSTR(val)
|
||||
#define XSTR(val) #val
|
||||
|
||||
class ResetIDsTest : public ::testing::Test {
|
||||
protected:
|
||||
LAMMPS *lmp;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
const char *args[] = {"ResetIDsTest", "-log", "none", "-nocite", "-echo", "screen"};
|
||||
char **argv = (char **)args;
|
||||
int argc = sizeof(args) / sizeof(char *);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp = new LAMMPS(argc, argv, MPI_COMM_WORLD);
|
||||
Info *info = new Info(lmp);
|
||||
if (info->has_style("atom", "full")) {
|
||||
lmp->input->one("variable input_dir index " STRINGIFY(TEST_INPUT_FOLDER));
|
||||
lmp->input->one("include ${input_dir}/in.fourmol");
|
||||
}
|
||||
delete info;
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
delete lmp;
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ResetIDsTest, MolIDAll)
|
||||
{
|
||||
if (lmp->atom->natoms == 0) GTEST_SKIP();
|
||||
|
||||
auto molid = lmp->atom->molecule;
|
||||
ASSERT_EQ(molid[GETIDX(1)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(21)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(28)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(29)], 6);
|
||||
|
||||
// the original data file has two different molecule IDs
|
||||
// for two residues of the same molecule/fragment.
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_mol_ids all");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(1)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(21)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(28)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(29)], 5);
|
||||
}
|
||||
|
||||
TEST_F(ResetIDsTest, DeletePlusAtomID)
|
||||
{
|
||||
if (lmp->atom->natoms == 0) GTEST_SKIP();
|
||||
|
||||
auto molid = lmp->atom->molecule;
|
||||
|
||||
// delete two water molecules
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("group allwater molecule 3:6");
|
||||
lmp->input->one("group twowater molecule 4:6:2");
|
||||
lmp->input->one("delete_atoms group twowater compress no bond yes");
|
||||
lmp->input->one("reset_mol_ids all");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_EQ(lmp->atom->natoms, 23);
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 26);
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(1)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 3);
|
||||
|
||||
// now also check and reset the atom ids
|
||||
|
||||
ASSERT_GE(GETIDX(1), 0);
|
||||
ASSERT_GE(GETIDX(2), 0);
|
||||
ASSERT_GE(GETIDX(3), 0);
|
||||
ASSERT_GE(GETIDX(4), 0);
|
||||
ASSERT_GE(GETIDX(5), 0);
|
||||
ASSERT_GE(GETIDX(6), 0);
|
||||
ASSERT_GE(GETIDX(7), 0);
|
||||
ASSERT_GE(GETIDX(8), 0);
|
||||
ASSERT_GE(GETIDX(9), 0);
|
||||
ASSERT_GE(GETIDX(10), 0);
|
||||
ASSERT_GE(GETIDX(11), 0);
|
||||
ASSERT_GE(GETIDX(12), 0);
|
||||
ASSERT_GE(GETIDX(13), 0);
|
||||
ASSERT_GE(GETIDX(14), 0);
|
||||
ASSERT_GE(GETIDX(15), 0);
|
||||
ASSERT_GE(GETIDX(16), 0);
|
||||
ASSERT_GE(GETIDX(17), 0);
|
||||
ASSERT_GE(GETIDX(18), 0);
|
||||
ASSERT_GE(GETIDX(19), 0);
|
||||
ASSERT_GE(GETIDX(20), 0);
|
||||
ASSERT_EQ(GETIDX(21), -1);
|
||||
ASSERT_EQ(GETIDX(22), -1);
|
||||
ASSERT_EQ(GETIDX(23), -1);
|
||||
ASSERT_GE(GETIDX(24), 0);
|
||||
ASSERT_GE(GETIDX(25), 0);
|
||||
ASSERT_GE(GETIDX(26), 0);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_atom_ids");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 23);
|
||||
for (int i = 1; i <= 23; ++i)
|
||||
ASSERT_GE(GETIDX(i), 0);
|
||||
}
|
||||
|
||||
TEST_F(ResetIDsTest, PartialOffset)
|
||||
{
|
||||
if (lmp->atom->natoms == 0) GTEST_SKIP();
|
||||
|
||||
auto molid = lmp->atom->molecule;
|
||||
|
||||
// delete two water molecules
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("group allwater molecule 3:6");
|
||||
lmp->input->one("group nowater subtract all allwater");
|
||||
lmp->input->one("reset_mol_ids allwater offset 4");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_EQ(lmp->atom->natoms, 29);
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 29);
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(1)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(21)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 7);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 7);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 7);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 8);
|
||||
ASSERT_EQ(molid[GETIDX(28)], 8);
|
||||
ASSERT_EQ(molid[GETIDX(29)], 8);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_mol_ids nowater offset 0");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(1)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(21)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 7);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 7);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 7);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 8);
|
||||
ASSERT_EQ(molid[GETIDX(28)], 8);
|
||||
ASSERT_EQ(molid[GETIDX(29)], 8);
|
||||
}
|
||||
|
||||
TEST_F(ResetIDsTest, DeleteAdd)
|
||||
{
|
||||
if (lmp->atom->natoms == 0) GTEST_SKIP();
|
||||
|
||||
auto molid = lmp->atom->molecule;
|
||||
|
||||
// delete two water molecules
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("group allwater molecule 3:6");
|
||||
lmp->input->one("group twowater molecule 4:6:2");
|
||||
lmp->input->one("group nowater subtract all allwater");
|
||||
lmp->input->one("delete_atoms group twowater compress no bond yes mol yes");
|
||||
lmp->input->one("reset_mol_ids allwater");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_EQ(lmp->atom->natoms, 23);
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 26);
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(1)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 1);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 4);
|
||||
|
||||
// now also check and reset the atom ids
|
||||
|
||||
ASSERT_GE(GETIDX(1), 0);
|
||||
ASSERT_GE(GETIDX(2), 0);
|
||||
ASSERT_GE(GETIDX(3), 0);
|
||||
ASSERT_GE(GETIDX(4), 0);
|
||||
ASSERT_GE(GETIDX(5), 0);
|
||||
ASSERT_GE(GETIDX(6), 0);
|
||||
ASSERT_GE(GETIDX(7), 0);
|
||||
ASSERT_GE(GETIDX(8), 0);
|
||||
ASSERT_GE(GETIDX(9), 0);
|
||||
ASSERT_GE(GETIDX(10), 0);
|
||||
ASSERT_GE(GETIDX(11), 0);
|
||||
ASSERT_GE(GETIDX(12), 0);
|
||||
ASSERT_GE(GETIDX(13), 0);
|
||||
ASSERT_GE(GETIDX(14), 0);
|
||||
ASSERT_GE(GETIDX(15), 0);
|
||||
ASSERT_GE(GETIDX(16), 0);
|
||||
ASSERT_GE(GETIDX(17), 0);
|
||||
ASSERT_GE(GETIDX(18), 0);
|
||||
ASSERT_GE(GETIDX(19), 0);
|
||||
ASSERT_GE(GETIDX(20), 0);
|
||||
ASSERT_EQ(GETIDX(21), -1);
|
||||
ASSERT_EQ(GETIDX(22), -1);
|
||||
ASSERT_EQ(GETIDX(23), -1);
|
||||
ASSERT_GE(GETIDX(24), 0);
|
||||
ASSERT_GE(GETIDX(25), 0);
|
||||
ASSERT_GE(GETIDX(26), 0);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_atom_ids sort yes");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 23);
|
||||
for (int i = 1; i <= 23; ++i)
|
||||
ASSERT_GE(GETIDX(i), 0);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_mol_ids nowater offset 1");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(1)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(2)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(3)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(4)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(5)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(6)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(7)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(8)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(9)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(10)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(11)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(12)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(13)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(14)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(15)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(16)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(17)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(18)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(19)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(20)], 2);
|
||||
ASSERT_EQ(molid[GETIDX(21)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 4);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("create_atoms 1 single 0.0 0.0 0.0");
|
||||
lmp->input->one("create_atoms 2 single 1.0 0.0 0.0");
|
||||
lmp->input->one("create_atoms 3 single 2.0 0.0 0.0");
|
||||
lmp->input->one("create_atoms 4 single 3.0 0.0 0.0");
|
||||
lmp->input->one("reset_mol_ids all single yes");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_EQ(lmp->atom->natoms, 27);
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 27);
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(21)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 4);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 5);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 6);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 7);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_mol_ids all single no");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(21)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 3);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 0);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 0);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 0);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 0);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_mol_ids all compress no single yes");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
ASSERT_EQ(molid[GETIDX(21)], 21);
|
||||
ASSERT_EQ(molid[GETIDX(22)], 21);
|
||||
ASSERT_EQ(molid[GETIDX(23)], 21);
|
||||
ASSERT_EQ(molid[GETIDX(24)], 24);
|
||||
ASSERT_EQ(molid[GETIDX(25)], 25);
|
||||
ASSERT_EQ(molid[GETIDX(26)], 26);
|
||||
ASSERT_EQ(molid[GETIDX(27)], 27);
|
||||
}
|
||||
|
||||
TEST_F(ResetIDsTest, DeathTests)
|
||||
{
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids"););
|
||||
auto mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all offset 1 1"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all offset -2"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all offset xxx"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR on proc 0: Expected integer.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all compress yes single no offset xxx"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR on proc 0: Expected integer.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all offset"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all compress"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all compress xxx"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all single"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all single xxx"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Illegal reset_mol_ids command.*"));
|
||||
}
|
||||
|
||||
TEST(ResetMolIds, CMDFail)
|
||||
{
|
||||
LAMMPS *lmp;
|
||||
const char *args[] = {"ResetIDsTest", "-log", "none", "-nocite", "-echo", "screen"};
|
||||
char **argv = (char **)args;
|
||||
int argc = sizeof(args) / sizeof(char *);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp = new LAMMPS(argc, argv, MPI_COMM_WORLD);
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all"););
|
||||
auto mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Reset_mol_ids command before.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
lmp->input->one("atom_modify id no");
|
||||
lmp->input->one("region box block 0 1 0 1 0 1");
|
||||
lmp->input->one("create_box 1 box");
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Cannot use reset_mol_ids unl.*"));
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
lmp->input->one("clear");
|
||||
lmp->input->one("region box block 0 1 0 1 0 1");
|
||||
lmp->input->one("create_box 1 box");
|
||||
TEST_FAILURE(lmp->input->one("reset_mol_ids all"););
|
||||
mesg = ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(mesg, MatchesRegex(".*ERROR: Can only use reset_mol_ids.*"));
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
delete lmp;
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
};
|
||||
|
||||
} // namespace LAMMPS_NS
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
|
||||
// handle arguments passed via environment variable
|
||||
if (const char *var = getenv("TEST_ARGS")) {
|
||||
std::vector<std::string> env = split_words(var);
|
||||
for (auto arg : env) {
|
||||
if (arg == "-v") {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true;
|
||||
|
||||
int rv = RUN_ALL_TESTS();
|
||||
MPI_Finalize();
|
||||
return rv;
|
||||
}
|
||||
@ -423,7 +423,7 @@ TEST_F(AtomStyleTest, atomic)
|
||||
ASSERT_EQ(lmp->atom->map_user, 1);
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 3);
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_ids");
|
||||
lmp->input->one("reset_atom_ids");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 2);
|
||||
ASSERT_EQ(lmp->atom->tag_consecutive(), 1);
|
||||
@ -810,7 +810,7 @@ TEST_F(AtomStyleTest, charge)
|
||||
ASSERT_EQ(lmp->atom->mass_setflag[2], 1);
|
||||
|
||||
if (!verbose) ::testing::internal::CaptureStdout();
|
||||
lmp->input->one("reset_ids");
|
||||
lmp->input->one("reset_atom_ids");
|
||||
lmp->input->one("replicate 2 2 2");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_EQ(lmp->atom->map_tag_max, 16);
|
||||
@ -1137,7 +1137,7 @@ TEST_F(AtomStyleTest, sphere)
|
||||
EXPECT_THAT(std::string(lmp->atom->atom_style), Eq("atomic"));
|
||||
lmp->input->one("read_restart test_atom_styles.restart");
|
||||
lmp->input->one("replicate 1 1 2");
|
||||
lmp->input->one("reset_ids");
|
||||
lmp->input->one("reset_atom_ids");
|
||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||
ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("sphere"));
|
||||
ASSERT_NE(lmp->atom->avec, nullptr);
|
||||
|
||||
Reference in New Issue
Block a user