Prism3
+ Collaboration diagram for 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) More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 

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: \( m_{k+2} \) and \( m_{k+4} \) must be bonded to \( l_3 \) and \( l_5 \) (if \( l_1 \) is a neighbour) or \( m_{k+2} \) and \( m_{k+4} \) must be bonded to \( l_4 \) and \( l_6 \) (if \( l_2 \) is a neighbour)).
  • ring::notNeighboursOfRing (CONDITION2: \( m_{k+1} \), \( m_{k+3} \) and \( m_{k+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.

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
T begin(T... args)
T end(T... args)
T find(T... args)
bool notNeighboursOfRing(std::vector< std::vector< int >> nList, std::vector< int > *triplet, std::vector< int > *ring)
Definition: topo_bulk.cpp:981
bool basalNeighbours(std::vector< std::vector< int >> nList, std::vector< int > *triplet, int atomOne, int atomTwo)
Definition: topo_bulk.cpp:908
T push_back(T... args)

◆ 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.

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.

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.

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
T size(T... args)

◆ 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.

48  {
49  //
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
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 clearRingList(std::vector< std::vector< int >> &rings)
Erases memory for a vector of vectors for a list of rings.
Definition: ring.cpp:22
int assignPolygonType(std::vector< std::vector< int >> rings, std::vector< int > *atomTypes, std::vector< int > nRings)
Definition: ring.cpp:40
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.
T resize(T... args)

◆ 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 \( (m_k) \) 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.

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 }
T distance(T... args)
T sort(T... args)
T unique(T... args)

◆ 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.

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 }
T clear(T... args)
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.

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
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 }
T count(T... args)
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.

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 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.
Definition: topo_bulk.cpp:1557
bool basalPrismConditions(std::vector< std::vector< int >> nList, std::vector< int > *basal1, std::vector< int > *basal2)
Definition: topo_bulk.cpp:1429
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)
Definition: shapeMatch.cpp:110
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.

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
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 }
T erase(T... args)
bool conditionOneDDC(std::vector< std::vector< int >> rings, std::vector< int > *peripheralRings, int iring)
Definition: topo_bulk.cpp:416
bool conditionTwoDDC(std::vector< std::vector< int >> rings, std::vector< int > *peripheralRings, int iring)
Definition: topo_bulk.cpp:488
bool conditionThreeDDC(std::vector< std::vector< int >> rings, std::vector< int > *peripheralRings)
Definition: topo_bulk.cpp:569
@ 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...
T insert(T... args)

◆ 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; \( l_1 \)) or second (index1; \( l_2 \)) element of basal1. If \( m_k \) is the nearest neighbour of \( l_1 \), \( m_{k+2} \) and \( m_{k+4} \) must be neighbours of \( l_3 \) and \( l_5 \)( \( l_5 \) or \( l_3 \)). Similarly modified for \( l_2 \)).
    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.

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)
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
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)
Definition: topo_bulk.cpp:786
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.
Definition: topo_bulk.cpp:1021

◆ 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.

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 \( i^{th} \) ring.
[in]jringIndex of the \( j^{th} \) ring.
[in]prismaticRingsVector containing the indices of rings which are prismatic.

Definition at line 1021 of file topo_bulk.cpp.

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.

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.

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.

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
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.

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.

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
144  listMixed; // Vector for ring indices of rings that are both DDC and HC
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;
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
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 }
std::vector< int > findDDC(std::vector< std::vector< int >> rings, std::vector< strucType > *ringType, std::vector< int > listHC, std::vector< cage::Cage > *cageList)
Definition: topo_bulk.cpp:285
int getAtomTypesTopoBulk(std::vector< std::vector< int >> rings, std::vector< ring::strucType > ringType, std::vector< cage::iceType > *atomTypes)
Definition: topo_bulk.cpp:1164
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.
Definition: topo_bulk.cpp:1247
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.
Definition: topo_bulk.cpp:1328
std::vector< int > findMixedRings(std::vector< std::vector< int >> rings, std::vector< strucType > *ringType, std::vector< int > *listDDC, std::vector< int > *listHC)
Definition: topo_bulk.cpp:1117
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)
Definition: topo_bulk.cpp:651
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)