18 namespace bg = boost::geometry;
62 linkedList.
resize(yCloud->nop, -1);
65 for (
int iatom = 0; iatom < yCloud->nop; iatom++) {
67 if ((*isIce)[iatom] ==
false || yCloud->pts[iatom].inSlice ==
false) {
71 linkedList[iatom] = iatom;
75 for (
int i = 0; i < yCloud->nop - 1; i++) {
78 if (linkedList[i] == -1) {
83 if (linkedList[i] != i) {
92 for (
int k = i + 1; k < yCloud->nop; k++) {
94 if ((*isIce)[k] ==
false) {
98 if (linkedList[k] != k) {
103 kAtomID = yCloud->pts[k].atomID;
104 auto it =
std::find(nList[j].begin() + 1, nList[j].end(), kAtomID);
105 if (it != nList[j].end()) {
107 temp = linkedList[j];
108 linkedList[j] = linkedList[k];
109 linkedList[k] = temp;
125 visited.
resize(yCloud->nop);
127 for (
int i = 0; i < yCloud->nop; i++) {
133 if (linkedList[i] == -1) {
136 if (linkedList[i] == i) {
141 nextElement = linkedList[currentIndex];
144 while (nextElement != index) {
146 currentIndex = nextElement;
147 visited[currentIndex] =
true;
148 nextElement = linkedList[currentIndex];
153 (*nClusters).push_back(iClusterNumber);
157 nLargestCluster = *
std::max_element((*nClusters).begin(), (*nClusters).end());
159 (*nClusters).begin(),
161 (*nClusters).begin(),
162 (*nClusters).end()));
167 startingIndex[lClusIndex];
170 index = startCluster;
172 iPoint = yCloud->pts[index];
173 iceCloud->pts.push_back(iPoint);
175 nextElement = linkedList[startCluster];
176 while (nextElement != index) {
177 currentIndex = nextElement;
179 iPoint = yCloud->pts[currentIndex];
180 iceCloud->pts.push_back(iPoint);
182 nextElement = linkedList[currentIndex];
187 iceCloud->currentFrame = yCloud->currentFrame;
188 iceCloud->nop = iceCloud->pts.
size();
189 iceCloud->box = yCloud->box;
190 iceCloud->boxLow = yCloud->boxLow;
193 for (
int iatom = 0; iatom < iceCloud->nop; iceCloud++) {
194 iceCloud->idIndexMap[iceCloud->pts[iatom].atomID] = iatom;
199 int totalClusters = (*nClusters).size();
200 int smallestCluster = nLargestCluster =
203 double avgClusterSize = 0.0;
206 for (
int iCluster = 0; iCluster < totalClusters; iCluster++) {
207 avgClusterSize += (*nClusters)[iCluster];
210 if (totalClusters == 0) {
213 avgClusterSize /= totalClusters;
216 iceCloud->currentFrame = yCloud->currentFrame;
217 nLargestCluster = (*nClusters)[lClusIndex];
221 totalClusters, smallestCluster, avgClusterSize,
246 (*linkedList).resize(iceCloud->nop);
248 for (
int iatom = 0; iatom < iceCloud->nop; iatom++) {
250 (*linkedList)[iatom] = iatom;
254 for (
int i = 0; i < iceCloud->nop - 1; i++) {
257 if ((*linkedList)[i] != i) {
266 for (
int k = i + 1; k < iceCloud->nop; k++) {
268 if ((*linkedList)[k] != k) {
273 auto it =
std::find(nList[j].begin() + 1, nList[j].end(), k);
274 if (it != nList[j].end()) {
276 temp = (*linkedList)[j];
277 (*linkedList)[j] = (*linkedList)[k];
278 (*linkedList)[k] = temp;
282 j = (*linkedList)[j];
335 isIce.
resize(yCloud->nop);
340 if (bopAnalysis ==
"q6") {
347 for (
int iatom = 0; iatom < yCloud->nop; iatom++) {
349 if (q6Values[iatom] > 0.5) {
358 if (bopAnalysis ==
"chill") {
364 for (
int iatom = 0; iatom < yCloud->nop; iatom++) {
380 &nClusters, &indexNumber, firstFrame);
406 double xBoxCenter, yBoxCenter, zBoxCenter;
407 double x_centroid, y_centroid, z_centroid;
413 for (
int k = 0; k < dim; k++) {
423 visited.
resize(iceCloud->nop);
430 double x_ij, y_ij, z_ij;
431 double xPBC, yPBC, zPBC;
434 for (
int i = 0; i < iceCloud->nop; i++) {
441 if (linkedList[i] == i) {
446 nextElement = linkedList[currentIndex];
449 while (nextElement != index) {
450 currentIndex = nextElement;
451 visited[currentIndex] =
true;
452 nextElement = linkedList[currentIndex];
458 x_ij = iceCloud->pts[currentIndex].x - iceCloud->pts[nextElement].x;
459 y_ij = iceCloud->pts[currentIndex].y - iceCloud->pts[nextElement].y;
460 z_ij = iceCloud->pts[currentIndex].z - iceCloud->pts[nextElement].z;
463 if (fabs(x_ij) > 0.5 * box[0]) {
465 xPBC = box[0] - fabs(x_ij);
467 iceCloud->pts[nextElement].x = iceCloud->pts[currentIndex].x - xPBC;
470 iceCloud->pts[nextElement].x = iceCloud->pts[currentIndex].x + xPBC;
475 if (fabs(y_ij) > 0.5 * box[1]) {
477 yPBC = box[1] - fabs(y_ij);
479 iceCloud->pts[nextElement].y = iceCloud->pts[currentIndex].y - yPBC;
482 iceCloud->pts[nextElement].y = iceCloud->pts[currentIndex].y + yPBC;
487 if (fabs(z_ij) > 0.5 * box[2]) {
489 zPBC = box[2] - fabs(z_ij);
491 iceCloud->pts[nextElement].z = iceCloud->pts[currentIndex].z - zPBC;
494 iceCloud->pts[nextElement].z = iceCloud->pts[currentIndex].z + zPBC;
505 xBoxCenter = 0.5 * (boxLow[0] + boxHigh[0]);
506 yBoxCenter = 0.5 * (boxLow[1] + boxHigh[1]);
507 zBoxCenter = 0.5 * (boxLow[2] + boxHigh[2]);
514 for (
int i = 0; i < iceCloud->nop; i++) {
515 x_centroid += iceCloud->pts[i].x;
516 y_centroid += iceCloud->pts[i].y;
517 z_centroid += iceCloud->pts[i].z;
520 if (iceCloud->nop == 0) {
521 std::cerr <<
"There are no particles in the cluster.\n";
526 x_centroid /= iceCloud->nop;
527 y_centroid /= iceCloud->nop;
528 z_centroid /= iceCloud->nop;
532 double xShift = x_centroid - xBoxCenter;
533 double yShift = y_centroid - yBoxCenter;
534 double zShift = z_centroid - zBoxCenter;
537 for (
int i = 0; i < iceCloud->nop; i++) {
538 iceCloud->pts[i].x -= xShift;
539 iceCloud->pts[i].y -= yShift;
540 iceCloud->pts[i].z -= zShift;
File for the bond order parameter analysis.
std::vector< double > getq6(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, bool isSlice=false)
molSys::PointCloud< molSys::Point< double >, double > getCorrel(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, bool isSlice=false)
molSys::PointCloud< molSys::Point< double >, double > getIceTypeNoPrint(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, bool isSlice=false)
Classifies each atom according to the CHILL algorithm without printing.
int recenterClusterCloud(molSys::PointCloud< molSys::Point< double >, double > *iceCloud, std::vector< std::vector< int >> nList)
Recenters the coordinates of a pointCloud.
int singleClusterLinkedList(molSys::PointCloud< molSys::Point< double >, double > *iceCloud, std::vector< std::vector< int >> nList, std::vector< int > *linkedList)
int largestIceCluster(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud, molSys::PointCloud< molSys::Point< double >, double > *iceCloud, std::vector< std::vector< int >> nList, std::vector< bool > *isIce, std::vector< int > *clusterID, std::vector< int > *nClusters, std::unordered_map< int, int > *indexNumber, int firstFrame)
Finds the largest ice cluster.
int clusterAnalysis(std::string path, molSys::PointCloud< molSys::Point< double >, double > *iceCloud, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, std::vector< std::vector< int >> &iceNeighbourList, double cutoff, int firstFrame, std::string bopAnalysis="q6")
double distance(molSys::PointCloud< molSys::Point< double >, double > *yCloud, int iatom, int jatom)
Inline generic function for obtaining the wrapped distance between two particles WITHOUT applying PBC...
molSys::PointCloud< molSys::Point< double >, double > clearPointCloud(molSys::PointCloud< molSys::Point< double >, double > *yCloud)
//! Function for clearing vectors in PointCloud after multiple usage
@ water
Liquid/amorphous phase.
@ unclassified
Not classified into any other category.
int clearNeighbourList(std::vector< std::vector< int >> &nList)
Erases memory for a vector of vectors for the neighbour list.
std::vector< std::vector< int > > getNewNeighbourListByIndex(molSys::PointCloud< molSys::Point< double >, double > *yCloud, double cutoff)
int writeClusterStats(std::string path, int currentFrame, int largestCluster, int numOfClusters, int smallestCluster, double avgClusterSize, int firstFrame)
Function for writing out cluster statistics.
This contains a collection of points; contains information for a particular frame.
This contains per-particle information.