diff --git a/doc/src/compute_cluster_atom.rst b/doc/src/compute_cluster_atom.rst index 502d2858d0..a4017171c9 100644 --- a/doc/src/compute_cluster_atom.rst +++ b/doc/src/compute_cluster_atom.rst @@ -15,12 +15,13 @@ Syntax .. parsed-literal:: compute ID group-ID cluster/atom cutoff - compute ID group-ID fragment/atom + compute ID group-ID fragment/atom [singlezero] compute ID group-ID aggregate/atom cutoff * ID, group-ID are documented in :doc:`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) +* *singlezero* = keyword to trigger assigning an ID of 0 to fragments with a single atom (optional) Examples """""""" @@ -52,6 +53,12 @@ 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. +The *singlezero* keyword turns on a special treatment for fragments, +where all fragments within the compute group that contain only a single +atom will have a fragment ID of 0. This can be useful in cases where +the fragment IDs are used as input for other commands in LAMMPS that +treat such single atoms different. + 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 distance from one or more atoms within a fragment that is part of diff --git a/src/compute_fragment_atom.cpp b/src/compute_fragment_atom.cpp index 6239ea9101..e71593ce3d 100644 --- a/src/compute_fragment_atom.cpp +++ b/src/compute_fragment_atom.cpp @@ -38,7 +38,12 @@ 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"); + singleflag = 0; + + if ((narg < 3) || (narg > 4)) + error->all(FLERR,"Illegal compute fragment/atom command"); + if ((narg == 4) && (strcmp(arg[3],"singlezero") == 0)) + singleflag = 1; if (atom->avec->bonds_allow == 0) error->all(FLERR,"Compute fragment/atom used when bonds are not allowed"); @@ -114,6 +119,7 @@ void ComputeFragmentAtom::compute_peratom() // owned + ghost atoms start with fragmentID = atomID // atoms not in group have fragmentID = 0 + // if singleflag is set atoms without bonds have fragmentID 0 as well. tagint *tag = atom->tag; int *mask = atom->mask; @@ -122,9 +128,10 @@ void ComputeFragmentAtom::compute_peratom() int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; - for (i = 0; i < nall; i++) + for (i = 0; i < nall; i++) { if (mask[i] & groupbit) fragmentID[i] = tag[i]; else fragmentID[i] = 0; + } // loop until no ghost atom fragment ID is changed // acquire fragmentIDs of ghost atoms @@ -152,9 +159,16 @@ void ComputeFragmentAtom::compute_peratom() for (i = 0; i < nlocal; i++) { // skip atom I if not in group or already marked + // also skip and set fragment ID to zero if singleflag is set + // and the atom is an isolated atom without bonds if (!(mask[i] & groupbit)) continue; if (markflag[i]) continue; + if (singleflag && (nspecial[i][0] == 0)) { + fragmentID[i] = 0; + markflag[i] = 1; + continue; + } // find one cluster of bond-connected atoms // ncluster = # of owned and ghost atoms in cluster @@ -165,44 +179,44 @@ void ComputeFragmentAtom::compute_peratom() stack[nstack++] = i; while (nstack) { - j = stack[--nstack]; - clist[ncluster++] = j; - markflag[j] = 1; + j = stack[--nstack]; + clist[ncluster++] = j; + markflag[j] = 1; - n = nspecial[j][0]; - list = special[j]; + 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 - - if (k < 0) continue; - if (!(mask[k] & groupbit)) continue; - if (k < nlocal && markflag[k]) continue; + // skip bond neighbor K if not in group or already marked - // 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 (k < 0) continue; + if (!(mask[k] & groupbit)) continue; + if (k < nlocal && markflag[k]) continue; + + // 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; + } } // 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); + 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; + j = clist[m]; + if (j >= nlocal && fragmentID[j] != newID) done = 0; + fragmentID[j] = newID; } } diff --git a/src/compute_fragment_atom.h b/src/compute_fragment_atom.h index 1422a71fb4..e5cc2a5b6f 100644 --- a/src/compute_fragment_atom.h +++ b/src/compute_fragment_atom.h @@ -35,7 +35,7 @@ class ComputeFragmentAtom : public Compute { double memory_usage(); private: - int nmax,commflag; + int nmax,commflag,singleflag; int *stack,*clist,*markflag; double *fragmentID; };