53 int *atomID,
int firstFrame,
int currentFrame,
bool doShapeMatching) {
73 double avgPrismHeight = 2.845;
81 nDefPrismList.
resize(maxDepth - 2);
82 heightPercent.
resize(maxDepth - 2);
84 atomTypes.
resize(yCloud->nop, 1);
87 rmsdPerAtom.
resize(yCloud->nop, -1);
89 atomState.
resize(yCloud->nop);
93 for (
int ringSize = 3; ringSize <= maxDepth; ringSize++) {
100 if (ringsOneType.
size() == 0) {
101 nPrismList[ringSize - 3] = 0;
102 nDefPrismList[ringSize - 3] = 0;
103 heightPercent[ringSize - 3] = 0.0;
112 nImperfectPrisms = 0;
114 ringsOneType.
size());
119 &nImperfectPrisms, nList, yCloud, &rmsdPerAtom,
122 nPrismList[ringSize - 3] =
124 nDefPrismList[ringSize - 3] =
126 int totalPrisms = nPerfectPrisms + nImperfectPrisms;
128 heightPercent[ringSize - 3] =
131 if (nPerfectPrisms + nImperfectPrisms == 0) {
139 &atomTypes, &atomState);
147 yCloud->currentFrame, firstFrame);
149 if (doShapeMatching) {
158 if (doShapeMatching) {
199 int totalRingNum = rings.
size();
207 int ringSize = rings[0].
size();
208 *nImperfectPrisms = 0;
211 Eigen::MatrixXd refPointSet(ringSize, 3);
221 for (
int iring = 0; iring < totalRingNum - 1; iring++) {
224 basal1 = rings[iring];
226 for (
int jring = iring + 1; jring < totalRingNum; jring++) {
227 basal2 = rings[jring];
230 if (doShapeMatching ==
true || ringSize == 4) {
234 if (isAxialPair ==
false) {
251 if (cond2 ==
false) {
253 if (!doShapeMatching) {
261 if (relaxedCond ==
false) {
267 yCloud, nList, refPointSet, &basal1, &basal2, rmsdPerAtom,
false);
270 if (isDeformedPrism) {
273 *nImperfectPrisms += 1;
298 *nPerfectPrisms += 1;
315 if (doShapeMatching) {
317 yCloud, nList, refPointSet, &basal1, &basal2, rmsdPerAtom,
true);
331 sort(listPrism.
begin(), listPrism.
end());
354 int l1 = (*basal1)[0];
369 for (
int k = 0; k < ringSize; k++) {
370 l1_neighbour =
false;
375 auto it =
std::find(nList[l1].begin() + 1, nList[l1].end(), m_k);
378 if (it != nList[l1].end()) {
393 isNeighbour[kIndex] =
true;
396 for (
int i = 1; i < ringSize; i++) {
397 lAtomID = (*basal1)[i];
398 for (
int k = 0; k < ringSize; k++) {
400 if (isNeighbour[k]) {
404 kAtomID = (*basal2)[k];
409 std::find(nList[lAtomID].begin() + 1, nList[lAtomID].end(), kAtomID);
412 if (it1 != nList[lAtomID].end()) {
413 isNeighbour[k] =
true;
421 for (
int k = 0; k < ringSize; k++) {
423 if (!isNeighbour[k]) {
442 bool isNeighbour =
false;
449 for (
int l = 0; l < ringSize; l++) {
453 for (
int m = 0; m < ringSize; m++) {
456 auto it =
std::find(nList[l_k].begin() + 1, nList[l_k].end(), m_k);
459 if (it != nList[l_k].end()) {
498 bool axialBasal1, axialBasal2;
500 double areaXY, areaXZ,
521 jatomIndex = (*basal1)[0];
524 for (
int k = 1; k < ringSize; k++) {
525 iatomIndex = (*basal1)[k];
530 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
531 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
534 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
535 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
538 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
539 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
541 jatomIndex = iatomIndex;
545 iatomIndex = (*basal1)[0];
548 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
549 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
552 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
553 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
556 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
557 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
564 areaXY = fabs(areaXY);
565 areaXZ = fabs(areaXZ);
566 areaYZ = fabs(areaYZ);
573 if (areaYZ > areaXY && areaYZ > areaXZ) {
578 else if (axialDim == 1) {
579 if (areaXZ > areaXY && areaXZ > areaYZ) {
584 else if (axialDim == 2) {
585 if (areaXY > areaXZ && areaXY > areaYZ) {
590 std::cerr <<
"Could not find the axial dimension.\n";
601 jatomIndex = (*basal2)[0];
604 for (
int k = 1; k < ringSize; k++) {
605 iatomIndex = (*basal2)[k];
610 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
611 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
614 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
615 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
618 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
619 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
621 jatomIndex = iatomIndex;
625 iatomIndex = (*basal2)[0];
628 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
629 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
632 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
633 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
636 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
637 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
644 areaXY = fabs(areaXY);
645 areaXZ = fabs(areaXZ);
646 areaYZ = fabs(areaYZ);
654 if (areaYZ > areaXY && areaYZ > areaXZ) {
659 else if (axialDim == 1) {
660 if (areaXZ > areaXY && areaXZ > areaYZ) {
665 else if (axialDim == 2) {
666 if (areaXY > areaXZ && areaXY > areaYZ) {
671 std::cerr <<
"Could not find the axial dimension.\n";
677 if (axialBasal1 ==
true && axialBasal2 ==
true) {
712 for (
int i = 0; i < listPrism.
size(); i++) {
713 iring = listPrism[i];
715 currentState = ringType[iring];
717 for (
int j = 0; j < ringSize; j++) {
718 iatom = rings[iring][j];
720 (*atomTypes)[iatom] = ringSize;
724 (*atomState)[iatom] = currentState;
727 if ((*atomState)[iatom] != currentState) {
730 (*atomState)[iatom] = currentState;
762 int nop = atomState.
size();
765 for (
int iatom = 0; iatom < nop; iatom++) {
769 (*atomTypes)[iatom] += maxDepth - 2;
772 (*atomTypes)[iatom] = 2;
793 int firstFrame,
int currentFrame) {
796 double shiftDistance;
797 double distFrmBoundary;
803 if (axialDim < 0 || axialDim > 2) {
807 double boxLowAxial = yCloud->boxLow[axialDim];
808 double boxHighAxial = boxLowAxial + yCloud->box[axialDim];
814 if (currentFrame == firstFrame) {
815 *atomID = yCloud->pts[0].atomID;
820 int iatomID = *atomID;
822 auto it = yCloud->idIndexMap.find(iatomID);
824 if (it != yCloud->idIndexMap.end()) {
825 atomIndex = it->second;
836 shiftDistance = boxLowAxial - yCloud->pts[atomIndex].x;
838 else if (axialDim == 1) {
839 shiftDistance = boxLowAxial - yCloud->pts[atomIndex].y;
842 shiftDistance = boxLowAxial - yCloud->pts[atomIndex].z;
846 for (
int iatom = 0; iatom < yCloud->nop; iatom++) {
849 yCloud->pts[iatom].x += shiftDistance;
851 if (yCloud->pts[iatom].x < boxLowAxial) {
852 distFrmBoundary = boxLowAxial - yCloud->pts[iatom].x;
853 yCloud->pts[iatom].x = boxHighAxial - distFrmBoundary;
856 else if (axialDim == 1) {
857 yCloud->pts[iatom].y += shiftDistance;
859 if (yCloud->pts[iatom].y < boxLowAxial) {
860 distFrmBoundary = boxLowAxial - yCloud->pts[iatom].y;
861 yCloud->pts[iatom].y = boxHighAxial - distFrmBoundary;
865 yCloud->pts[iatom].z += shiftDistance;
867 if (yCloud->pts[iatom].z < boxLowAxial) {
868 distFrmBoundary = boxLowAxial - yCloud->pts[iatom].z;
869 yCloud->pts[iatom].z = boxHighAxial - distFrmBoundary;
bool relaxedPrismConditions(std::vector< std::vector< int >> nList, std::vector< int > *basal1, std::vector< int > *basal2)
int prismAnalysis(std::string path, std::vector< std::vector< int >> rings, std::vector< std::vector< int >> nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, int maxDepth, int *atomID, int firstFrame, int currentFrame, bool doShapeMatching=false)
std::vector< int > findPrisms(std::vector< std::vector< int >> rings, std::vector< strucType > *ringType, int *nPerfectPrisms, int *nImperfectPrisms, std::vector< std::vector< int >> nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > *rmsdPerAtom, bool doShapeMatching=false)
int deformedPrismTypes(std::vector< ring::strucType > atomState, std::vector< int > *atomTypes, int maxDepth)
Get the atom type values for deformed prisms.
int clearRingList(std::vector< std::vector< int >> &rings)
Erases memory for a vector of vectors for a list of rings.
bool discardExtraTetragonBlocks(std::vector< int > *basal1, std::vector< int > *basal2, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
int rmAxialTranslations(molSys::PointCloud< molSys::Point< double >, double > *yCloud, int *atomID, int firstFrame, int currentFrame)
Shift the entire ice nanotube and remove axial translations.
int assignPrismType(std::vector< std::vector< int >> rings, std::vector< int > listPrism, int ringSize, std::vector< ring::strucType > ringType, std::vector< int > *atomTypes, std::vector< ring::strucType > *atomState)
bool hasCommonElements(std::vector< int > ring1, std::vector< int > ring2)
bool basalPrismConditions(std::vector< std::vector< int >> nList, std::vector< int > *basal1, std::vector< int > *basal2)
std::vector< std::vector< int > > getSingleRingSize(std::vector< std::vector< int >> rings, int ringSize)
Returns a vector of vectors of rings of a single size.
@ Prism
The ring belongs to a prism block, classified according to the prism identification scheme.
@ unclassified
The ring is unclassified, which may be either water or a deformed type which cannot be classified by ...
bool matchPrism(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, const Eigen::MatrixXd &refPoints, std::vector< int > *basal1, std::vector< int > *basal2, std::vector< double > *rmsdPerAtom, bool isPerfect=true)
Eigen::MatrixXd getPointSetRefRing(int n, int axialDim)
int writePrismNum(std::string path, std::vector< int > nPrisms, std::vector< int > nDefPrisms, std::vector< double > heightPercent, int maxDepth, int currentFrame, int firstFrame)
int writeLAMMPSdumpINT(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > rmsdPerAtom, std::vector< int > atomTypes, int maxDepth, std::string path)
Write out a LAMMPS dump file containing the RMSD per atom.
int writeLAMMPSdataAllPrisms(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, std::vector< int > atomTypes, int maxDepth, std::string path, bool doShapeMatching=false)
Write a data file for prisms of every type.
double normHeightPercent(molSys::PointCloud< molSys::Point< double >, double > *yCloud, int nPrisms, double avgPrismHeight)
This contains a collection of points; contains information for a particular frame.
This contains per-particle information.
File containing functions used specific to quasi-one-dimensional topological network critera (the pri...