43 std::vector<std::vector<int>> nList, std::vector<bool> *isIce,
44 std::vector<int> *list, std::vector<int> *nClusters,
45 std::unordered_map<int, int> *indexNumber,
int firstFrame) {
50 std::vector<int> linkedList;
52 std::vector<int> startingIndex;
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];
151 startingIndex.push_back(index);
153 (*nClusters).push_back(iClusterNumber);
157 nLargestCluster = *std::max_element((*nClusters).begin(), (*nClusters).end());
158 int lClusIndex = distance(
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 =
201 *std::min_element((*nClusters).begin(),
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,
239 std::vector<std::vector<int>> nList, std::vector<int> *linkedList) {
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];
316 std::vector<std::vector<int>> nList,
317 std::vector<std::vector<int>> &iceNeighbourList,
double cutoff,
318 int firstFrame, std::string bopAnalysis) {
320 std::vector<bool> isIce;
322 std::vector<int> clusterID;
324 std::vector<int> nClusters;
325 std::unordered_map<int, int>
335 isIce.resize(yCloud->nop);
340 if (bopAnalysis ==
"q6") {
342 std::vector<double> q6Values;
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);
400 std::vector<std::vector<int>> nList) {
403 std::vector<double> box = iceCloud->box;
404 std::vector<double> boxLow = iceCloud->boxLow;
405 std::vector<double> boxHigh;
406 double xBoxCenter, yBoxCenter, zBoxCenter;
407 double x_centroid, y_centroid, z_centroid;
409 std::vector<int> linkedList;
410 std::vector<bool> visited;
413 for (
int k = 0; k < dim; k++) {
414 boxHigh.push_back(boxLow[k] + box[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;
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 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")
int writeClusterStats(std::string path, int currentFrame, int largestCluster, int numOfClusters, int smallestCluster, double avgClusterSize, int firstFrame)
Function for writing out cluster statistics.