All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
Prism3
+ Collaboration diagram for Prism3:

Namespaces

namespace  prism3
 

Functions

int ring::bulkPolygonRingAnalysis (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 firstFrame)
 
int ring::topoBulkAnalysis (std::string path, std::vector< std::vector< int > > rings, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, int firstFrame, bool onlyTetrahedral=true)
 
std::vector< int > ring::findDDC (std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, std::vector< int > listHC, std::vector< cage::Cage > *cageList)
 
std::vector< int > ring::findMixedRings (std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, std::vector< int > *listDDC, std::vector< int > *listHC)
 
std::vector< int > ring::findHC (std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, std::vector< std::vector< int > > nList, std::vector< cage::Cage > *cageList)
 
bool ring::conditionOneDDC (std::vector< std::vector< int > > rings, std::vector< int > *peripheralRings, int iring)
 
bool ring::conditionTwoDDC (std::vector< std::vector< int > > rings, std::vector< int > *peripheralRings, int iring)
 
bool ring::conditionThreeDDC (std::vector< std::vector< int > > rings, std::vector< int > *peripheralRings)
 
bool ring::basalConditions (std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
 Tests whether two rings are basal rings (true) or not (false)
 
bool ring::basalNeighbours (std::vector< std::vector< int > > nList, std::vector< int > *triplet, int atomOne, int atomTwo)
 
bool ring::notNeighboursOfRing (std::vector< std::vector< int > > nList, std::vector< int > *triplet, std::vector< int > *ring)
 
int ring::findPrismatic (std::vector< std::vector< int > > rings, std::vector< int > *listHC, std::vector< strucType > *ringType, int iring, int jring, std::vector< int > *prismaticRings)
 Finds the prismatic rings from basal rings iring and jring.
 
int ring::getAtomTypesTopoBulk (std::vector< std::vector< int > > rings, std::vector< ring::strucType > ringType, std::vector< cage::iceType > *atomTypes)
 
int ring::getStrucNumbers (std::vector< ring::strucType > ringType, std::vector< cage::Cage > cageList, int *numHC, int *numDDC, int *mixedRings, int *prismaticRings, int *basalRings)
 Determines the number of HCs, DDCs, Mixed rings, prismatic and basal rings.
 
int prism3::findBulkPrisms (std::vector< std::vector< int > > rings, std::vector< ring::strucType > *ringType, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > *rmsdPerAtom, double heightCutoff=8)
 Find out which rings are prisms.
 
bool prism3::basalPrismConditions (std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
 
bool prism3::relaxedPrismConditions (std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
 
bool prism3::basalRingsSeparation (molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< int > basal1, std::vector< int > basal2, double heightCutoff=8)
 Check to see that candidate basal prisms are not really far from each other.
 

Detailed Description

Function Documentation

◆ basalConditions()

bool ring::basalConditions ( std::vector< std::vector< int > >  nList,
std::vector< int > *  basal1,
std::vector< int > *  basal2 
)

Tests whether two rings are basal rings (true) or not (false)

Check to see if two basal rings are HCs or not, using the neighbour list information. The neighbour list nList is a vector of vectors, containing atom indices (not atom IDs!). The first element of each subvector in nList is the atom index of the particle for which the other elements are the nearest neighbours. Internally, the following functions are called:

  • ring::basalNeighbours (CONDITION1: mk+2 and mk+4 must be bonded to l3 and l5 (if l1 is a neighbour) or mk+2 and mk+4 must be bonded to l4 and l6 (if l2 is a neighbour)).
  • ring::notNeighboursOfRing (CONDITION2: mk+1, mk+3 and mk+5 must NOT be bonded to any element in basal1).
    Parameters
    [in]nListVector of vectors of the neighbour list (by index).
    [in]basal1Vector containing the first candidate basal ring.
    [in]basal2Vector containing the second candidate basal ring.
    Returns
    A bool; true if the basal rings being tested fulfill this condition for being the basal rings of an HC.

Definition at line 786 of file topo_bulk.cpp.

Code
787 {
788 int l1 = (*basal1)[0]; // first element of basal1 ring
789 int l2 = (*basal1)[1]; // second element of basal1 ring
790 int ringSize = 6; // Size of the ring; each ring contains 6 elements
791 int m_k; // Atom Index (in pointCloud) of element in basal2
792 int kIndex; // Index of m_k in basal2, corresponding to m_k
793 int currentKindex; // Current k index when finding alternating elements of
794 // basal2
795 std::vector<int> evenTriplet; // contains m_k, m_{k+2}, m_{k+4}
796 std::vector<int> oddTriplet; // contains m_{k+1}, m_{k+3}, m_{k+5}
797 int compare1, compare2; // l3 and l5 OR l4 and l6
798 int index;
799 bool l1_neighbour, l2_neighbour; // m_k is a neighbour of l1(true) or not
800 // (false); m_k is a neighbour of l2(true)
801 bool isNeigh, notNeigh; // Used to check if the rings are basal or not
802
803 // ---------------------------------------------
804 // SEARCH FOR L1_NEIGHBOUR OR L2_NEIGHBOUR
805 // Search for whether an element of basal2 is a neighbour of l1 or l2
806 for (int k = 0; k < ringSize; k++) {
807 // init
808 l1_neighbour = false;
809 l2_neighbour = false;
810 m_k = (*basal2)[k];
811
812 // ---------------
813 // CHECK IF M_K MATCHES L1 NEIGHBOURS
814 auto it1 = std::find(nList[l1].begin() + 1, nList[l1].end(), m_k);
815 // If m_k was found in l1's nList
816 if (it1 != nList[l1].end()) {
817 compare1 = (*basal1)[2]; // l3
818 compare2 = (*basal1)[4]; // l5
819 kIndex = k; // Saving the array index of m_k
820 l1_neighbour = true;
821 break;
822 } // m_k found in l1's nList
823 // ---------------
824 // CHECK IF M_K MATCHES L2 NEIGHBOURS
825 auto it2 = std::find(nList[l2].begin() + 1, nList[l2].end(), m_k);
826 // If m_k was found in l1's nList
827 if (it2 != nList[l2].end()) {
828 compare1 = (*basal1)[3]; // l4
829 compare2 = (*basal1)[5]; // l6
830 kIndex = k; // Saving the array index of m_k
831 l2_neighbour = true;
832 break;
833 } // m_k found in l1's nList
834 // ---------------
835 } // End of search for basal2 elements in l1 or l2's nList
836 // ---------------------------------------------
837
838 // Return false if neither l1 nor l2 have any neighbours
839 // in basal2
840
841 if (l1_neighbour == false && l2_neighbour == false) {
842 return false;
843 } // basal conditions not fulfilled
844
845 // Get the alternating elements starting with kIndex.
846 // 'evenTriplet': m_k, m_{k+2}, m_{k+4} - neighbours of compare1 and compare2.
847 // 'oddTriplet': m_{k+1}, m_{k+3}, m_{k+5}- cannot be neighbours of basal1
848 for (int k = 0; k <= 5; k++) {
849 currentKindex = kIndex + k; // k
850 // Wrap-around
851 if (currentKindex >= ringSize) {
852 currentKindex -= ringSize;
853 } // end of wrap-around of k
854 //
855 // Update 'evenTriplet'
856 if (k % 2 == 0) {
857 evenTriplet.push_back((*basal2)[currentKindex]);
858 } // end of update of evenTriplet
859 // Update 'oddTriplet'
860 else {
861 oddTriplet.push_back((*basal2)[currentKindex]);
862 } // end of update of oddTriplet
863 } // End of getting alternating triplets
864
865 // ---------------------------------------------
866 // CONDITION1: m_{k+2} and m_{k+4} must be bonded to l3 and l5 (if l1 is a
867 // neighbour) or m_{k+2} and m_{k+4} must be bonded to l4 and l6 (if l2 is a
868 // neighbour) Basically, this boils down to checking whether compare1 and
869 // compare2 are in the neighbour lists of the last two elements of evenTriplet
870
871 isNeigh = ring::basalNeighbours(nList, &evenTriplet, compare1, compare2);
872
873 // If condition1 is not true, then the candidate
874 // rings are not part of an HC
875 if (!isNeigh) {
876 return false;
877 } // Not an HC
878
879 // ---------------------------------------------
880 // CONDITION2: m_{k+1}, m_{k+3} and m_{k+5} must NOT be bonded to any element
881 // in basal1.
882 // Basically, this boils down to checking whether the elements of oddTriplet
883 // are in the neighbour lists of all the elements of basal1.
884
885 // condition 2. This must be true for an HC
886 notNeigh = ring::notNeighboursOfRing(nList, &oddTriplet, basal1);
887
888 // If condition2 is not true, the the candidate rings
889 // are not part of an HC
890 if (!notNeigh) {
891 return false;
892 } // Not an HC
893
894 // Otherwise, all the conditions are true and this is an HC
895 return true;
896
897} // end of function
bool notNeighboursOfRing(std::vector< std::vector< int > > nList, std::vector< int > *triplet, std::vector< int > *ring)
bool basalNeighbours(std::vector< std::vector< int > > nList, std::vector< int > *triplet, int atomOne, int atomTwo)

◆ basalNeighbours()

bool ring::basalNeighbours ( std::vector< std::vector< int > >  nList,
std::vector< int > *  triplet,
int  atomOne,
int  atomTwo 
)

Tests whether the last two elements of a triplet are neighbours of two atom IDs passed in

Tests whether the last two elements of a triplet are neighbours of two atom indices which have been passed in as inputs.

Parameters
[in]nListVector of vectors of the neighbour list (by index).
[in]tripletVector containing the current triplet being tested.
[in]atomOneIndex of the first atom.
[in]atomTwoIndex of the second atom.
Returns
A bool; true if the condition is met and false otherwise.

Definition at line 908 of file topo_bulk.cpp.

Code
910 {
911 // Search for needles in a haystack :)
912 int needle1 = (*triplet)[1];
913 int needle2 = (*triplet)[2];
914 bool neighbourFound = false;
915 bool neighOne = false,
916 neighTwo = false; // Neighbour for atomOne, or neighbour for atomTwo
917 // ----------------------------
918 // For first element needle1, which must belong to either atomOne's or
919 // atomTwo's neighbour list Search atomOne's neighbours
920 auto it =
921 std::find(nList[atomOne].begin() + 1, nList[atomOne].end(), needle1);
922 if (it != nList[atomOne].end()) {
923 neighbourFound = true;
924 neighOne = true;
925 } // atomOne's neighbour
926 // If it is not atomOne's neighbour, it might be atomTwo's neighbour
927 if (!neighOne) {
928 it = std::find(nList[atomTwo].begin() + 1, nList[atomTwo].end(), needle1);
929 if (it != nList[atomTwo].end()) {
930 neighbourFound = true;
931 neighTwo = true;
932 } // end of check to see if neighbour was found
933 } // End of check to see if needle1 is atomTwo's neighbour
934 // ----------------------------
935 // If needle1 is not a neighbour of atomOne or atomTwo, return false
936 if (neighbourFound == false) {
937 return false;
938 }
939
940 // Check to see if needle2 is a neighbour of either atomOne or atomTwo
941 // ===============
942 // if atomOne was a neighbour of needle1, needle2 must be a neighbour of
943 // atomTwo
944 if (neighOne) {
945 it = std::find(nList[atomTwo].begin() + 1, nList[atomTwo].end(), needle2);
946 // It is a neighbour
947 if (it != nList[atomTwo].end()) {
948 return true;
949 }
950 // It is not a neighbour
951 else {
952 return false;
953 }
954 } // End of check for neighbour of atomTwo
955 // ===============
956 // if atomTwo was a neighbour of needle1, needle2 must be a neighbour of
957 // atomOne
958 else {
959 it = std::find(nList[atomOne].begin() + 1, nList[atomOne].end(), needle2);
960 // It is a neighbour
961 if (it != nList[atomOne].end()) {
962 return true;
963 }
964 // It is not a neighbour
965 else {
966 return false;
967 }
968 }
969 // ===============
970}

◆ basalPrismConditions()

bool prism3::basalPrismConditions ( std::vector< std::vector< int > >  nList,
std::vector< int > *  basal1,
std::vector< int > *  basal2 
)

Tests whether two rings are basal rings (true) or not (false) for a prism (strict criterion)

A function that checks to see if two basal rings are basal rings of a prism block or not, using the neighbour list information. The neighbour list nList is a row-ordered vector of vectors, containing atom indices (not atom IDs!). The first element of each subvector in nList is the atom index of the particle for which the other elements are the nearest neighbours.

Parameters
[in]nListRow-ordered neighbour list by atom index.
[in]basal1The vector for one of the basal rings.
[in]basal2The vector for the other basal ring.
Returns
A value that is true if the basal rings constitute a prism block, and false if they do not make up a prism block.

Definition at line 1429 of file topo_bulk.cpp.

Code
1431 {
1432 int l1 = (*basal1)[0]; // first element of basal1 ring
1433 int ringSize =
1434 (*basal1).size(); // Size of the ring; each ring contains n elements
1435 int m_k; // Atom ID of element in basal2
1436 bool l1_neighbour; // m_k is a neighbour of l1(true) or not (false)
1437
1438 // isNeighbour is initialized to false for all basal2 elements; indication if
1439 // basal2 elements are neighbours of basal1
1440 std::vector<bool> isNeighbour(ringSize, false);
1441 int kIndex; // m_k index
1442 int lAtomID; // atomID of the current element of basal1
1443 int kAtomID; // atomID of the current element of basal2
1444
1445 // ---------------------------------------------
1446 // COMPARISON OF basal2 ELEMENTS WITH l1
1447 for (int k = 0; k < ringSize; k++) {
1448 l1_neighbour = false;
1449 m_k = (*basal2)[k];
1450 // =================================
1451 // Checking to seee if m_k is be a neighbour of l1
1452 // Find m_k inside l1 neighbour list
1453 auto it = std::find(nList[l1].begin() + 1, nList[l1].end(), m_k);
1454
1455 // If the element has been found, for l1
1456 if (it != nList[l1].end()) {
1457 l1_neighbour = true;
1458 kIndex = k;
1459 break;
1460 }
1461 } // l1 is a neighbour of m_k
1462
1463 // If there is no nearest neighbour, then the two rings are not part of the
1464 // prism
1465 if (!l1_neighbour) {
1466 return false;
1467 }
1468
1469 // ---------------------------------------------
1470 // NEIGHBOURS of basal1 in basal2
1471 isNeighbour[kIndex] = true;
1472
1473 // All elements of basal1 must be neighbours of basal2
1474 for (int i = 1; i < ringSize; i++) {
1475 lAtomID = (*basal1)[i]; // element of basal1 ring
1476 for (int k = 0; k < ringSize; k++) {
1477 // Skip if already a neighbour
1478 if (isNeighbour[k]) {
1479 continue;
1480 }
1481 // Get the comparison basal2 element
1482 kAtomID = (*basal2)[k]; // element of basal2 ring;
1483
1484 // Checking to see if kAtomID is a neighbour of lAtomID
1485 // Find kAtomID inside lAtomID neighbour list
1486 auto it1 =
1487 std::find(nList[lAtomID].begin() + 1, nList[lAtomID].end(), kAtomID);
1488
1489 // If the element has been found, for l1
1490 if (it1 != nList[lAtomID].end()) {
1491 isNeighbour[k] = true;
1492 }
1493 } // Loop through basal2
1494 } // end of check for neighbours of basal1
1495
1496 // ---------------------------------------------
1497
1498 // They should all be neighbours
1499 for (int k = 0; k < ringSize; k++) {
1500 // Check to see if any element is false
1501 if (!isNeighbour[k]) {
1502 return false;
1503 }
1504 }
1505
1506 // Everything works out!
1507 return true;
1508}

◆ basalRingsSeparation()

bool prism3::basalRingsSeparation ( molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
std::vector< int >  basal1,
std::vector< int >  basal2,
double  heightCutoff = 8 
)

Check to see that candidate basal prisms are not really far from each other.

Check to see that candidate basal prisms are not really far from each other Return true if the basal rings are within the heightCutoff

Definition at line 1557 of file topo_bulk.cpp.

Code
1559 {
1560 //
1561 int ringSize = basal1.size();
1562 int l_k, m_k; // Atom indices
1563 double infHugeNumber = 100000;
1564 double leastDist = infHugeNumber;
1565 int index = -1; // starting index
1566 // For the first element of basal1:
1567
1568 l_k = basal1[0]; // This is the atom particle C++ index
1569
1570 // Search for the nearest neighbour of l_k in basal2
1571 // Loop through basal2 elements
1572 for (int m = 0; m < ringSize; m++) {
1573 m_k = basal2[m]; // Atom index to find in the neighbour list of iatom
1574
1575 // Calculate the distance
1576 double dist = gen::periodicDist(yCloud, l_k, m_k);
1577
1578 // Update the least distance
1579 if (leastDist > dist) {
1580 leastDist = dist; // This is the new least distance
1581 index = m;
1582 } // end of update of the least distance
1583
1584 } // found element
1585
1586 // If the element has been found, for l1
1587 if (leastDist < heightCutoff) {
1588 return true;
1589 } // end of check
1590 else {
1591 return false;
1592 }
1593}
double periodicDist(molSys::PointCloud< molSys::Point< double >, double > *yCloud, int iatom, int jatom)
Inline generic function for obtaining the unwrapped periodic distance between two particles,...
Definition generic.hpp:108

◆ bulkPolygonRingAnalysis()

int ring::bulkPolygonRingAnalysis ( 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  firstFrame 
)

Find out rings in the bulk, looping through all ring sizes upto the maxDepth The input ringsAllSizes array has rings of every size.

Function that loops through the primitive rings (which is a vector of vectors) of all sizes, upto maxDepth (the largest ring size).

  • ring::clearRingList (Clears the vector of vectors for rings of a single type, to prevent excessive memory being blocked).
  • ring::getSingleRingSize (Fill a vector of vectors for rings of a particular ring size).
  • ring::findPrisms (Now that rings of a particular size have been obtained, prism blocks are found and saved).
  • topoparam::normHeightPercent (Gets the height% for the prism blocks).
  • ring::assignPrismType (Assigns a prism type to each atom type).
  • sout::writePrismNum (Write out the prism information for the current frame).
  • sout::writeLAMMPSdataAllPrisms (Writes out a LAMMPS data file for the current frame, which can be visualized in OVITO).
    Parameters
    [in]pathThe string to the output directory, in which files will be written out.
    [in]ringsRow-ordered vector of vectors for rings of a single type.
    [in]nListRow-ordered neighbour list by index.
    [in]yCloudThe input PointCloud.
    [in]maxDepthThe maximum possible size of the primitive rings.
    [in]firstFrameThe first frame to be analyzed

Definition at line 44 of file topo_bulk.cpp.

Code
48 {
49 //
50 std::vector<std::vector<int>>
51 ringsOneType; // Vector of vectors of rings of a single size
52 int nRings; // Number of rings of the current type
53 std::vector<int> nRingList; // Vector of the values of the number of rings
54 // for a particular frame
55 std::vector<int>
56 atomTypes; // contains int values for each ring type considered
57 // -------------------------------------------------------------------------------
58 // Init
59 nRingList.resize(
60 maxDepth -
61 2); // Has a value for every value of ringSize from 3, upto maxDepth
62 // The atomTypes vector is the same size as the pointCloud atoms
63 atomTypes.resize(yCloud->nop, 1); // The dummy or unclassified value is 1
64 // -------------------------------------------------------------------------------
65 // Run this loop for rings of sizes upto maxDepth
66 // The smallest possible ring is of size 3
67 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
68 // Clear ringsOneType
69 ring::clearRingList(ringsOneType);
70 // Get rings of the current ring size
71 ringsOneType = ring::getSingleRingSize(rings, ringSize);
72 //
73 // Continue if there are zero rings of ringSize
74 if (ringsOneType.size() == 0) {
75 nRingList[ringSize - 3] = 0; // Update the number of prisms
76 continue;
77 } // skip if there are no rings
78 //
79 // -------------
80 // Number of rings with n nodes
81 nRings = ringsOneType.size();
82 // -------------
83 // Now that you have rings of a certain size:
84 nRingList[ringSize - 3] = nRings; // Update the number of n-membered rings
85 // -------------
86 } // end of loop through every possible ringSize
87
88 // Get the atom types for all the ring types
89 ring::assignPolygonType(rings, &atomTypes, nRingList);
90
91 // Write out the ring information
92 sout::writeRingNumBulk(path, yCloud->currentFrame, nRingList, maxDepth, firstFrame);
93 // Write out the lammps data file for the particular frame
94 sout::writeLAMMPSdataAllRings(yCloud, nList, atomTypes, maxDepth, path, false);
95
96 return 0;
97}
int nop
Current frame number.
Definition mol_sys.hpp:173
int currentFrame
Collection of points.
Definition mol_sys.hpp:172
int assignPolygonType(std::vector< std::vector< int > > rings, std::vector< int > *atomTypes, std::vector< int > nRings)
Definition ring.cpp:40
int clearRingList(std::vector< std::vector< int > > &rings)
Erases memory for a vector of vectors for a list of rings.
Definition ring.cpp:22
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.
Definition ring.cpp:200
int writeRingNumBulk(std::string path, int currentFrame, std::vector< int > nRings, int maxDepth, int firstFrame)
int writeLAMMPSdataAllRings(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > nList, std::vector< int > atomTypes, int maxDepth, std::string path, bool isMonolayer=true)
Write a data file for rings of every type for a monolayer.

◆ conditionOneDDC()

bool ring::conditionOneDDC ( std::vector< std::vector< int > >  rings,
std::vector< int > *  peripheralRings,
int  iring 
)

First condition for the DDC: There must be at least 3 other rings in which each element of the equatorial ring is present

For a given ring, which is being tested as the equatorial ring, this function tests if each element of the ring (mk) is present in at least three other rings or not. Returns false if this is not true. The ring indices of rings that have the common element are saved inside the periperal ring vector (peripheralRings) as potential peripheral rings, which is then passed as an input to the subsequent functions testing conditions.

Parameters
[in]ringsVector of vectors containing the 6-membered primitive rings.
[in]peripheralRingsVector containing the indices of rings which are potential peripheral rings.
[in]iringIndex of the ring being tested as equatorial.
Returns
A bool; true if ring being tested as equatorial, iring, satisfies the above condition for being an equatorial ring, and false otherwise.

Definition at line 416 of file topo_bulk.cpp.

Code
417 {
418 int index; // Atom ID to be compared
419 int noOfCommonRings =
420 0; // No of rings in which the element to be matched has been found
421 int jElement; // Atom ID being compared to index
422
423 // Loop through each element of iring for finding matches
424 for (int m = 0; m < 6; m++) {
425 index = rings[iring][m]; // Atom Index to be compared and matched with
426 noOfCommonRings = 0; // init to zero.
427 // Loop through every ring except iring
428 for (int jring = 0; jring < rings.size(); jring++) {
429 if (iring == jring) {
430 continue;
431 } // Skip for iring
432 // -------
433 // Search every element of jring
434 for (int k = 0; k < 6; k++) {
435 jElement = rings[jring][k];
436 if (jElement == index) {
437 noOfCommonRings++;
438 (*peripheralRings).push_back(jring);
439 break;
440 } // if index is found inside jring
441 else {
442 continue;
443 }
444 } // end of loop through every element of jring
445 // -------
446 } // end of loop through all rings except iring
447 // If less than 3 rings have been found for each element, then this is
448 // not an equatorial ring
449 if (noOfCommonRings < 3) {
450 return false;
451 } // end of check for common ring number per element in iring
452 } // end of loop through each element of iring
453
454 // iring is an equatorial ring. The duplicate ring IDs inside
455 // peripheralRings should be removed
456 std::vector<int>::iterator ip; // Iterator to find the last element upto
457 // which unique elements are present
458 // Duplicate IDs must be removed
459 int numElements =
460 (*peripheralRings).size(); // number of elements in peripheralRings
461 sort((*peripheralRings).begin(), (*peripheralRings).end());
462 ip = std::unique((*peripheralRings).begin(),
463 (*peripheralRings).begin() + numElements);
464 // Resize peripheral rings to remove undefined terms
465 (*peripheralRings).resize(std::distance((*peripheralRings).begin(), ip));
466
467 return true;
468}

◆ conditionThreeDDC()

bool ring::conditionThreeDDC ( std::vector< std::vector< int > >  rings,
std::vector< int > *  peripheralRings 
)

Third condition for the DDC: Even (by vector index) numbered index triplets and odd triplets must have at least one element in common

For a given ring, which is being tested as the equatorial ring, this function tests the following, given peripheralRings stored in increasing order of the triplet starting element:

  1. Rings corresponding to T1, T3, T5 should have at least one common element.
  2. Rings corresponding to T2, T4, T6 should have at least one common element.
  3. The following rings should have at least three common elements- {T1, T3}, {T2, T4}, {T3, T5}, {T4, T6}. Internally calls the following functions:
  • ring::commonElementsInThreeRings (CONDITION 1: Rings corresponding to T1, T3, T5 should have at least one common element).
  • ring::commonElementsInThreeRings (CONDITION 2: Rings corresponding to T1, T3, T5 should have at least one common element).
  • ring::findsCommonElements (Gets the common elements between a pair of rings).
    Parameters
    [in]ringsVector of vectors containing the 6-membered primitive rings.
    [in]peripheralRingsVector containing the indices of rings which are potential peripheral rings.
    Returns
    A bool; true if ring being tested as equatorial satisfies the above condition for being an equatorial ring, and false otherwise.

Definition at line 569 of file topo_bulk.cpp.

Code
570 {
571 // New
572 std::vector<int> common; // Vector containing common elements
573 bool hasCommon; // true if the rings have a common element
574 int iring, jring; // Pairs of peripheral rings
575 // ----------------------------------------------------------------------------
576 // CONDITION 1: Rings corresponding to T1, T3, T5 should have at least one
577 // common element.
578 hasCommon = ring::commonElementsInThreeRings(rings[(*peripheralRings)[0]],
579 rings[(*peripheralRings)[2]],
580 rings[(*peripheralRings)[4]]);
581
582 // If T1, T3, T5 don't have a common element, return false
583 if (!hasCommon) {
584 return false;
585 } // not a DDC
586 // ----------------------------------------------------------------------------
587 // CONDITION 2: Rings corresponding to T1, T3, T5 should have at least one
588 // common element.
589 hasCommon = ring::commonElementsInThreeRings(rings[(*peripheralRings)[1]],
590 rings[(*peripheralRings)[3]],
591 rings[(*peripheralRings)[5]]);
592
593 // If T1, T3, T5 don't have a common element, return false
594 if (!hasCommon) {
595 return false;
596 } // not a DDC
597 // ----------------------------------------------------------------------------
598 // CONDITION 3: Rings corresponding to {T1, T3}, {T2, T4}, {T3, T5}, {T4,
599 // T6}
600 // must have three elements in common amongst them
601
602 // Loops to get pairs of rings corresponding to the right triplets
603 for (int i = 0; i <= 3; i++) {
604 common.clear(); // init
605 // Pairs of rings corresponding to triplets.
606 iring = (*peripheralRings)[i];
607 jring = (*peripheralRings)[i + 2];
608 // Get the common elements
609 common = ring::findsCommonElements(rings[iring], rings[jring]);
610 // There should be at least three elements
611 if (common.size() < 3) {
612 return false;
613 } // not a DDC
614 } // end of getting iring and jring
615 // ----------------------------------------------------------------------------
616
617 // iring is an equatorial ring and peripheralRings has the 6 peripheral rings
618 return true;
619}
bool commonElementsInThreeRings(std::vector< int > ring1, std::vector< int > ring2, std::vector< int > ring3)
Common elements in 3 rings.
Definition ring.cpp:114
std::vector< int > findsCommonElements(std::vector< int > ring1, std::vector< int > ring2)
Returns the common elements of two rings.
Definition ring.cpp:85

◆ conditionTwoDDC()

bool ring::conditionTwoDDC ( std::vector< std::vector< int > >  rings,
std::vector< int > *  peripheralRings,
int  iring 
)

Second condition for the DDC: There must be at least 1 other ring for every triplet in the equatorial ring

For a given ring, which is being tested as the equatorial ring, this function tests if each triplet that can be formed from the ring is common to at least one other ring or not. Returns false if this is not true. The ring indices of rings that have the common triplet are ultimately saved inside the periperal ring vector as potential peripheral rings, which is passed as an input to the subsequent condition-testing functions. The function calls the following function internally:

  • ring::findTripletInRing (Searches inside another ring with index jring for the current triplet, which was obtained from iring).
    Parameters
    [in]ringsVector of vectors containing the 6-membered primitive rings.
    [in]peripheralRingsVector containing the indices of rings which are potential peripheral rings.
    [in]iringIndex of the ring being tested as equatorial.
    Returns
    A bool; true if ring being tested as equatorial, iring, satisfies the above condition for being an equatorial ring, and false otherwise.

Definition at line 488 of file topo_bulk.cpp.

Code
489 {
490 std::vector<int> triplet; // Triplet formed from iring
491 int ringSize = 6; // Here, all the rings are hexagons
492 int j; // Used for making the triplet
493 int jring; // Peripheral ring ID to be searched
494 int count; // Number of rings found that match the triplet
495 std::vector<int>
496 newPeripherals; // Vector in which the new peripheral ring IDs are saved.
497 // This will be swapped with peripheralRings later
498
499 for (int k = 0; k < ringSize; k++) {
500 triplet.clear(); // Clear the triplet
501 // Get a triplet
502 for (int i = k; i < k + 3; i++) {
503 j = i;
504 if (i >= ringSize) {
505 j = i - ringSize;
506 }
507 triplet.push_back(rings[iring][j]);
508 } // end of getting a triplet from k
509 // -------------
510 // Compare the triplet with every possible peripheral
511 // ring inside peripheralRings.
512 count = 0; // init to zero
513 // Loop through all possible peripheral rings
514 for (int m = 0; m < (*peripheralRings).size(); m++) {
515 jring = (*peripheralRings)[m]; // Ring ID of ring to be searched
516 // Search inside the ring with index jring for the triplet
517 bool foundTriplet = ring::findTripletInRing(rings[jring], triplet);
518
519 // If the triplet has been found inside jring
520 if (foundTriplet) {
521 newPeripherals.push_back(jring); // Update new peripheral vector
522 count++;
523 break;
524 } // end of ring found
525 } // end of loop through all possible peripheral rings
526 // If count is 0, then the triplet was not found in any peripheral ring
527 if (count == 0) {
528 return false;
529 } // Return false since the triplet was not found
530 // -------------
531 } // end of looping through 0-6 to get triplets
532
533 // Swap the old peripheral rings vector with the new one
534 (*peripheralRings).swap(newPeripherals);
535
536 // If there are more than 6 peripheral rings, the code will fail
537 // Comment this out if you want
538 if ((*peripheralRings).size() > 6) {
539 std::cerr
540 << "There are more than 6 peripheral rings. The code will fail. \n";
541 return false;
542 } // end of check for more than 6 peripherals
543
544 return true;
545}
bool findTripletInRing(std::vector< int > ring, std::vector< int > triplet)
Searches a particular ring for a triplet.
Definition ring.cpp:148

◆ findBulkPrisms()

int prism3::findBulkPrisms ( std::vector< std::vector< int > >  rings,
std::vector< ring::strucType > *  ringType,
std::vector< std::vector< int > >  nList,
molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
std::vector< double > *  rmsdPerAtom,
double  heightCutoff = 8 
)

Find out which rings are prisms.

Determines which rings are n-sided prisms. This function returns a vector which contains the ring indices of all the rings which are prisms. The ring indices correspond to the index of the rings inside the vector of vector rings, starting from 0. Prism rings can be found using a three-step procedure, in which first two basal rings are found. Prismatic rings are simply rings which share every face made by upper and lower triplets of the basal rings The neighbour list is also required as an input, which is a vector of vectors, containing atom IDs. The first element of the neighbour list is the atom index of the atom for which the other elements are nearest neighbours.\

Parameters
[in]ringsThe input vector of vectors containing the primitive rings of a single ring size (number of nodes).
[in]ringTypeA vector containing a ring::strucType value (a classification type) for each ring.
[in]nPrismsThe number of prism blocks identified for the number of nodes.
[in]nListThe row-ordered neighbour list (by atom index).
[in]yCloudThe input PointCloud.
Returns
A vector containing the ring indices of all the rings which have been classified as prisms. The indices are with respect to the input rings vector of vectors.

Definition at line 1328 of file topo_bulk.cpp.

Code
1332 {
1333 int totalRingNum = rings.size(); // Total number of rings
1334 std::vector<int> basal1; // First basal ring
1335 std::vector<int> basal2; // Second basal ring
1336 bool cond1, cond2; // Conditions for rings to be basal (true) or not (false)
1337 int ringSize = rings[0].size(); // Number of nodes in each ring
1338 // Matrix for the reference ring for a given ringSize.
1339 Eigen::MatrixXd refPointSet(ringSize, 3);
1340
1341 int axialDim = 2; // Default=z
1342 refPointSet = pntToPnt::getPointSetRefRing(ringSize, axialDim);
1343 //
1344
1345 // Two loops through all the rings are required to find pairs of basal rings
1346 for (int iring = 0; iring < totalRingNum - 1; iring++) {
1347 cond1 = false;
1348 cond2 = false;
1349 basal1 = rings[iring]; // Assign iring to basal1
1350 // Loop through the other rings to get a pair
1351 for (int jring = iring + 1; jring < totalRingNum; jring++) {
1352 basal2 = rings[jring]; // Assign jring to basal2
1353 // ------------
1354 // Put extra check for axial basal rings if shapeMatching is being done
1355 // ------------
1356 // Step one: Check to see if basal1 and basal2 have common
1357 // elements or not. If they don't, then they cannot be basal rings
1358 cond1 = ring::hasCommonElements(basal1, basal2);
1359 if (cond1 == true) {
1360 continue;
1361 }
1362
1363 // ------------
1364 bool smallDist =
1365 prism3::basalRingsSeparation(yCloud, basal1, basal2, heightCutoff);
1366 if (!smallDist) {
1367 continue;
1368 } // the basal rings are too far apart
1369
1370 // Otherwise
1371 // Do shape matching here
1372 bool isPrism = match::matchUntetheredPrism(yCloud, nList, refPointSet,
1373 &basal1, &basal2, rmsdPerAtom);
1374
1375 // Success! The rings are basal rings of a prism!
1376 if (isPrism) {
1377 //
1378 // Update iring
1379 if ((*ringType)[iring] == ring::strucType::unclassified) {
1380 (*ringType)[iring] = ring::strucType::Prism;
1381 }
1382 // Update jring
1383 if ((*ringType)[jring] == ring::strucType::unclassified) {
1384 (*ringType)[jring] = ring::strucType::Prism;
1385 }
1386 } // end of reduced criteria
1387 // Strict criteria
1388 else {
1389 cond2 = prism3::basalPrismConditions(nList, &basal1, &basal2);
1390 // If the condition is false then the strict criterion has not been met
1391 if (!cond2) {
1392 continue;
1393 }
1394 // Update iring
1395 if ((*ringType)[iring] == ring::strucType::unclassified) {
1396 (*ringType)[iring] = ring::strucType::Prism;
1397 }
1398 // Update jring
1399 if ((*ringType)[jring] == ring::strucType::unclassified) {
1400 (*ringType)[jring] = ring::strucType::Prism;
1401 }
1402 //
1403 // Shape-matching to get the RMSD (if shape-matching is desired)
1404
1405 // bool isKnownPrism = match::matchPrism(
1406 // yCloud, nList, refPointSet, &basal1, &basal2, rmsdPerAtom, true);
1407
1408 // -----------
1409 } // end of strict criteria
1410
1411 } // end of loop through rest of the rings to get the second basal ring
1412 } // end of loop through all rings for first basal ring
1413
1414 return 0;
1415}
bool basalPrismConditions(std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
bool basalRingsSeparation(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< int > basal1, std::vector< int > basal2, double heightCutoff=8)
Check to see that candidate basal prisms are not really far from each other.
bool hasCommonElements(std::vector< int > ring1, std::vector< int > ring2)
Definition ring.cpp:226
@ 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 matchUntetheredPrism(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)
Eigen::MatrixXd getPointSetRefRing(int n, int axialDim)

◆ findDDC()

std::vector< int > ring::findDDC ( std::vector< std::vector< int > >  rings,
std::vector< strucType > *  ringType,
std::vector< int >  listHC,
std::vector< cage::Cage > *  cageList 
)

Find out which hexagonal rings are DDC (Double Diamond Cages) rings. Returns a vector containing all the ring IDs which are DDC rings

Determines which hexagonal rings are DDC rings. This function returns a vector which contains the ring IDs of all the rings which are DDC rings. The ring IDs correspond to the index of the rings inside the vector of vector rings, starting from 0. DDC rings can be found using a three-step procedure, in which equatorial rings and their corresponding rings can be found. Peripheral rings can be shared, so first all the equatorial rings must be found. Whenever an equatorial ring and the corresponding peripheral rings are found, their values must be updated to DDC enum type inside the ringType vector, which has been passed as an input to this function. At the end, the output vector can be updated to avoid adding the same ring index more than once (this may happen for peripheral rings, which can be shared). Internally, the function calls the following:

  • ring::conditionOneDDC (Step one: Finds all rings which contain each index (m_k) of the equatorial ring, iring, in at least three other rings).
  • ring::conditionTwoDDC (Step two: For every triplet in iring, there is at least one hexagonal ring other than iring that passes through the triplet. The peripheral rings are stored in order of the starting element of each triplet.)
  • ring::conditionThreeDDC (Step three: For every triplet in the equatorial ring, there is at least one hexagonal ring other than iring that passes through the triplet. Rings corresponding to triplets need not be searched again since peripheralRings are stored in that order. Rings corresponding to T1, T3, T5 must have a common element. Similarly rings corresponding to T2, T4, T6 must have at least one common element. Alternating rings corresponding to triplets must have at least three common elements).
Parameters
[in]ringsVector of vectors containing 6-membered primitive rings (wherein each ring contains the atom indices of the particles which constitute the ring).
[in]ringTypeVector containing a ring::strucType (structure type) for each ring.
[in]cageListVector in which every cage is saved.
Returns
A vector of all the ring indices which constitute DDCs.

Definition at line 285 of file topo_bulk.cpp.

Code
288 {
289 std::vector<int> listDDC;
290 int totalRingNum = rings.size(); // Total number of hexagonal rings
291 std::vector<int> peripheralRings; // Indices which may be peripheral rings
292 bool cond1, cond2, cond3; // Conditions for DDC
293 int jring; // Index for peripheral ring being added
294 std::vector<int> DDCRings; // Indices of rings which constitute a single DDC,
295 // with the equatorial ring first
296 // Vector for checking if a ring is basal, prismatic or peripheral
297 std::vector<bool>
298 notEquatorial; // true if the ring is prismatic, basal or peripheral.
299 notEquatorial.resize(totalRingNum); // Initialized to false
300
301 // --------
302 // Set all basal and prismatic rings to true (which are part of an HC)
303 for (int i = 0; i < listHC.size(); i++) {
304 int currentRingIndex = listHC[i];
305 // Set this to true
306 notEquatorial[currentRingIndex] = true;
307 } // end of update of notEquatorial
308 // --------
309
310 // To search for equatorial rings, loop through all
311 // the hexagonal rings
312 for (int iring = 0; iring < totalRingNum; iring++) {
313 // ------------
314 // Step zero: If the ring has been classified as a basal or prismatic ring
315 // in an HC or is a peripheral ring, then it cannot be the equatiorial ring
316 // in a DDC
317 //
318 if (notEquatorial[iring]) {
319 continue;
320 } // skip for rings which are not equatorial
321 //
322 // ------------
323 // Init
324 peripheralRings.clear();
325 // ------------
326 // Step one: Find all rings which contain each index (m_k) of the equatorial
327 // ring, iring, in at least three other rings
328 cond1 = ring::conditionOneDDC(rings, &peripheralRings, iring);
329 if (cond1 == false) {
330 continue;
331 }
332 // ------------
333 // Step two: For every triplet in iring, there is at least one
334 // hexagonal ring other than iring that passes through the triplet.
335 // The peripheral rings are stored in order of the starting element
336 // of each triplet.
337 cond2 = ring::conditionTwoDDC(rings, &peripheralRings, iring);
338 if (cond2 == false) {
339 continue;
340 }
341 // ------------
342 // Step three: For every triplet in the equatorial ring, there is at least
343 // one hexagonal ring other than iring that passes through the triplet.
344 // Rings corresponding to triplets need not be searched again since
345 // peripheralRings are stored in that order. Rings corresponding to T1, T3,
346 // T5 must have a common element. Similarly rings corresponding to T2, T4,
347 // T6 must have at least one common element. Alternating rings corresponding
348 // to triplets must have at least three common elements
349 cond3 = ring::conditionThreeDDC(rings, &peripheralRings);
350 if (cond3 == false) {
351 continue;
352 }
353 // ------------
354 // If the peripheral rings are duplicates, skip everything
355 sort(peripheralRings.begin(), peripheralRings.end());
356 peripheralRings.erase(
357 unique(peripheralRings.begin(), peripheralRings.end()),
358 peripheralRings.end());
359 // There should be 6 unique peripheral rings
360 if (peripheralRings.size() != 6) {
361 continue;
362 }
363 // ------------
364 // If iring is an equatorial ring, add it to the listDDC vector
365 if ((*ringType)[iring] == ring::strucType::unclassified) {
366 (*ringType)[iring] = ring::strucType::DDC;
367 listDDC.push_back(iring);
368 }
369 // Add the peripheral ring IDs too
370 for (int j = 0; j < peripheralRings.size(); j++) {
371 jring = peripheralRings[j];
372 if ((*ringType)[jring] == ring::strucType::unclassified) {
373 (*ringType)[jring] = ring::strucType::DDC;
374 listDDC.push_back(jring);
375 } else if ((*ringType)[jring] == ring::strucType::HCbasal) {
376 (*ringType)[jring] = ring::strucType::bothBasal;
377 listDDC.push_back(jring);
378 } // end of update
379 // never true
380 else if ((*ringType)[jring] == ring::strucType::HCprismatic) {
381 (*ringType)[jring] = ring::strucType::bothPrismatic;
382 listDDC.push_back(jring);
383 }
384 //
385 // Update the notEquatorial vector
386 notEquatorial[jring] = true;
387 } // end of update for peripheral rings
388 // Add rings to the cageList vector of struct Cages.
389 DDCRings.clear(); // init
390 DDCRings.push_back(iring); // Add the equatorial ring first
391 DDCRings.insert(std::end(DDCRings), std::begin(peripheralRings),
392 std::end(peripheralRings));
393 (*cageList).push_back({cage::cageType::DoubleDiaC, DDCRings});
394 // ------------
395 } // end of loop through all hexagonal rings
396
397 return listDDC;
398}
bool conditionTwoDDC(std::vector< std::vector< int > > rings, std::vector< int > *peripheralRings, int iring)
bool conditionOneDDC(std::vector< std::vector< int > > rings, std::vector< int > *peripheralRings, int iring)
bool conditionThreeDDC(std::vector< std::vector< int > > rings, std::vector< int > *peripheralRings)
@ HCbasal
The ring belongs only to a hexagonal cage (HC). Specifically, the ring is purely a basal ring of an H...
@ DDC
The ring belongs to a double-diamond cage (DDC).
@ bothPrismatic
The ring belongs to both a DDC and HC and is, thus, a 'mixed' ring. The ring is also one of the prism...
@ bothBasal
The ring belongs to both a DDC and HC. It is a 'mixed' ring. The ring is also one of the basal rings ...
@ HCprismatic
The ring belongs only to a hexagonal cage (HC); specifically the ring is purely a prismatic ring of a...

◆ findHC()

std::vector< int > ring::findHC ( std::vector< std::vector< int > >  rings,
std::vector< strucType > *  ringType,
std::vector< std::vector< int > >  nList,
std::vector< cage::Cage > *  cageList 
)

Find out which hexagonal rings are HC rings. Returns a vector containing all the ring IDs which are HC rings

Determines which hexagonal rings are HCs. This function returns a vector which contains the ring IDs of all the rings which are HC rings. The ring IDs correspond to the index of the rings inside the vector of vector rings, starting from 0. HC rings can be found using a three-step procedure, in which first two basal rings are found. Prismatic rings are simply rings which share every face made by upper and lower triplets of the basal rings The neighbour list is also required as an input, which is a vector of vectors, containing atom IDs. The first element of the neighbour list is the atomID of the atom for which the other elements are nearest neighbours. The function calls the following functions internally:

  • ring::hasCommonElements (Step one: Checks to see if basal1 and basal2, two candidate basal rings, have common elements or not. If they don't, then they cannot be basal rings).
  • ring::basalConditions (Step two and three: One of the elements of basal2 must be the nearest neighbour of either the first (index0; l1) or second (index1; l2) element of basal1. If mk is the nearest neighbour of l1, mk+2 and mk+4 must be neighbours of l3 and l5( l5 or l3). Similarly modified for l2).
    Parameters
    [in]ringsVector of vectors containing 6-membered primitive rings (wherein each ring contains the atom indices of the particles which constitute the ring).
    [in]ringTypeVector containing a ring::strucType (structure type) for each ring.
    [in]nListRow-ordered vector of vectors of the neighbour list (by index).
    [in]cageListVector in which every cage is saved.
    Returns
    A vector of all the ring indices which constitute HCs.

Definition at line 651 of file topo_bulk.cpp.

Code
654 {
655 std::vector<int> listHC;
656 int totalRingNum = rings.size(); // Total number of hexagonal rings
657 std::vector<int> basal1; // First basal ring
658 std::vector<int> basal2; // Second basal ring
659 bool cond1, cond2; // Conditions for rings to be basal (true) or not (false)
660 std::vector<int>
661 HCRings; // Indices of rings which constitute a single HC, with the basal
662 // rings first, followed by prismatic rings
663 std::vector<int> prismaticRings; // Ring indices of prismatic rings
664 int kring; // Ring index of the prismatic rings
665 std::vector<bool>
666 isPrismatic; // Flag for checking if the ring is prismatic (true) or not
667 // (false), since the basal rings are checked
668 isPrismatic.resize(totalRingNum); // Initialized to false
669
670 // Two loops through all the rings are required to find pairs of basal rings
671 for (int iring = 0; iring < totalRingNum - 1; iring++) {
672 // -----------------------
673 // Skip if iring is prismatic
674 if (isPrismatic[iring]) {
675 continue;
676 } // Skip if prismatic
677 // -----------------------
678 cond1 = false;
679 cond2 = false;
680 basal1 = rings[iring]; // Assign iring to basal1
681 // Loop through the other rings to get a pair
682 for (int jring = iring + 1; jring < totalRingNum; jring++) {
683 // -----------------------
684 // Skip if iring is prismatic
685 if (isPrismatic[jring]) {
686 continue;
687 } // Skip if prismatic
688 // -----------------------
689 basal2 = rings[jring]; // Assign jring to basal2
690 // ------------
691 // Step one: Check to see if basal1 and basal2 have common
692 // elements or not. If they don't, then they cannot be basal rings
693 cond1 = ring::hasCommonElements(basal1, basal2);
694 if (cond1 == true) {
695 continue;
696 }
697 // -----------
698 // Step two and three: One of the elements of basal2 must be the nearest
699 // neighbour of either the first (index0; l1) or second (index1; l2)
700 // element of basal1. If m_k is the nearest neighbour of l1, m_{k+2} and
701 // m_{k+4} must be neighbours of l3 and l5(l5 or l3). Modify for l2.
702 cond2 = ring::basalConditions(nList, &basal1, &basal2);
703 if (cond2 == false) {
704 continue;
705 }
706 // -----------
707 // iring and jring are basal rings!
708 // Update iring
709 if ((*ringType)[iring] == ring::strucType::unclassified) {
710 (*ringType)[iring] = ring::strucType::HCbasal;
711 listHC.push_back(iring);
712 } else if ((*ringType)[iring] == ring::strucType::DDC) {
713 (*ringType)[iring] = ring::strucType::bothBasal;
714 listHC.push_back(iring);
715 }
716 // Update jring
717 if ((*ringType)[jring] == ring::strucType::unclassified) {
718 (*ringType)[jring] = ring::strucType::HCbasal;
719 listHC.push_back(jring);
720 } else if ((*ringType)[jring] == ring::strucType::DDC) {
721 (*ringType)[jring] = ring::strucType::bothBasal;
722 listHC.push_back(jring);
723 }
724 // Find the prismatic rings
725 prismaticRings.clear(); // Clear the prismatic ring vector first
726 ring::findPrismatic(rings, &listHC, ringType, iring, jring,
727 &prismaticRings);
728 // Update the prismatic rings
729 for (int k = 0; k < prismaticRings.size(); k++) {
730 kring =
731 prismaticRings[k]; // Current ring index of the (3) prismatic rings
732 // Update kring
733 if ((*ringType)[kring] == ring::strucType::unclassified) {
734 (*ringType)[kring] = ring::strucType::HCprismatic;
735 listHC.push_back(kring);
736 } else if ((*ringType)[kring] == ring::strucType::DDC) {
737 (*ringType)[kring] = ring::strucType::bothPrismatic;
738 listHC.push_back(kring);
739 }
740 //
741 // Update the isPrismatic vector
742 isPrismatic[kring] = true;
743 //
744 } // End of update of prismatic rings in listHC
745 // -----------
746 // Update the cageList vector of Cages
747 // Update the basal rings
748 HCRings.clear();
749 HCRings.push_back(iring);
750 HCRings.push_back(jring);
751 // Add the prismaticRings
752 HCRings.insert(std::end(HCRings), std::begin(prismaticRings),
753 std::end(prismaticRings));
754 (*cageList).push_back({cage::cageType::HexC, HCRings});
755 // -----------
756 } // end of loop through rest of the rings to get the second basal ring
757 } // end of loop through all rings for first basal ring
758
759 sort(listHC.begin(), listHC.end());
760 auto ip = std::unique(listHC.begin(), listHC.end());
761 // Resize peripheral rings to remove undefined terms
762 listHC.resize(std::distance(listHC.begin(), ip));
763
764 return listHC;
765}
bool basalConditions(std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
Tests whether two rings are basal rings (true) or not (false)
int findPrismatic(std::vector< std::vector< int > > rings, std::vector< int > *listHC, std::vector< strucType > *ringType, int iring, int jring, std::vector< int > *prismaticRings)
Finds the prismatic rings from basal rings iring and jring.

◆ findMixedRings()

std::vector< int > ring::findMixedRings ( std::vector< std::vector< int > >  rings,
std::vector< strucType > *  ringType,
std::vector< int > *  listDDC,
std::vector< int > *  listHC 
)

Find out which hexagonal rings are both DDCs (Double Diamond Cages) and HCs (Hexagonal Cages). Returns a vector containing all the ring IDs which are of this type

Determines which hexagonal rings are both DDCs and HCs. This function returns a vector which contains the ring IDs of all the rings which are both. The ring IDs correspond to the index of the rings inside the vector of vector rings, starting from 0. Rings which are both are of enum type bothBasal OR bothPrismatic. Reassign rings which are mixed in listDDC and listHC as the dummy value -10.

Parameters
[in]ringsThe 6-membered primitive rings.
[in]ringTypeStructure type for every ring.
[in]listDDCContains a vector of ring indices of DDCs.
[in]listHCContains a vector of ring indices of HCs.
Returns
A vector containing the indices of rings which are mixed.

Definition at line 1117 of file topo_bulk.cpp.

Code
1120 {
1121 std::vector<int> listMixed;
1122 int dummyValue = -10;
1123
1124 // Loop through all rings in the ringType and
1125 // adds the ring Indices of all rings which are both DDCs and HCs
1126 for (int iring = 0; iring < (*ringType).size(); iring++) {
1127 // If iring is of mixed type, add it to the listMixed vector
1128 if ((*ringType)[iring] == ring::strucType::bothBasal ||
1129 (*ringType)[iring] == ring::strucType::bothPrismatic) {
1130 listMixed.push_back(iring);
1131
1132 //-----------------
1133 // Search for iring in listDDC
1134 std::sort((*listDDC).begin(), (*listDDC).end());
1135 auto iter = std::find((*listDDC).begin(), (*listDDC).end(), iring);
1136 if (iter != (*listDDC).end()) {
1137 *iter = dummyValue; // Assign dummy value to the mixed ring
1138 } // found in listDDC
1139 //-----------------
1140 //-----------------
1141 // Search for iring in listHC
1142 std::sort((*listHC).begin(), (*listHC).end());
1143 auto itr = std::find((*listHC).begin(), (*listHC).end(), iring);
1144 if (itr != (*listHC).end()) {
1145 *itr = dummyValue; // Assign dummy value to the mixed ring
1146 } // found in listHC
1147 //-----------------
1148
1149 } // end of check for type
1150 } // end of loop through all every ring
1151
1152 return listMixed;
1153}

◆ findPrismatic()

int ring::findPrismatic ( std::vector< std::vector< int > >  rings,
std::vector< int > *  listHC,
std::vector< strucType > *  ringType,
int  iring,
int  jring,
std::vector< int > *  prismaticRings 
)

Finds the prismatic rings from basal rings iring and jring.

Finding prismatic rings when passed the information in the ringType input vector.

Parameters
[in]ringsThe 6-membered primitive rings.
[in]listHCVector containing the ring indices of rings which are part of HCs.
[in]ringTypeContains a structure type for each ring.
[in]iringIndex of the ith ring.
[in]jringIndex of the jth ring.
[in]prismaticRingsVector containing the indices of rings which are prismatic.

Definition at line 1021 of file topo_bulk.cpp.

Code
1024 {
1025 int iIndex, jIndex; // Used for making rings to be searched
1026 int ringSize = rings[0].size(); // This is 6 for hexagons
1027 std::vector<int> iTriplet; // triplet formed from iring
1028 std::vector<int> jTriplet; // triplet formed from jring
1029 std::vector<int> common; // Common elements
1030
1031 // Make all possible triplets out of iring
1032 for (int i = 0; i < ringSize; i++) {
1033 // init
1034 iTriplet.clear();
1035 // ------
1036 // Get a triplet
1037 for (int m = 0; m < 3; m++) {
1038 iIndex = i + m;
1039 if (iIndex >= ringSize) {
1040 iIndex -= ringSize;
1041 }
1042 iTriplet.push_back(rings[iring][iIndex]);
1043 } // end of getting a triplet from iring
1044
1045 // -------------------------------------------
1046 // Now that a triplet has been found, find all rings with that triplet in
1047 // it!
1048 for (int kring = 0; kring < rings.size(); kring++) {
1049 // If this is the same as iring or jring, skip
1050 if (kring == iring || kring == jring) {
1051 continue;
1052 } // is not prismatic
1053 //
1054 // Now find out whether kring has the triplet or not!
1055 common = ring::findsCommonElements(iTriplet, rings[kring]);
1056
1057 // If this triplet is not shared by kring
1058 // skip
1059 if (common.size() != 3) {
1060 continue;
1061 } // kring does not have iTriplet
1062
1063 // -----------------
1064 // If kring does have the triplet, check to see if at least three other
1065 // elements of kring are shared by jring
1066 jTriplet.clear(); // init
1067 // Make jTriplet
1068 for (int j = 0; j < ringSize; j++) {
1069 int katom = rings[kring][j];
1070 auto it = std::find(iTriplet.begin(), iTriplet.end(), katom);
1071
1072 // If not found, add it to jTriplet
1073 if (it == iTriplet.end()) {
1074 jTriplet.push_back(katom);
1075 } // update jTriplet
1076 } // end of making jTriplet out of kring
1077 // -----------------
1078
1079 // Now search for jTriplet inside jring
1080 common = ring::findsCommonElements(jTriplet, rings[jring]);
1081
1082 // Update the prismatic rings
1083 if (common.size() == 3) {
1084 //
1085 (*listHC).push_back(kring); // Update listHC vector
1086 (*prismaticRings).push_back(kring); // Update prismatic rings
1087 // Update the type inside ringType
1088 // If the ring is already a DDC ring, it is a mixed ring
1089 if ((*ringType)[kring] == ring::strucType::DDC) {
1090 (*ringType)[kring] = ring::strucType::bothPrismatic;
1091 }
1092 // If it is unclassified, it is just a prismatic ring
1093 if ((*ringType)[kring] == ring::strucType::unclassified) {
1094 (*ringType)[kring] = ring::strucType::HCprismatic;
1095 } // end ring update
1096 } // add kring to the list of prismatic rings
1097 } // end of searching through rings for kring
1098 // -------------------------------------------
1099 } // end of getting pairs of triplets
1100
1101 return 0;
1102}

◆ getAtomTypesTopoBulk()

int ring::getAtomTypesTopoBulk ( std::vector< std::vector< int > >  rings,
std::vector< ring::strucType ringType,
std::vector< cage::iceType > *  atomTypes 
)

Assigns a type of enum class iceType, to every atom, using information from ringType, which has the information of every ring

Assigns a type (cage::iceType) to each atom, according to the previous classification of every ring in ringType. Each subring or vector inside the vector of vector rings, is by index, meaning that the atoms are saved by their indices starting from 0 in the PointCloud.

Parameters
[in]ringsVector of vectors of 6-membered rings.
[in]ringTypeVector containing the structural type for each ring.
[in]atomTypesStructural type for each atom.

Definition at line 1164 of file topo_bulk.cpp.

Code
1166 {
1167 cage::iceType iRingType; // Type of the current ring
1168 int iatom; // Current ring
1169 int ringSize = rings[0].size(); // Size of the ring
1170
1171 // Loop through every ring in ringType
1172 for (int iring = 0; iring < ringType.size(); iring++) {
1173 //
1174 // Skip if the ring is unclassified
1175 if (ringType[iring] == ring::strucType::unclassified) {
1176 continue;
1177 } // skip for unclassified rings
1178
1179 // ------------
1180 // Get the current ring type
1181 // DDC
1182 if (ringType[iring] == ring::strucType::DDC) {
1183 iRingType = cage::iceType::ddc;
1184 } // DDC atoms
1185 //
1186 // HC
1187 else if (ringType[iring] == ring::strucType::HCbasal ||
1188 ringType[iring] == ring::strucType::HCprismatic) {
1189 iRingType = cage::iceType::hc;
1190 } // HC atoms
1191 //
1192 // Mixed
1193 else if (ringType[iring] == ring::strucType::bothBasal ||
1194 ringType[iring] == ring::strucType::bothPrismatic) {
1195 iRingType = cage::iceType::mixed;
1196 } // HC atoms
1197 // Prism
1198 else if (ringType[iring] == ring::strucType::Prism ||
1199 ringType[iring] == ring::strucType::deformedPrism ||
1200 ringType[iring] == ring::strucType::mixedPrismRing) {
1201 iRingType = cage::iceType::pnc; // 5 membered pnc
1202 } // prism
1203 // Should never go here
1204 else {
1205 continue;
1206 } //
1207 // ------------
1208 // Otherwise, loop through every inside the ring and assign atomTypes the
1209 // iRingType
1210 for (int i = 0; i < ringSize; i++) {
1211 iatom = rings[iring][i]; // Atom index in ring
1212 if ((*atomTypes)[iatom] == cage::iceType::mixed ||
1213 (*atomTypes)[iatom] == cage::iceType::mixed2) {
1214 continue;
1215 } // Don't reassign
1216 // For atoms shared by PNCs and DDCs/HCs
1217 if (ringSize == 6) {
1218 if ((*atomTypes)[iatom] == cage::iceType::pnc) {
1219 (*atomTypes)[iatom] = cage::iceType::mixed2;
1220 } else {
1221 (*atomTypes)[iatom] = iRingType;
1222 }
1223 } else {
1224 (*atomTypes)[iatom] = iRingType;
1225 }
1226 } // end of loop thorugh the current ring
1227 } // end of loop through every ring
1228
1229 return 0;
1230}
iceType
Definition cage.hpp:75

◆ getStrucNumbers()

int ring::getStrucNumbers ( std::vector< ring::strucType ringType,
std::vector< cage::Cage cageList,
int *  numHC,
int *  numDDC,
int *  mixedRings,
int *  prismaticRings,
int *  basalRings 
)

Determines the number of HCs, DDCs, Mixed rings, prismatic and basal rings.

Determines the number of HCs, DDCs from the cageList vector, containing a list of cages. The number of mixed rings, prismatic rings and basal rings are obtained from the ringType vector.

Parameters
[in]ringTypeVector containing the structural type for each ring.
[in]cageListContains all the cages (DDCs and HCs).
[in]numHCThe number of HCs.
[in]numDDCThe number of DDCs.
[in]mixedRingsThe number of mixed rings.
[in]prismaticRingsThe number of prismatic rings (of HCs/mixed rings).
[in]basalRingsTThe number of basal rings (of HCs/mixed rings).

Definition at line 1247 of file topo_bulk.cpp.

Code
1250 {
1251 // Determines the number of HCs, DDCs, Mixed rings, prismatic and basal rings
1252 // Init
1253 *numHC = 0;
1254 *numDDC = 0;
1255 *mixedRings = 0;
1256 *prismaticRings = 0;
1257 *basalRings = 0;
1258 // ------------------------------------
1259 // GETTING THE CAGES (DDCs and HCs)
1260 // Loop through cages
1261 for (int icage = 0; icage < cageList.size(); icage++) {
1262 //
1263 // HC
1264 if (cageList[icage].type == cage::cageType::HexC) {
1265 *numHC += 1;
1266 } // end of updating HC number
1267 //
1268 // DDC
1269 if (cageList[icage].type == cage::cageType::DoubleDiaC) {
1270 *numDDC += 1;
1271 } // end of updating DDC number
1272 } // end of loop through cages
1273 // ------------------------------------
1274 // GETTING THE RINGSS (Mixed, Prismatic and Basal rings)
1275 // Loop through the rings
1276 for (int iring = 0; iring < ringType.size(); iring++) {
1277 // Mixed
1278 if (ringType[iring] == ring::strucType::bothBasal ||
1279 ringType[iring] == ring::strucType::bothPrismatic) {
1280 *mixedRings += 1;
1281 // Also update basal rings
1282 if (ringType[iring] == ring::strucType::bothBasal) {
1283 *basalRings += 1;
1284 } // mixed basal rings
1285 // Also update prismatic rings
1286 if (ringType[iring] == ring::strucType::bothPrismatic) {
1287 *prismaticRings += 1;
1288 } // mixed prismatic rings
1289 } // end of updating mixed
1290 //
1291 // HCs
1292 if (ringType[iring] == ring::strucType::HCprismatic) {
1293 *prismaticRings += 1;
1294 } // HC prismatic
1295 // basal HCs
1296 if (ringType[iring] == ring::strucType::HCbasal) {
1297 *basalRings += 1;
1298 } // HC basal
1299 } // end of loop through every ring
1300 // ------------------------------------
1301
1302 return 0;
1303} // end of function

◆ notNeighboursOfRing()

bool ring::notNeighboursOfRing ( std::vector< std::vector< int > >  nList,
std::vector< int > *  triplet,
std::vector< int > *  ring 
)

Tests to check that elements of a triplet are not neighbours of a ring (vector) passed

Checks to make sure that the elements of the triplet are NOT neighbours of any elements inside a vector (ring) passed in (false) If any of them are neighbours, this function returns false.

Parameters
[in]nListVector of vectors of the neighbour list (by index).
[in]tripletVector containing the current triplet being tested.
[in]ringRing passed in.
Returns
A bool; true if the condition is met and false otherwise.

Definition at line 981 of file topo_bulk.cpp.

Code
983 {
984 int iatom; // AtomID of the atom to be searched for inside the neighbour
985 // lists
986 int jatom; // AtomID of in whose neighbour list iatom will be searched for
987 std::vector<int>::iterator it;
988
989 for (int i = 0; i < (*triplet).size(); i++) {
990 iatom = (*triplet)[i]; // AtomID to be searched for
991 // iatom must be searched for in the neighbour lists of all elements
992 // of the ring vector
993 for (int j = 0; j < (*ring).size(); j++) {
994 jatom = (*ring)[j];
995 // ------------------
996 // Search for iatom in the neighbour list of jatom
997 it = std::find(nList[jatom].begin() + 1, nList[jatom].end(), iatom);
998 // It is a neighbour!
999 if (it != nList[jatom].end()) {
1000 return false;
1001 }
1002 // ------------------
1003 } // end of loop through every element of ring
1004 } // end of loop through all triplet elements
1005
1006 return true;
1007}

◆ relaxedPrismConditions()

bool prism3::relaxedPrismConditions ( std::vector< std::vector< int > >  nList,
std::vector< int > *  basal1,
std::vector< int > *  basal2 
)

Reduced criterion: Two candidate basal rings of a prism block should have at least one bond between them

Relaxed criteria for deformed prism blocks: at least one bond should exist between the basal rings.

Definition at line 1516 of file topo_bulk.cpp.

Code
1518 {
1519 int ringSize =
1520 (*basal1).size(); // Size of the ring; each ring contains n elements
1521 int m_k; // Atom ID of element in basal2
1522 bool isNeighbour = false; // This is true if there is at least one bond
1523 // between the basal rings
1524 int l_k; // Atom ID of element in basal1
1525
1526 // ---------------------------------------------
1527 // COMPARISON OF basal2 ELEMENTS (m_k) WITH basal1 ELEMENTS (l_k)
1528 // Loop through all the elements of basal1
1529 for (int l = 0; l < ringSize; l++) {
1530 l_k = (*basal1)[l];
1531 // Search for the nearest neighbour of l_k in basal2
1532 // Loop through basal2 elements
1533 for (int m = 0; m < ringSize; m++) {
1534 m_k = (*basal2)[m];
1535 // Find m_k inside l_k neighbour list
1536 auto it = std::find(nList[l_k].begin() + 1, nList[l_k].end(), m_k);
1537
1538 // If the element has been found, for l1
1539 if (it != nList[l_k].end()) {
1540 isNeighbour = true;
1541 break;
1542 } // found element
1543 } // end of loop through all the elements of basal2
1544
1545 // If a neighbour has been found then
1546 if (isNeighbour) {
1547 return true;
1548 }
1549 } // end of loop through all the elements of basal1
1550
1551 // If a neighbour has not been found, return false
1552 return false;
1553}

◆ topoBulkAnalysis()

int ring::topoBulkAnalysis ( std::string  path,
std::vector< std::vector< int > >  rings,
std::vector< std::vector< int > >  nList,
molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
int  firstFrame,
bool  onlyTetrahedral = true 
)

Find out which rings are DDCs or HCs, which are comprised of 6-membered primitive rings. Start with a neighbour list (by index) and a vector of vectors of rings (also by index). TODO: try 'square' ice and ice0

Finds out if rings constitute double-diamond cages or hexagonal cages. Requires a neighbour list (by index) and a vector of vectors of primitive rings which should also be by index. This is registered as a Lua function and is accessible to the user. Internally, this function calls the following functions:

  • ring::getSingleRingSize (Saves rings of a single ring size into a new vector of vectors, which is subsequently used for finding DDCs, HCs etc).
  • ring::findDDC (Finds the DDCs).
  • ring::findHC (Finds the HCs).
  • ring::findMixedRings (Finds the mixed rings, which are shared by DDCs and HCs both).
  • ring::getStrucNumbers (Gets the number of structures (DDCs, HCs, mixed rings, basal rings, prismatic rings, to be used for write-outs).
  • sout::writeTopoBulkData (Writes out the numbers and data obtained for the current frame).
  • ring::getAtomTypesTopoBulk (Gets the atom type for every atom, to be used for printing out the ice types found).
  • sout::writeLAMMPSdataTopoBulk (Writes out the atoms, with the classified types, into a LAMMPS data file, which can be visualized in OVITO).
    Parameters
    [in]pathThe file path of the output directory to which output files will be written.
    [in]ringsVector of vectors containing the primitive rings. This contains rings of all sizes.
    [in]nListRow-ordered neighbour list, by index.
    [in]yCloudThe input PointCloud, with respect to which the indices in the rings and nList vector of vectors have been saved.
    [in]firstFrameFirst frame to be analyzed
    [in]onlyTetrahedralFlag for only finding DDCs and HCs (true) or also finding PNCs (false)

Definition at line 134 of file topo_bulk.cpp.

Code
138 {
139 //
140 // Ring IDs of each type will be saved in these vectors
141 std::vector<int> listDDC; // Vector for ring indices of DDC
142 std::vector<int> listHC; // Vector for ring indices of HC
143 std::vector<int>
144 listMixed; // Vector for ring indices of rings that are both DDC and HC
145 std::vector<ring::strucType>
146 ringType; // This vector will have a value for each ring inside
147 // ringList, of type enum strucType in gen.hpp
148 // Make a list of all the DDCs and HCs
149 std::vector<cage::Cage> cageList;
150 std::vector<std::vector<int>>
151 ringsOneType; // Vector of vectors of rings of a single size
152 int initRingSize; // Todo or not: calculate the PNCs or not
153 int maxRingSize = 6; // DDCs and HCs are for 6-membered rings
154 std::vector<cage::iceType>
155 atomTypes; // This vector will have a value for every atom
156 // Number of types
157 int numHC, numDDC, mixedRings, prismaticRings, basalRings;
158
159 // TODO: handle shapeMatching
160 bool doShapeMatching = true;
161 // Qualifier for the RMSD per atom:
162 std::vector<double> rmsdPerAtom;
163 //
164
165 // test
166 // std::cout << "rings"
167 // << "\n";
168 // for (int i = 0; i < rings.size(); i++) {
169 // for (int j = 0; j < rings[i].size(); j++) {
170 // std::cout << rings[i][j] << " ";
171 // }
172 // std::cout << "\n";
173 // }
174 // std::cout << "\n";
175
176 if (onlyTetrahedral) {
177 initRingSize = 6;
178 } else {
179 initRingSize = 5;
180 }
181
182 // Init the atom type vector
183 atomTypes.resize(yCloud->nop); // Has a value for each atom
184 // Init the rmsd per atom (not used yet)
185 rmsdPerAtom.resize(yCloud->nop); // Has a value for each atom
186
187 // ----------------------------------------------
188 // Init
189 // Get rings of size 5 or 6.
190 for (int ringSize = initRingSize; ringSize <= maxRingSize; ringSize++) {
191 // Clear ringsOneType
192 ring::clearRingList(ringsOneType);
193 // Get rings of the current ring size
194 ringsOneType = ring::getSingleRingSize(rings, ringSize);
195 // Skip for zero rings
196 if (ringsOneType.size() == 0) {
197 continue;
198 } // skip for no rings of ringSize
199 //
200 // Init the ringType vector
201 ringType.resize(
202 ringsOneType.size()); // Has a value for each ring. init to zero.
203 // ----------------------------------------------
204 if (ringSize == 6) {
205 // Get the cages
206
207 // Find HC rings, saving the ring IDs (starting from 0) to listHC
208 listHC = ring::findHC(ringsOneType, &ringType, nList, &cageList);
209
210 // Find DDC rings, saving the IDs to listDDC
211 listDDC = ring::findDDC(ringsOneType, &ringType, listHC, &cageList);
212
213 // Find rings which are both DDCs and HCs (mixed)
214 // A dummy value of -10 in the listDDC and listHC vectors for mixed rings
215 listMixed =
216 ring::findMixedRings(ringsOneType, &ringType, &listDDC, &listHC);
217
218 // Get the number of structures (DDCs, HCs, mixed rings, basal rings,
219 // prismatic rings)
220 ring::getStrucNumbers(ringType, cageList, &numHC, &numDDC, &mixedRings,
221 &prismaticRings, &basalRings);
222
223 // Write out to a file
224 sout::writeTopoBulkData(path, yCloud->currentFrame, numHC, numDDC,
225 mixedRings, basalRings, prismaticRings,
226 firstFrame);
227 // Gets the atom type for every atom, to be used for printing out the ice
228 // types found
229 ring::getAtomTypesTopoBulk(ringsOneType, ringType, &atomTypes);
230 }
231 // Finding prismatic blocks
232 else {
233 // Get the prism block classifications
234 prism3::findBulkPrisms(ringsOneType, &ringType, nList, yCloud,
235 &rmsdPerAtom);
236 // Gets the atom type for every atom, to be used for printing out the ice
237 // types found
238 ring::getAtomTypesTopoBulk(ringsOneType, ringType, &atomTypes);
239 }
240 }
241
242 // Print out the lammps data file with the bonds
243 sout::writeLAMMPSdataTopoBulk(yCloud, nList, atomTypes, path);
244 // To output the bonds between dummy atoms, uncomment the following line
245 // sout::writeLAMMPSdataTopoBulk(yCloud, nList, atomTypes, path, true);
246
247 return 0;
248}
int getAtomTypesTopoBulk(std::vector< std::vector< int > > rings, std::vector< ring::strucType > ringType, std::vector< cage::iceType > *atomTypes)
int findBulkPrisms(std::vector< std::vector< int > > rings, std::vector< ring::strucType > *ringType, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > *rmsdPerAtom, double heightCutoff=8)
Find out which rings are prisms.
int getStrucNumbers(std::vector< ring::strucType > ringType, std::vector< cage::Cage > cageList, int *numHC, int *numDDC, int *mixedRings, int *prismaticRings, int *basalRings)
Determines the number of HCs, DDCs, Mixed rings, prismatic and basal rings.
std::vector< int > findDDC(std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, std::vector< int > listHC, std::vector< cage::Cage > *cageList)
std::vector< int > findHC(std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, std::vector< std::vector< int > > nList, std::vector< cage::Cage > *cageList)
std::vector< int > findMixedRings(std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, std::vector< int > *listDDC, std::vector< int > *listHC)
int writeTopoBulkData(std::string path, int currentFrame, int numHC, int numDDC, int mixedRings, int basalRings, int prismaticRings, int firstFrame)
int writeLAMMPSdataTopoBulk(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > nList, std::vector< cage::iceType > atomTypes, std::string path, bool bondsBetweenDummy=false)