/* * Pop and process the next molecule on the workStack (private). */ void ClusterIdentifier::processNextMolecule(Cluster& cluster) { CellList::NeighborArray neighborArray; Molecule::AtomIterator atomIter; ClusterLink* thisLinkPtr; ClusterLink* otherLinkPtr; Atom* otherAtomPtr; Boundary& boundary = system().boundary(); double cutoffSq = cutoff_*cutoff_; double rsq; int thisMolId, otherMolId, otherClusterId; // Pop this molecule off the stack thisLinkPtr = &workStack_.pop(); thisMolId = thisLinkPtr->molecule().id(); if (thisLinkPtr->clusterId() != cluster.id()) { UTIL_THROW("Top ClusterLink not marked with this cluster id"); } /* * Loop over atoms of this molecule. * For each atom of type atomTypeId_, find neighboring molecules. * Add each new neighbor to the cluster, and to the workStack. */ thisLinkPtr->molecule().begin(atomIter); for ( ; atomIter.notEnd(); ++atomIter) { if (atomIter->typeId() == atomTypeId_) { cellList_.getNeighbors(atomIter->position(), neighborArray); for (int i = 0; i < neighborArray.size(); i++) { otherAtomPtr = neighborArray[i]; otherMolId = otherAtomPtr->molecule().id(); if (otherMolId != thisMolId) { rsq = boundary.distanceSq(atomIter->position(), otherAtomPtr->position()); if (rsq < cutoffSq) { otherLinkPtr = &(links_[otherMolId]); assert(&otherLinkPtr->molecule() == &otherAtomPtr->molecule()); otherClusterId = otherLinkPtr->clusterId(); if (otherClusterId == -1) { cluster.addLink(*otherLinkPtr); workStack_.push(*otherLinkPtr); } else if (otherClusterId != cluster.id()) { UTIL_THROW("Cluster Clash!"); } } } } // neighbor atoms } } // atoms }
/* * Identify all clusters in the system. */ void ClusterIdentifier::identifyClusters() { // Initialize all data structures: // Setup a grid of empty cells cellList_.setup(system().boundary(), cutoff_); // Clear clusters array and all links clusters_.clear(); for (int i = 0; i < links_.capacity(); ++i) { links_[i].clear(); } // Build the cellList, associate Molecule with ClusterLink. // Iterate over molecules of species speciesId_ System::MoleculeIterator molIter; Molecule::AtomIterator atomIter; system().begin(speciesId_, molIter); for ( ; molIter.notEnd(); ++molIter) { // Associate this Molecule with a ClusterLink links_[molIter->id()].setMolecule(*molIter.get()); // Add atoms of type = atomTypeId_ to the CellList for (molIter->begin(atomIter); atomIter.notEnd(); ++atomIter) { if (atomIter->typeId() == atomTypeId_) { system().boundary().shift(atomIter->position()); cellList_.addAtom(*atomIter); } } } // Identify all clusters Cluster* clusterPtr; ClusterLink* linkPtr; int clusterId = 0; system().begin(speciesId_, molIter); for ( ; molIter.notEnd(); ++molIter) { // Find the link with same index as this molecule linkPtr = &(links_[molIter->id()]); assert (&(linkPtr->molecule()) == molIter.get()); // If this link is not in a cluster, begin a new cluster if (linkPtr->clusterId() == -1) { // Add a new empty cluster to clusters_ array clusters_.resize(clusterId+1); clusterPtr = &clusters_[clusterId]; clusterPtr->clear(); clusterPtr->setId(clusterId); // Identify molecules in this cluster clusterPtr->addLink(*linkPtr); workStack_.push(*linkPtr); while (workStack_.size() > 0) { processNextMolecule(*clusterPtr); } clusterId++; } } // Validity check - throws exception on failure. isValid(); }