seams_output.cpp
Go to the documentation of this file.
Code
1//-----------------------------------------------------------------------------------
2// d-SEAMS - Deferred Structural Elucidation Analysis for Molecular Simulations
3//
4// Copyright (c) 2018--present d-SEAMS core team
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the MIT License as published by
8// the Open Source Initiative.
9//
10// A copy of the MIT License is included in the LICENSE file of this repository.
11// You should have received a copy of the MIT License along with this program.
12// If not, see <https://opensource.org/licenses/MIT>.
13//-----------------------------------------------------------------------------------
14
15#include <seams_input.hpp>
16#include <seams_output.hpp>
17
24 std::vector<std::vector<int>> rings, std::vector<std::vector<int>> bonds,
25 std::string filename) {
26 std::ofstream outputFile;
27 std::vector<int> atoms; // Holds all atom IDs to print
28 int ringSize = rings[0].size(); // Ring size of each ring in rings
29 int iatom; // Index, not atom ID
30 bool padAtoms = false; // Add extra atoms if the atom IDs are skipped
31 int prevAtomID = 0; // Check for previous atom ID
32 int dummyAtoms = 0; // Number of dummy atoms to fill
33 int dummyID;
34 int jatom; // Array index is 1 less than the ID (index for dummy atom)
35 // ----------------
36 // Return if there are no rings
37 if (rings.size() == 0) {
38 return 1;
39 }
40 // ----------------
41 // Otherwise create file
42 // Create output dir if it doesn't exist already
43 const char *path = "../output"; // relative to the build directory
44 fs::path dir(path);
45 // if (fs::create_directory(dir)) {
46 // std::cerr << "Output directory created\n";
47 // }
48 // ----------------
49 // Get all the unique atomIDs of the atoms in the rings of this type
50 // Put all atom IDs into one 1-D vector
51 size_t total_size{0};
52 // Get the total number of atoms (repeated)
53 total_size = rings.size() * ringSize;
54 // Reserve this size inside atoms
55 atoms.reserve(total_size);
56 // Fill up all these atom IDs
57 for (int iring = 0; iring < rings.size(); iring++) {
58 std::move(rings[iring].begin(), rings[iring].end(),
59 std::back_inserter(atoms));
60 } // end of loop through all rings in the list
61
62 // Sort the array according to atom ID, which will be needed to get the
63 // unique IDs and to remove duplicates
64 sort(atoms.begin(), atoms.end());
65 // Get the unique atom IDs
66 auto ip = std::unique(atoms.begin(), atoms.end());
67 // Resize the vector to remove undefined terms
68 atoms.resize(std::distance(atoms.begin(), ip));
69 // If the number of atoms is less than the total nop, add dummy atoms
70 if (atoms.size() != yCloud->nop) {
71 padAtoms = true;
72 }
73 // ----------------
74 // Write output to file inside the output directory
75 outputFile.open("../output/" + filename);
76 // FORMAT:
77 // Comment Line
78 // 4 atoms
79 // 4 bonds
80 // 0 angles
81 // 0 dihedrals
82 // 0 impropers
83 // 1 atom types
84 // 1 bond types
85 // 0 angle types
86 // 0 dihedral types
87 // 0 improper types
88 // -1.124000 52.845002 xlo xhi
89 // 0.000000 54.528999 ylo yhi
90 // 1.830501 53.087501 zlo zhi
91
92 // Masses
93
94 // 1 15.999400 # O
95
96 // Atoms
97
98 // 1 1 1 0 20.239 1.298 6.873 # O
99 // 2 1 1 0 0 5.193 6.873 # O
100 // 3 1 1 0 2.249 1.298 6.873 # O
101
102 // -------
103 // Write the header
104 // Write comment line
105 outputFile << "Written out by D-SEAMS\n";
106 // Write out the number of atoms
107 outputFile << atoms[atoms.size() - 1] << " "
108 << "atoms"
109 << "\n";
110 // Number of bonds
111 outputFile << bonds.size() << " bonds"
112 << "\n";
113 outputFile << "0 angles\n0 dihedrals\n0 impropers\n";
114 // If padded atoms are required, two atom types will be required
115 if (padAtoms) {
116 outputFile << "2 atom types\n";
117 } else {
118 outputFile << "1 atom types\n";
119 } // end of atom types
120 outputFile
121 << "1 bond types\n0 angle types\n0 dihedral types\n0 improper types\n";
122 // Box lengths
123 outputFile << "0 " << yCloud->box[0] << " xlo xhi\n";
124 outputFile << "0 " << yCloud->box[1] << " ylo yhi\n";
125 outputFile << "0 " << yCloud->box[2] << " zlo zhi\n";
126 // Masses
127 outputFile << "\nMasses\n\n";
128 outputFile << "1 15.999400 # O\n";
129 if (padAtoms) {
130 outputFile << "2 1.0 # dummy\n";
131 }
132 // Atoms
133 outputFile << "\nAtoms\n\n";
134 // -------
135 // Write out the atom coordinates
136 // Loop through atoms
137 for (int i = 0; i < atoms.size(); i++) {
138 iatom = atoms[i] - 1; // The actual index is one less than the ID
139 // -----------
140 // Pad out
141 // Fill in dummy atoms if some have been skipped
142 if (atoms[i] != prevAtomID + 1) {
143 dummyAtoms = atoms[i] - prevAtomID - 1;
144 dummyID = prevAtomID;
145 // Loop to write out dummy atoms
146 for (int j = 0; j < dummyAtoms; j++) {
147 dummyID++;
148 jatom = dummyID - 1;
149 // 1 molecule-tag atom-type q x y z
150 outputFile << dummyID << " " << yCloud->pts[jatom].molID << " 2 0 "
151 << yCloud->pts[jatom].x << " " << yCloud->pts[jatom].y << " "
152 << yCloud->pts[jatom].z << "\n";
153 } // end of dummy atom write-out
154 } // end of check for dummy atom printing
155 // -----------
156 // Write out coordinates
157 // 1 molecule-tag atom-type q x y z
158 outputFile << atoms[i] << " " << yCloud->pts[iatom].molID << " 1 0 "
159 << yCloud->pts[iatom].x << " " << yCloud->pts[iatom].y << " "
160 << yCloud->pts[iatom].z << "\n";
161 // update the previous atom ID
162 prevAtomID = atoms[i];
163 } // end of loop through all atoms in atomID
164
165 // Print the bonds now!
166 outputFile << "\nBonds\n\n";
167 // Loop through all bonds
168 for (int ibond = 0; ibond < bonds.size(); ibond++) {
169 outputFile << ibond + 1 << " 1 " << bonds[ibond][0] << " "
170 << bonds[ibond][1] << "\n";
171 }
172
173 // Once the datafile has been printed, exit
174 return 0;
175}
176
182int sout::writeRings(std::vector<std::vector<int>> rings,
183 std::string filename) {
184 std::ofstream outputFile;
185 // ----------------
186 // Create output dir if it doesn't exist already
187 const char *path = "../output"; // relative to the build directory
188 fs::path dir(path);
189 // if (fs::create_directory(dir)) {
190 // std::cerr << "Output directory created\n";
191 // }
192 // ----------------
193 // Write output to file inside the output directory
194 outputFile.open("../output/" + filename);
195
196 // Format:
197 // 272 214 906 1361 388 1
198
199 for (int iring = 0; iring < rings.size(); iring++) {
200 // Otherwise, write out to the file
201 for (int k = 0; k < rings[iring].size(); k++) {
202 outputFile << rings[iring][k] << " ";
203 } // end of loop through ring elements
204 outputFile << "\n";
205 } // end of loop through rings
206
207 outputFile.close();
208
209 return 0;
210}
211
217 std::vector<int> *basal1, std::vector<int> *basal2, int prismNum,
218 molSys::PointCloud<molSys::Point<double>, double> *yCloud) {
219 std::ofstream outputFile;
220 std::string number = std::to_string(prismNum);
221 std::string filename = "prism" + number + ".dat";
222 int ringSize =
223 (*basal1).size(); // Size of the ring; each ring contains n elements
224 int iatomIndex; // index of atom coordinate being written out
225
226 // ----------------
227 // Create output dir if it doesn't exist already
228 const char *path = "../output/prisms"; // relative to the build directory
229 fs::path dir(path);
230 // if (fs::create_directory(dir)) {
231 // std::cerr << "Output Prism directory created\n";
232 // }
233 // ----------------
234 // Write output to file inside the output directory
235 outputFile.open("../output/prisms/" + filename);
236
237 // Format:
238 // x y z coordinates of each node
239
240 // For basal 1
241 for (int iring = 0; iring < ringSize; iring++) {
242 iatomIndex = (*basal1)[iring]; // C++ indices are one less
243 // Write the coordinates out to the file
244 outputFile << yCloud->pts[iatomIndex].x << " ";
245 outputFile << yCloud->pts[iatomIndex].y << " ";
246 outputFile << yCloud->pts[iatomIndex].z << " ";
247
248 outputFile << "\n";
249 } // end of loop through basal1
250
251 // For basal 2
252 for (int iring = 0; iring < ringSize; iring++) {
253 iatomIndex = (*basal2)[iring]; // C++ indices are one less
254 // Write the coordinates out to the file
255 outputFile << yCloud->pts[iatomIndex].x << " ";
256 outputFile << yCloud->pts[iatomIndex].y << " ";
257 outputFile << yCloud->pts[iatomIndex].z << " ";
258
259 outputFile << "\n";
260 } // end of loop through basal1
261
262 outputFile.close();
263
264 // ---- Print out all the coordinates of a single ring, for prismNum=1 only
265 if (prismNum == 1) {
266 outputFile.open("../output/prisms/singleRing.dat");
267 // For basal 1
268 for (int iring = 0; iring < ringSize; iring++) {
269 iatomIndex = (*basal1)[iring]; // C++ indices are one less
270 // Write the coordinates out to the file
271 outputFile << yCloud->pts[iatomIndex].x << " ";
272 outputFile << yCloud->pts[iatomIndex].y << " ";
273 outputFile << yCloud->pts[iatomIndex].z << " ";
274
275 outputFile << "\n";
276 } // end of loop through basal1
277 outputFile.close();
278 }
279
280 return 0;
281}
282
288 std::string path, std::vector<cage::Cage> *cageList,
289 std::vector<std::vector<int>> rings, std::vector<std::vector<int>> nList,
291 int currentFrame) {
292 int numDDC; // Number of DDCs
293 int numHC; // Number of HCs
294 int numMC; // Number of MCs
295 int totalCages = (*cageList).size(); // Total number of cages
296 cage::cageType type; // Current cage type
297
298 // ---------------------------------
299 // Error handling!
300 if (totalCages == 0) {
301 std::cerr << "There are no cages to print.\n";
302 return 1;
303 }
304 // ---------------------------------
305 // Init
306 numDDC = 0;
307 numHC = 0;
308 numMC = 0;
309
310 // Loop through every cage
311 for (int icage = 0; icage < totalCages; icage++) {
312 type = (*cageList)[icage].type;
313 // ------
314 // Add to the cage type and write out to the appropriate folders
315 // Hexagonal Cages
316 if (type == cage::cageType::HexC) {
317 numHC++;
318 sout::writeEachCage((*cageList)[icage].rings, numHC, type, rings, yCloud);
319 sout::writeBasalRingsHex((*cageList)[icage].rings, numHC, nList, rings);
320 } // end of write out of HCs
321 // Double diamond Cages
322 else if (type == cage::cageType::DoubleDiaC) {
323 numDDC++;
324 sout::writeEachCage((*cageList)[icage].rings, numDDC, type, rings,
325 yCloud);
326 } // end of write out of DDCs
327 // // Mixed Cages
328 // else if (type == cage::Mixed) {
329 // numMC++;
330 // sout::writeEachCage((*cageList)[icage].rings, numMC, type, rings,
331 // yCloud);
332 // } // end of write out of MCs
333 // // Error
334 else {
335 std::cerr << "The cage is of the wrong type\n";
336 continue;
337 } // some error
338 // ------
339 } // end of loop through all cages
340
341 return 0;
342}
343
349 std::vector<int> currentCage, int cageNum, cage::cageType type,
350 std::vector<std::vector<int>> rings,
351 molSys::PointCloud<molSys::Point<double>, double> *yCloud) {
352 std::ofstream outputFile;
353 std::string number = std::to_string(cageNum);
354 std::string filename = "cage" + number + ".dat";
355 int ringSize =
356 rings[0].size(); // Size of the ring; each ring contains n elements
357 int iatomIndex; // index of atom coordinate being written out
358 std::string actualCageType; // is icage a DDC, HC or MC?
359 char cageChar[100]; // is icage a DDC, HC or MC?
360 int iring; // Ring index of the current ring
361
362 if (type == cage::cageType::HexC) {
363 strcpy(cageChar, "../output/cages/hexCages");
364 actualCageType = "hexCages";
365 } else if (type == cage::cageType::DoubleDiaC) {
366 strcpy(cageChar, "../output/cages/doubleDiaCages");
367 actualCageType = "doubleDiaCages";
368 } else {
369 // throw error
370 std::cerr << "The cage is of the wrong type. Exit\n";
371 return 1;
372 } //
373
374 // ----------------
375 // Create output dir if it doesn't exist already
376 const char *path = "../output/cages"; // relative to the build directory
377 fs::path dir(path);
378 // if (fs::create_directory(dir)) {
379 // std::cerr << "Output Cage directory created\n";
380 // }
381 // ----------------
382 // Subdirectory
383
384 const fs::path path1(cageChar);
385 // fs::create_directories(path1);
386
387 // Write output to file inside the output directory
388 std::string fileOutNameFull =
389 "../output/cages/" + actualCageType + "/" + filename;
390 outputFile.open(fileOutNameFull);
391
392 // Format:
393 // x y z coordinates of each node
394
395 // For hexagonal cages:
396 if (type == cage::cageType::HexC) {
397 // Print out only basal ring atoms, since they describe the outer structure
398 // The first two rings are basal rings
399 for (int i = 0; i < 2; i++) {
400 iring = currentCage[i]; // Current iring
401 // Get every node of iring
402 for (int j = 0; j < ringSize; j++) {
403 iatomIndex = rings[iring][j] - 1; // C++ indices are one less
404 // Write out the coordinates to the file
405 outputFile << yCloud->pts[iatomIndex].x << " ";
406 outputFile << yCloud->pts[iatomIndex].y << " ";
407 outputFile << yCloud->pts[iatomIndex].z << " ";
408
409 outputFile << "\n";
410 } // end of loop through iring
411 } // end of getting every ring in the current cage
412 } // end of printing basal ring atoms for hexagonal cages
413 // For currentCage
414 else {
415 // Loop through all cages (could be duplicates) TODO: remove duplicates
416 for (int i = 0; i < currentCage.size(); i++) {
417 iring = currentCage[i]; // Current iring
418 // Get every node of iring
419 for (int j = 0; j < ringSize; j++) {
420 iatomIndex = rings[iring][j] - 1; // C++ indices are one less
421 // Write out the coordinates to the file
422 outputFile << yCloud->pts[iatomIndex].x << " ";
423 outputFile << yCloud->pts[iatomIndex].y << " ";
424 outputFile << yCloud->pts[iatomIndex].z << " ";
425
426 outputFile << "\n";
427 } // end of loop through iring
428 } // end of getting every ring in the current cage
429 } // end of cage printing (has duplicates)
430
431 // Close the output file
432 outputFile.close();
433
434 return 0;
435}
436
441int sout::writeBasalRingsHex(std::vector<int> currentCage, int cageNum,
442 std::vector<std::vector<int>> nList,
443 std::vector<std::vector<int>> rings) {
444 std::ofstream outputFile;
445 std::string number = std::to_string(cageNum);
446 std::string filename = "basalRings" + number + ".dat";
447 int ringSize =
448 rings[0].size(); // Size of the ring; each ring contains n elements
449 int iatomIndex; // index of atom coordinate being written out TODO get rid of
450 // this
451 int iring; // Ring index of the current ring
452 // Variables for the hydrogen-bonded 'second' basal ring
453 std::vector<int>
454 basal2; // Elements are bonded to each element of basal1 in order
455 std::vector<int> basal1; // 'First' basal ring
456 std::vector<int>
457 unOrderedBasal2; // Unordered basal2 ring, the ith element is not
458 // necessarily bonded to the ith element of basal1
459 int iatom, jatom; // Atom numbers (starting from 1), not C++ indices; saved
460 // inside rings
461 int natom; // Neighbour list ID for iatom
462 int findAtom; // Atom number of atomID to find in neighbour list
463 bool atomFound; // bool to check if an atomID has been found in the neighbour
464 // list or not
465 // Variables for ordering basal2
466 // After finding the nearest neighbours, elements which are not nearest
467 // neighbours are assigned a value of zero.
468 int needle; // First non-zero element of basal2 after getting the nearest
469 // neighbours
470 int startNeedle; // Index of basal2; the first non-zero element of basal2
471 int startHayStack; // Index of unOrderedBasal2, corresponding to the first
472 // non-zero element of basal2
473 bool isClock; // Original order of unOrderedBasal2
474 int nextElement; // Next element in unOrderedBasal2 after startHayStack
475
476 // ----------------
477 // Create output dir if it doesn't exist already
478 const char *path = "../output/cages"; // relative to the build directory
479 fs::path dir(path);
480 // if (fs::create_directory(dir)) {
481 // std::cerr << "Output Cage directory created\n";
482 // }
483 // ----------------
484 // Subdirectory
485
486 const fs::path path1("../output/cages/hexBasalRings");
487 // fs::create_directories(path1);
488
489 // Write output to file inside the output directory
490 std::string fileOutNameFull = "../output/cages/hexBasalRings/" + filename;
491 outputFile.open(fileOutNameFull);
492
493 // Format:
494 // Coordinate IDs (starting from 1), ordered according to the input XYZ file
495 // The first line is a comment line
496 outputFile << "# Particle IDs in the two basal rings\n";
497
498 // ---------------
499 // Find the nearest neighbours of basal1 elements in basal2
500 basal1 = rings[currentCage[0]]; // First basal ring
501 unOrderedBasal2 = rings[currentCage[1]]; // Unordered second basal ring
502
503 for (int i = 0; i < basal1.size(); i++) {
504 iatom = basal1[i]; // This is the atom particle ID, not the C++ index
505
506 // Search through unOrderedBasal2 for an element in the neighbourlist of
507 // iatom
508 for (int k = 0; k < unOrderedBasal2.size(); k++) {
509 findAtom =
510 unOrderedBasal2[k]; // Atom ID to find in the neighbour list of iatom
511
512 atomFound = false; // init
513 jatom = 0;
514
515 // Search through the neighbour list for findAtom
516 for (int n = 1; n < nList[iatom - 1].size(); n++) {
517 natom = nList[iatom - 1][n]; // Atom ID
518
519 if (findAtom == natom) {
520 atomFound = true;
521 break;
522 } // Check
523 } // Loop through nList
524
525 if (atomFound) {
526 jatom = natom;
527 break;
528 } // atom has been found
529 } // end of loop through all atomIDs in unOrderedBasal2
530 basal2.push_back(jatom);
531 } // end of loop through all the atomIDs in basal1
532
533 // ---------------------------------------------------
534 // Get particles which are not nearest neighbours
535 // 'Alternately' ordered particles
536
537 // ---------------
538 // Init
539 isClock = false;
540
541 // ---------------
542 // Get the first non-zero index {needle}
543 for (int i = 0; i < 2; i++) {
544 if (basal2[i] != 0) {
545 needle = basal2[i]; // Set the needle to the first non-zero element
546 startNeedle = i; // Index of basal2
547 break; // Break out of the loop
548 } // end of checking for non-zero index
549 } // end of getting the first non-zero index
550
551 // Find the index matching needle in unOrderedBasal2
552 for (int i = 0; i < unOrderedBasal2.size(); i++) {
553 if (unOrderedBasal2[i] == needle) {
554 startHayStack = i; // Index at which needle has been found
555 } // end of check for needle
556 } // end of search for needle in unOrderedBasal2
557
558 // ---------------
559 // Check for 'clockwise' order
560 // Check 'next' element
561 nextElement = startHayStack + 2;
562 if (nextElement >= ringSize) {
563 nextElement -= ringSize;
564 }
565
566 // Init (indices of basal2 and unOrderedBasal2 respectively)
567 iatom = 0;
568 jatom = 0;
569
570 if (basal2[startNeedle + 2] == unOrderedBasal2[nextElement]) {
571 isClock = true;
572 // Fill the three elements in increasing order
573 for (int i = 1; i < ringSize; i += 2) {
574 iatom = startNeedle + i;
575 jatom = startHayStack + i;
576 // Make sure the indices are not larger than 6
577 if (iatom >= ringSize) {
578 iatom -= ringSize;
579 }
580 if (jatom >= ringSize) {
581 jatom -= ringSize;
582 }
583
584 basal2[iatom] = unOrderedBasal2[jatom];
585 } // end of filling next two alternate elements
586 } // check to see if clockwise order is correct
587
588 // ---------------
589 // Check for 'anticlockwise' order
590 // Check 'next' element
591 if (!isClock) {
592 iatom = 0;
593 jatom = 0; // init
594
595 // First element
596 iatom = startNeedle + 2;
597 jatom = startHayStack - 2;
598 if (jatom < 0) {
599 jatom += ringSize;
600 }
601
602 if (basal2[iatom] == unOrderedBasal2[jatom]) {
603 // Fill the three elements in increasing order
604 for (int i = 1; i < ringSize; i += 2) {
605 iatom = startNeedle + i;
606 jatom = startHayStack - i;
607 // Make sure the indices are not larger than 6
608 if (iatom > ringSize) {
609 iatom -= ringSize;
610 }
611 if (jatom < 0) {
612 jatom += ringSize;
613 }
614
615 basal2[iatom] = unOrderedBasal2[jatom];
616 } // end of filling next two alternate elements
617 } // check to see if anticlockwise order is correct
618 else {
619 std::cerr << "Something is wrong with your HCs.\n";
620 return 1;
621 } // exit with error
622 } // End of check for anticlockwise stuff
623
624 // ---------------------------------------------------
625 // Print out the ordered rings
626 // For hexagonal cages:
627 // Only print out basal1 and basal2
628
629 // BASAL1
630 for (int i = 0; i < basal1.size(); i++) {
631 outputFile << basal1[i] << " ";
632 } // end of loop through basal1
633 outputFile << "\n";
634
635 // BASAL2
636 for (int i = 0; i < basal2.size(); i++) {
637 outputFile << basal2[i] << " ";
638 } // end of loop through basal2
639
640 // Close the output file
641 outputFile.close();
642
643 return 0;
644}
645
651 std::vector<int> *basal1, std::vector<int> *basal2, int prismNum,
652 std::vector<std::vector<int>> nList,
654 bool isDeformed) {
655 std::ofstream outputFile;
656 std::string number = std::to_string(prismNum);
657 std::string filename = "basalRings" + number + ".dat";
658 int ringSize =
659 (*basal1).size(); // Size of the ring; each ring contains n elements
660 int nBonds; // Number of bonds between the two deformed prisms
661 int l_k, m_k; // Atom ID in basal1 and basal2 respectively
662 int iatom,
663 jatom; // Index not ID of basal1 and basal2 respectively which match
664 int currentIatom, currentJatom; // Index not ID for matchedBasal1 and
665 // matchedBasal2 respectively
666 bool isNeighbour; // Basal rings should have at least one nearest neighbour
667 bool isClock; // The order is in the original 'direction' of basal2
668 bool isAntiClock; // The order must be reversed
669 std::vector<int> matchedBasal1, matchedBasal2; // Vectors with revised order
670
671 // ----------------
672 // Path for deformed prisms
673 if (isDeformed) {
674 // Create output dir if it doesn't exist already
675 const char *path = "../output/deformed"; // relative to the build directory
676 fs::path dir(path);
677 // if (fs::create_directory(dir)) {
678 // std::cerr << "Output Cage directory created\n";
679 // }
680 // ----------------
681 // Subdirectory
682
683 const fs::path path1("../output/deformed/basalRings");
684 // fs::create_directories(path1);
685
686 // Write output to file inside the output directory
687 std::string fileOutNameFull = "../output/deformed/basalRings/" + filename;
688 outputFile.open(fileOutNameFull);
689 } else {
690 // Create output dir if it doesn't exist already
691 const char *path = "../output/perfect"; // relative to the build directory
692 fs::path dir(path);
693 // if (fs::create_directory(dir)) {
694 // std::cerr << "Output Cage directory created\n";
695 // }
696 // ----------------
697 // Subdirectory
698
699 const fs::path path1("../output/perfect/basalRings");
700 // fs::create_directories(path1);
701
702 // Write output to file inside the output directory
703 std::string fileOutNameFull = "../output/perfect/basalRings/" + filename;
704 outputFile.open(fileOutNameFull);
705 } // end of creating file paths
706
707 // Format:
708 // Coordinate IDs (starting from 1), ordered according to the input XYZ file
709 // The first line is a comment line
710 outputFile << "# Particle IDs in the two basal rings\n";
711
712 // ---------------
713 // Find the nearest neighbours of basal1 elements in basal2
714
715 nBonds = 0;
716 isNeighbour = false;
717 // Loop through every element of basal1
718 for (int l = 0; l < ringSize; l++) {
719 l_k = (*basal1)[l]; // This is the atom particle ID, not the C++ index
720
721 // Search for the nearest neighbour of l_k in basal2
722 // Loop through basal2 elements
723 for (int m = 0; m < ringSize; m++) {
724 m_k = (*basal2)[m]; // Atom ID to find in the neighbour list of iatom
725
726 // Find m_k inside l_k neighbour list
727 auto it = std::find(nList[l_k].begin() + 1, nList[l_k].end(), m_k);
728
729 // If the element has been found, for l1
730 if (it != nList[l_k].end()) {
731 isNeighbour = true;
732 iatom = l; // index of basal1
733 jatom = m; // index of basal2
734 break;
735 } // found element
736
737 } // end of loop through all atomIDs in basal2
738
739 if (isNeighbour) {
740 break;
741 } // nearest neighbour found
742 } // end of loop through all the atomIDs in basal1
743
744 if (!isNeighbour) {
745 std::cerr << "Something is wrong with your deformed prism.\n";
746 return 1;
747 }
748 // ---------------------------------------------------
749 // Find out if the order of basal2 is 'clockwise' or 'anticlockwise'
750 isClock = false; // init
751 isAntiClock = false;
752
753 // atom index (not ID)
754 int tempJfor, tempJback;
755
756 tempJfor = jatom + 1;
757 tempJback = jatom - 1;
758
759 if (jatom == ringSize - 1) {
760 tempJfor = 0;
761 tempJback = ringSize - 2;
762 }
763 if (jatom == 0) {
764 tempJfor = 1;
765 tempJback = ringSize - 1;
766 }
767
768 int forwardJ = (*basal2)[tempJfor];
769 int backwardJ = (*basal2)[tempJback];
770 int currentI = (*basal1)[iatom];
771
772 // Check clockwise
773 double distClock = gen::periodicDist(yCloud, currentI, forwardJ);
774 double distAntiClock = gen::periodicDist(yCloud, currentI, backwardJ);
775
776 // Clockwise
777 if (distClock < distAntiClock) {
778 isClock = true;
779 } // end of clockwise check
780 // Anti-clockwise
781 if (distAntiClock < distClock) {
782 isAntiClock = true;
783 } // end of anti-clockwise check
784 // Some error
785 if (isClock == false && isAntiClock == false) {
786 // std::cerr << "The points are equidistant.\n";
787 return 1;
788 } // end of error handling
789 // ---------------------------------------------------
790 // Get the order of basal1 and basal2
791 for (int i = 0; i < ringSize; i++) {
792 currentIatom = iatom + i;
793 if (currentIatom >= ringSize) {
794 currentIatom -= ringSize;
795 } // end of basal1 element wrap-around
796
797 // In clockwise order
798 if (isClock) {
799 currentJatom = jatom + i;
800 if (currentJatom >= ringSize) {
801 currentJatom -= ringSize;
802 } // wrap around
803 } // end of clockwise update
804 else {
805 currentJatom = jatom - i;
806 if (currentJatom < 0) {
807 currentJatom += ringSize;
808 } // wrap around
809 } // end of anti-clockwise update
810
811 // Add to matchedBasal1 and matchedBasal2 now
812 matchedBasal1.push_back((*basal1)[currentIatom]);
813 matchedBasal2.push_back((*basal2)[currentJatom]);
814 }
815 // ---------------------------------------------------
816 // Print out the ordered rings
817 // For hexagonal cages:
818 // Only print out basal1 and basal2
819
820 // BASAL1
821 for (int i = 0; i < matchedBasal1.size(); i++) {
822 outputFile << matchedBasal1[i] << " ";
823 } // end of loop through basal1
824 outputFile << "\n";
825
826 // BASAL2
827 for (int i = 0; i < matchedBasal2.size(); i++) {
828 outputFile << matchedBasal2[i] << " ";
829 } // end of loop through basal2
830
831 // Close the output file
832 outputFile.close();
833
834 return 0;
835}
836
840int sout::writeClusterStats(std::string path, int currentFrame,
841 int largestCluster, int numOfClusters,
842 int smallestCluster, double avgClusterSize,
843 int firstFrame) {
844 std::ofstream outputFile;
845 // ----------------
846 // Make the output directory if it doesn't exist
847 sout::makePath(path);
848 // ----------------
849 // Write output to file inside the output directory
850 outputFile.open(path + "clusterStats.dat",
851 std::ios_base::app | std::ios_base::out);
852
853 // Format:
854 // Comment line
855 // 1 3 0 0 4 35 40 ....
856
857 // ----------------
858 // Comment line for the first frame
859 if (currentFrame == firstFrame) {
860 outputFile << "Frame largestCluster numOfClusters smallestCluster "
861 "avgClusterSize\n";
862 }
863 // ----------------
864
865 outputFile << currentFrame << " " << largestCluster << " " << numOfClusters
866 << " " << smallestCluster << " " << avgClusterSize << "\n";
867
868 outputFile.close();
869
870 return 0;
871}
872
877int sout::writeMoleculeIDsInSlice(std::string path,
878 molSys::PointCloud<molSys::Point<double>, double> *yCloud) {
879 std::ofstream outputFile;
880 std::string filename =
881 "molID-" + std::to_string(yCloud->currentFrame) + ".dat";
882 std::vector<int> idVec; // Vector which will contain all molecule IDs present in the slice
883 // Eventually we will sort this and only keep unique molecule IDs.
884 int prevElem, currentElem; // previous and current mol ID in the sequence
885 int lastPrintedElemSeries; // Last element printed
886 // ----------------
887 // Make the output directory if it doesn't exist
888 sout::makePath(path);
889 sout::makePath(path+"selection");
890 sout::makePath(path+"selection/IDtextFiles");
891 // ----------------
892 // Write output to file inside the output directory
893 outputFile.open(path + "selection/IDtextFiles/" + filename);
894
895 // ----------------
896 // Find all molecule IDs from yCloud
897 // Loop through all iatom in yCloud
898 for (int iatom = 0; iatom < yCloud->nop; iatom++)
899 {
900 // If iatom is in the slice, add the molecule ID to idVec
901 if (yCloud->pts[iatom].inSlice)
902 {
903 idVec.push_back(yCloud->pts[iatom].molID);
904 } // end of adding molecule ID to vector for slice
905 } // end of loop through iatom
906 // ----------------
907 // Sort in ascending order
908 std::sort(idVec.begin(), idVec.end());
909 auto it = std::unique(idVec.begin(), idVec.end());
910 // Get rid of undefined elements
911 idVec.resize(std::distance(idVec.begin(), it));
912 // ----------------
913
914 // Format:
915 // Comment line
916 // 1 2 3 4 6 7
917
918 // ----------------
919 // Comment line
920 outputFile << "# Molecule IDs in slice\n";
921 outputFile << "# LAMMPS command : group groupName molecule 100:10000 \n";
922 // Format
923 // In LAMMPS, groups can be assigned by ID using the following command
924 // group groupName molecule 100:10000
925 // ----------------
926 // First element
927 outputFile << idVec[0];
928 prevElem = idVec[0];
929 lastPrintedElemSeries = idVec[0];
930 // ----------------
931
932 // Print other molecule IDs to the file
933 for (int i=1; i<idVec.size(); i++)
934 {
935 currentElem = idVec[i]; // current mol ID
936 // prevElem is the previous mol ID
937 // if the currentElem-prevElem>1
938 if (currentElem-prevElem>1 || i==idVec.size()-1)
939 {
940 if (lastPrintedElemSeries!=prevElem)
941 {
942 outputFile << ":" << prevElem << " " << currentElem;
943 lastPrintedElemSeries = currentElem;
944 } // the previous element has not been printed
945 else{
946 outputFile << " " << currentElem;
947 lastPrintedElemSeries = currentElem;
948 } // the previous element has already been printed
949 //
950 } // print currentElem
951 //
952 prevElem = currentElem;
953 } // end of printing all elements to file
954
955 outputFile.close();
956
957 return 0;
958}
959
965 molSys::PointCloud<molSys::Point<double>, double> *yCloud) {
966 std::ofstream outputFile;
967 std::string filename =
968 "ovito-molIDSelect-" + std::to_string(yCloud->currentFrame) + ".dat";
969 std::vector<int> idVec; // Vector which will contain all molecule IDs present in the slice
970 // Eventually we will sort this and only keep unique molecule IDs.
971 int prevElem, currentElem; // previous and current mol ID in the sequence
972 int lastPrintedElemSeries; // Last element printed
973 // ----------------
974 // Make the output directory if it doesn't exist
975 sout::makePath(path);
976 sout::makePath(path+"selection");
977 sout::makePath(path+"selection/IDovitoFiles");
978 // ----------------
979 // Write output to file inside the output directory
980 outputFile.open(path + "selection/IDovitoFiles/" + filename);
981
982 // ----------------
983 // Find all molecule IDs from yCloud
984 // Loop through all iatom in yCloud
985 for (int iatom = 0; iatom < yCloud->nop; iatom++)
986 {
987 // If iatom is in the slice, add the molecule ID to idVec
988 if (yCloud->pts[iatom].inSlice)
989 {
990 idVec.push_back(yCloud->pts[iatom].molID);
991 } // end of adding molecule ID to vector for slice
992 } // end of loop through iatom
993 // ----------------
994 // Sort in ascending order
995 std::sort(idVec.begin(), idVec.end());
996 auto it = std::unique(idVec.begin(), idVec.end());
997 // Get rid of undefined elements
998 idVec.resize(std::distance(idVec.begin(), it));
999 // ----------------
1000
1001 // Format:
1002 // Comment line
1003 // 1 2 3 4 6 7
1004
1005 // ----------------
1006 // Comment line
1007 outputFile << "# Molecule IDs in slice\n";
1008 outputFile << "# OVITO Expression select command \n";
1009 // ----------------
1010
1011 // Print other molecule IDs to the file
1012 for (int i=0; i<idVec.size()-1; i++)
1013 {
1014 currentElem = idVec[i]; // current mol ID
1015
1016 outputFile << "MoleculeIdentifier == " << currentElem << " || ";
1017
1018 } // end of printing all elements to file except the last one
1019
1020 // Print the last element
1021 outputFile << "MoleculeIdentifier == " << idVec.back();
1022
1023 outputFile.close();
1024
1025 return 0;
1026}
1027
1031int sout::writePrismNum(std::string path, std::vector<int> nPrisms,
1032 std::vector<int> nDefPrisms,
1033 std::vector<double> heightPercent, int maxDepth,
1034 int currentFrame, int firstFrame) {
1035 std::ofstream outputFile;
1036 int totalPrisms; // Number of total prisms
1037 // ----------------
1038 // Make the output directory if it doesn't exist
1039 sout::makePath(path);
1040 std::string outputDirName = path + "topoINT";
1041 sout::makePath(outputDirName);
1042 // ----------------
1043 // Write output to file inside the output directory
1044 outputFile.open(path + "topoINT/nPrisms.dat",
1045 std::ios_base::app | std::ios_base::out);
1046
1047 // ----------------
1048 // Write the comment line if the first frame is being written out
1049 if (currentFrame == firstFrame) {
1050 outputFile << "Frame RingSize Num_of_prisms Height% RingSize ... Height\n";
1051 }
1052 // ----------------
1053 // Format:
1054 // Frame RingSize Num_of_prisms Height% RingSize ... Height%
1055 // 1 3 0 0 4 35 40 ....
1056
1057 outputFile << currentFrame << " ";
1058
1059 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1060 totalPrisms = nPrisms[ringSize - 3] + nDefPrisms[ringSize - 3];
1061 // Write out
1062 outputFile << ringSize << " " << totalPrisms << " "
1063 << nDefPrisms[ringSize - 3] << " " << heightPercent[ringSize - 3]
1064 << " ";
1065 }
1066
1067 outputFile << "\n";
1068
1069 outputFile.close();
1070
1071 return 0;
1072}
1073
1077int sout::writeRingNum(std::string path, int currentFrame,
1078 std::vector<int> nRings,
1079 std::vector<double> coverageAreaXY,
1080 std::vector<double> coverageAreaXZ,
1081 std::vector<double> coverageAreaYZ, int maxDepth,
1082 int firstFrame) {
1083 std::ofstream outputFileXY;
1084 std::ofstream outputFileXZ;
1085 std::ofstream outputFileYZ;
1086 // ----------------
1087 // Make the output directory if it doesn't exist
1088 sout::makePath(path);
1089 std::string outputDirName = path + "topoMonolayer";
1090 sout::makePath(outputDirName);
1091 // ----------------
1092 // Coverage Area of XY
1093 // Write output to file inside the output directory
1094 outputFileXY.open(path + "topoMonolayer/coverageAreaXY.dat",
1095 std::ios_base::app | std::ios_base::out);
1096
1097 // Format:
1098 // Comment line
1099 // 1 3 0 0 4 35 40 ....
1100
1101 // ----------------
1102 // Add comment for the first frame
1103 if (currentFrame == firstFrame) {
1104 outputFileXY << "Frame RingSize Num_of_rings CoverageAreaXY% RingSize ... "
1105 "CoverageAreaXY%\n";
1106 }
1107 // ----------------
1108
1109 outputFileXY << currentFrame << " ";
1110
1111 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1112 outputFileXY << ringSize << " " << nRings[ringSize - 3] << " "
1113 << coverageAreaXY[ringSize - 3] << " ";
1114 }
1115
1116 outputFileXY << "\n";
1117
1118 outputFileXY.close();
1119 // ----------------
1120 // Coverage Area of XZ
1121 // Write output to file inside the output directory
1122 outputFileXZ.open(path + "topoMonolayer/coverageAreaXZ.dat",
1123 std::ios_base::app | std::ios_base::out);
1124
1125 // ----------------
1126 // Add comment for the first frame
1127 if (currentFrame == firstFrame) {
1128 outputFileXZ << "Frame RingSize Num_of_rings CoverageAreaXZ% RingSize ... "
1129 "CoverageAreaXZ%\n";
1130 }
1131 // ----------------
1132
1133 // Format:
1134 // Frame RingSize Num_of_prisms Height% RingSize ... Height%
1135 // 1 3 0 0 4 35 40 ....
1136
1137 outputFileXZ << currentFrame << " ";
1138
1139 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1140 outputFileXZ << ringSize << " " << nRings[ringSize - 3] << " "
1141 << coverageAreaXZ[ringSize - 3] << " ";
1142 }
1143
1144 outputFileXZ << "\n";
1145
1146 outputFileXZ.close();
1147 // ----------------
1148 // Coverage Area of YZ
1149 // Write output to file inside the output directory
1150 outputFileYZ.open(path + "topoMonolayer/coverageAreaYZ.dat",
1151 std::ios_base::app | std::ios_base::out);
1152
1153 // ----------------
1154 // Add comment for the first frame
1155 if (currentFrame == firstFrame) {
1156 outputFileYZ << "Frame RingSize Num_of_rings CoverageAreaYZ% RingSize ... "
1157 "CoverageAreaYZ%\n";
1158 }
1159 // ----------------
1160
1161 // Format:
1162 // Frame RingSize Num_of_prisms Height% RingSize ... Height%
1163 // 1 3 0 0 4 35 40 ....
1164
1165 outputFileYZ << currentFrame << " ";
1166
1167 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1168 outputFileYZ << ringSize << " " << nRings[ringSize - 3] << " "
1169 << coverageAreaYZ[ringSize - 3] << " ";
1170 }
1171
1172 outputFileYZ << "\n";
1173
1174 outputFileYZ.close();
1175
1176 return 0;
1177}
1178
1182int sout::writeRingNumBulk(std::string path, int currentFrame,
1183 std::vector<int> nRings,
1184 int maxDepth,
1185 int firstFrame) {
1186 std::ofstream outputFile;
1187 // ----------------
1188 // Make the output directory if it doesn't exist
1189 sout::makePath(path);
1190 std::string outputDirName = path + "bulkTopo";
1191 sout::makePath(outputDirName);
1192 // ----------------
1193 // Ring output file
1194 // Write output to file inside the output directory
1195 outputFile.open(path + "bulkTopo/num_rings.dat",
1196 std::ios_base::app | std::ios_base::out);
1197
1198 // Format:
1199 // Comment line
1200 // 1 3 0 4 35 ....
1201
1202 // ----------------
1203 // Add comment for the first frame
1204 if (currentFrame == firstFrame) {
1205 outputFile << "Frame RingSize Num_of_rings RingSize Num_of_rings...\n";
1206 }
1207 // ----------------
1208
1209 outputFile << currentFrame << " ";
1210
1211 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1212 outputFile << ringSize << " " << nRings[ringSize - 3] << " ";
1213 }
1214
1215 outputFile << "\n";
1216
1217 outputFile.close();
1218
1219 return 0;
1220}
1221
1226int sout::printRDF(std::string fileName, std::vector<double> *rdfValues,
1227 double binwidth, int nbin) {
1228 //
1229 std::ofstream outputFile; // For the output file
1230 double r; // Distance for the current bin
1231
1232 // Append to the file
1233 outputFile.open(fileName, std::ios_base::app | std::ios_base::out);
1234
1235 // Loop through all the bins
1236 for (int ibin = 0; ibin < nbin; ibin++) {
1237 //
1238 r = binwidth * (ibin + 0.5); // Current distance for ibin
1239 outputFile << r << " " << (*rdfValues)[ibin] << "\n";
1240 } // end of loop through all bins
1241
1242 outputFile.close();
1243
1244 return 0;
1245}
1246
1251int sout::writeTopoBulkData(std::string path, int currentFrame, int numHC,
1252 int numDDC, int mixedRings, int basalRings,
1253 int prismaticRings, int firstFrame) {
1254 //
1255 std::ofstream outputFile;
1256 // ----------------
1257 // Make the output directory if it doesn't exist
1258 sout::makePath(path);
1259 std::string outputDirName = path + "bulkTopo";
1260 sout::makePath(outputDirName);
1261 // ----------------
1262 // Write output to file inside the output directory
1263 outputFile.open(path + "bulkTopo/cageData.dat",
1264 std::ios_base::app | std::ios_base::out);
1265
1266 // Format:
1267 // Frame RingSize Num_of_prisms Height% RingSize ... Height%
1268 // 1 3 0 0 4 35 40 ....
1269 // -------------------
1270 // If first frame then write the comment line
1271 if (currentFrame == firstFrame) {
1272 outputFile << "Frame HCnumber DDCnumber MixedRingNumber PrismaticRings "
1273 "basalRings\n";
1274 }
1275 // -------------------
1276 outputFile << currentFrame << " " << numHC << " " << numDDC << " "
1277 << mixedRings << " " << prismaticRings << " " << basalRings
1278 << "\n";
1279
1280 outputFile.close();
1281 return 0;
1282} // end of function
1283
1290 std::vector<double> rmsdPerAtom, std::vector<int> atomTypes,
1291 std::string path, int firstFrame) {
1292 std::ofstream outputFile;
1293 int iatom; // Index, not atom ID
1294 std::string filename =
1295 "dump-" + std::to_string(yCloud->currentFrame) + ".lammpstrj";
1296 // ----------------
1297 // Make the output directory if it doesn't exist
1298 std::string outputDirName = path + "bulkTopo/dumpFiles";
1299 sout::makePath(outputDirName);
1300 // ----------------
1301 // Write out information about the data types
1302 if (yCloud->currentFrame == firstFrame) {
1303 outputFile.open(path + "bulkTopo/typeInfo.dat");
1304 outputFile << "Atom types in the dump files are:\n";
1305 outputFile << " Type 0 (dummy) = unidentified phase\n";
1306 outputFile << " Type 1 (hc) = atom belonging to a Hexagonal Cage.\n";
1307 outputFile << " Type 2 (ddc) = atom belonging to a Double-Diamond Cage\n";
1308 outputFile << " Type 3 (mixed) = atom belonging to a mixed ring shared by "
1309 "a DDC and HC\n";
1310 outputFile
1311 << " Type 4 (pnc) = atom belonging to a pair of pentagonal rings\n";
1312 outputFile << " Type 5 (mixed2) = atom belonging to a pentagonal "
1313 "nanochannel, shared by DDCs/HCs\n";
1314 outputFile.close();
1315 } // end of writing out information
1316 // ----------------
1317 // Write output to file inside the output directory
1318 outputFile.open(path + "bulkTopo/dumpFiles/" + filename);
1319 // ----------------------------------------------------
1320 // Header Format
1321
1322 // ITEM: TIMESTEP
1323 // 0
1324 // ITEM: NUMBER OF ATOMS
1325 // 500
1326 // ITEM: BOX BOUNDS pp pp pp
1327 // -9.0400100000000005e-01 1.7170999999999999e+01
1328 // -9.0400100000000005e-01 1.7170999999999999e+01
1329 // -9.0400100000000005e-01 1.7170999999999999e+01
1330 // ITEM: ATOMS id mol type x y z rmsd
1331
1332 // -----------------
1333 // -------
1334 // Write the header
1335 // ITEM: TIMESTEP
1336 outputFile << "ITEM: TIMESTEP\n";
1337 // Write out frame number
1338 outputFile << yCloud->currentFrame << "\n";
1339 // ITEM: NUMBER OF ATOMS
1340 outputFile << "ITEM: NUMBER OF ATOMS\n";
1341 // Number of atoms
1342 outputFile << yCloud->pts.size() << "\n";
1343 // ITEM: BOX BOUNDS pp pp pp
1344 outputFile << "ITEM: BOX BOUNDS pp pp pp\n";
1345 // Box lengths
1346 outputFile << yCloud->boxLow[0] << " " << yCloud->boxLow[0] + yCloud->box[0]
1347 << "\n";
1348 outputFile << yCloud->boxLow[1] << " " << yCloud->boxLow[1] + yCloud->box[1]
1349 << "\n";
1350 outputFile << yCloud->boxLow[2] << " " << yCloud->boxLow[2] + yCloud->box[2]
1351 << "\n";
1352 // ITEM: ATOMS id mol type x y z rmsd
1353 outputFile << "ITEM: ATOMS id mol type x y z rmsd\n";
1354 // -------
1355 // Write out the atom coordinates
1356 // Format
1357 // ITEM: ATOMS id mol type x y z rmsd
1358 //
1359 // Loop through atoms
1360 for (int i = 0; i < yCloud->pts.size(); i++) {
1361 iatom =
1362 yCloud->pts[i].atomID; // The actual ID can be different from the index
1363 // Write out coordinates
1364 outputFile << iatom << " " << yCloud->pts[i].molID << " " << atomTypes[i]
1365 << " " << yCloud->pts[i].x << " " << yCloud->pts[i].y << " "
1366 << yCloud->pts[i].z << " " << rmsdPerAtom[i] << "\n";
1367
1368 } // end of loop through all atoms in pointCloud
1369 // -----------------------------------------------------
1370 outputFile.close(); // Close the file
1371 return 0;
1372} // end of function
1373
1380 std::vector<double> rmsdPerAtom, std::vector<int> atomTypes, int maxDepth,
1381 std::string path) {
1382 //
1383 std::ofstream outputFile;
1384 int iatom; // Index, not atom ID
1385 std::string filename =
1386 "dump-" + std::to_string(yCloud->currentFrame) + ".lammpstrj";
1387 // ----------------
1388 // Make the output directory if it doesn't exist
1389 std::string outputDirName = path + "topoINT/dumpFiles";
1390 sout::makePath(outputDirName);
1391 // ----------------
1392 // Write output to file inside the output directory
1393 outputFile.open(path + "topoINT/dumpFiles/" + filename);
1394 // ----------------------------------------------------
1395 // Header Format
1396
1397 // ITEM: TIMESTEP
1398 // 0
1399 // ITEM: NUMBER OF ATOMS
1400 // 500
1401 // ITEM: BOX BOUNDS pp pp pp
1402 // -9.0400100000000005e-01 1.7170999999999999e+01
1403 // -9.0400100000000005e-01 1.7170999999999999e+01
1404 // -9.0400100000000005e-01 1.7170999999999999e+01
1405 // ITEM: ATOMS id mol type x y z rmsd
1406
1407 // -----------------
1408 // -------
1409 // Write the header
1410 // ITEM: TIMESTEP
1411 outputFile << "ITEM: TIMESTEP\n";
1412 // Write out frame number
1413 outputFile << yCloud->currentFrame << "\n";
1414 // ITEM: NUMBER OF ATOMS
1415 outputFile << "ITEM: NUMBER OF ATOMS\n";
1416 // Number of atoms
1417 outputFile << yCloud->pts.size() << "\n";
1418 // ITEM: BOX BOUNDS pp pp pp
1419 outputFile << "ITEM: BOX BOUNDS pp pp pp\n";
1420 // Box lengths
1421 outputFile << yCloud->boxLow[0] << " " << yCloud->boxLow[0] + yCloud->box[0]
1422 << "\n";
1423 outputFile << yCloud->boxLow[1] << " " << yCloud->boxLow[1] + yCloud->box[1]
1424 << "\n";
1425 outputFile << yCloud->boxLow[2] << " " << yCloud->boxLow[2] + yCloud->box[2]
1426 << "\n";
1427 // ITEM: ATOMS id mol type x y z rmsd
1428 outputFile << "ITEM: ATOMS id mol type x y z rmsd\n";
1429 // -------
1430 // Write out the atom coordinates
1431 // Format
1432 // ITEM: ATOMS id mol type x y z rmsd
1433 //
1434 // Loop through atoms
1435 for (int i = 0; i < yCloud->pts.size(); i++) {
1436 iatom =
1437 yCloud->pts[i].atomID; // The actual ID can be different from the index
1438 // Write out coordinates
1439 outputFile << iatom << " " << yCloud->pts[i].molID << " " << atomTypes[i]
1440 << " " << yCloud->pts[i].x << " " << yCloud->pts[i].y << " "
1441 << yCloud->pts[i].z << " " << rmsdPerAtom[i] << "\n";
1442
1443 } // end of loop through all atoms in pointCloud
1444 // -----------------------------------------------------
1445 return 0;
1446} // end of function
1447
1454 std::string path) {
1455 //
1456 std::ofstream outputFile;
1457 int iatom; // Index, not atom ID
1458 std::string filename =
1459 "dump-" + std::to_string(yCloud->currentFrame) + ".lammpstrj";
1460 // ----------------
1461 // Make the output directory if it doesn't exist
1462 sout::makePath(path+"selection");
1463 std::string outputDirName = path + "selection/dumpFiles";
1464 sout::makePath(outputDirName);
1465 // ----------------
1466 // Write output to file inside the output directory
1467 outputFile.open(path + "selection/dumpFiles/" + filename);
1468 // ----------------------------------------------------
1469 // Header Format
1470
1471 // ITEM: TIMESTEP
1472 // 0
1473 // ITEM: NUMBER OF ATOMS
1474 // 500
1475 // ITEM: BOX BOUNDS pp pp pp
1476 // -9.0400100000000005e-01 1.7170999999999999e+01
1477 // -9.0400100000000005e-01 1.7170999999999999e+01
1478 // -9.0400100000000005e-01 1.7170999999999999e+01
1479 // ITEM: ATOMS id mol type x y z rmsd
1480
1481 // -----------------
1482 // -------
1483 // Write the header
1484 // ITEM: TIMESTEP
1485 outputFile << "ITEM: TIMESTEP\n";
1486 // Write out frame number
1487 outputFile << yCloud->currentFrame << "\n";
1488 // ITEM: NUMBER OF ATOMS
1489 outputFile << "ITEM: NUMBER OF ATOMS\n";
1490 // Number of atoms
1491 outputFile << yCloud->pts.size() << "\n";
1492 // ITEM: BOX BOUNDS pp pp pp
1493 outputFile << "ITEM: BOX BOUNDS pp pp pp\n";
1494 // Box lengths
1495 outputFile << yCloud->boxLow[0] << " " << yCloud->boxLow[0] + yCloud->box[0]
1496 << "\n";
1497 outputFile << yCloud->boxLow[1] << " " << yCloud->boxLow[1] + yCloud->box[1]
1498 << "\n";
1499 outputFile << yCloud->boxLow[2] << " " << yCloud->boxLow[2] + yCloud->box[2]
1500 << "\n";
1501 // ITEM: ATOMS id mol type x y z rmsd
1502 outputFile << "ITEM: ATOMS id mol type x y z inSlice\n";
1503 // -------
1504 // Write out the atom coordinates
1505 // Format
1506 // ITEM: ATOMS id mol type x y z rmsd
1507 //
1508 // Loop through atoms
1509 for (int i = 0; i < yCloud->pts.size(); i++) {
1510 iatom =
1511 yCloud->pts[i].atomID; // The actual ID can be different from the index
1512 // Write out coordinates
1513 outputFile << iatom << " " << yCloud->pts[i].molID << " " << yCloud->pts[i].type
1514 << " " << yCloud->pts[i].x << " " << yCloud->pts[i].y << " "
1515 << yCloud->pts[i].z << " " << yCloud->pts[i].inSlice << "\n";
1516
1517 } // end of loop through all atoms in pointCloud
1518 // -----------------------------------------------------
1519 return 0;
1520} // end of function
1521
1529 std::vector<std::vector<int>> nList, std::vector<int> atomTypes,
1530 int maxDepth, std::string path, bool doShapeMatching) {
1531 //
1532 std::ofstream outputFile;
1533 int iatom; // Index, not atom ID
1534 int bondTypes = 1;
1535 // Bond stuff
1536 std::vector<std::vector<int>> bonds; // Vector of vector, with each row
1537 // containing the atom IDs of each bond
1538 std::string filename =
1539 "system-prisms-" + std::to_string(yCloud->currentFrame) + ".data";
1540
1541 // ---------------
1542 // Get the bonds
1543 bonds = bond::populateBonds(nList, yCloud);
1544 //
1545 // ----------------
1546 // Make the output directory if it doesn't exist
1547 sout::makePath(path);
1548 std::string outputDirName = path + "topoINT";
1549 sout::makePath(outputDirName);
1550 outputDirName = path + "topoINT/dataFiles/";
1551 sout::makePath(outputDirName);
1552 // ----------------
1553 // Write output to file inside the output directory
1554 outputFile.open(path + "topoINT/dataFiles/" + filename);
1555 // FORMAT:
1556 // Comment Line
1557 // 4 atoms
1558 // 4 bonds
1559 // 0 angles
1560 // 0 dihedrals
1561 // 0 impropers
1562 // 1 atom types
1563 // 1 bond types
1564 // 0 angle types
1565 // 0 dihedral types
1566 // 0 improper types
1567 // -1.124000 52.845002 xlo xhi
1568 // 0.000000 54.528999 ylo yhi
1569 // 1.830501 53.087501 zlo zhi
1570
1571 // Masses
1572
1573 // 1 15.999400 # O
1574
1575 // Atoms
1576
1577 // 1 1 1 0 20.239 1.298 6.873 # O
1578 // 2 1 1 0 0 5.193 6.873 # O
1579 // 3 1 1 0 2.249 1.298 6.873 # O
1580
1581 // -------
1582 // Write the header
1583 // Write comment line
1584 outputFile << "Written out by D-SEAMS\n";
1585 // Write out the number of atoms
1586 outputFile << yCloud->pts.size() << " "
1587 << "atoms"
1588 << "\n";
1589 // Number of bonds
1590 outputFile << bonds.size() << " bonds"
1591 << "\n";
1592 outputFile << "0 angles\n0 dihedrals\n0 impropers\n";
1593 // There are maxDepth-2 total types of prisms + dummy
1594 if (doShapeMatching) {
1595 outputFile << 2 * maxDepth - 2 << " atom types\n";
1596 } else {
1597 outputFile << maxDepth << " atom types\n";
1598 }
1599 // Bond types
1600 outputFile
1601 << bondTypes
1602 << " bond types\n0 angle types\n0 dihedral types\n0 improper types\n";
1603 // Box lengths
1604 outputFile << yCloud->boxLow[0] << " " << yCloud->boxLow[0] + yCloud->box[0]
1605 << " xlo xhi\n";
1606 outputFile << yCloud->boxLow[1] << " " << yCloud->boxLow[1] + yCloud->box[1]
1607 << " ylo yhi\n";
1608 outputFile << yCloud->boxLow[2] << " " << yCloud->boxLow[2] + yCloud->box[2]
1609 << " zlo zhi\n";
1610 // Masses
1611 outputFile << "\nMasses\n\n";
1612 outputFile << "1 15.999400 # dummy\n";
1613 outputFile << "2 1.0 # mixedRings \n";
1614 // There are maxDepth-2 other prism types
1615 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1616 outputFile << ringSize << " 15.999400 # prism" << ringSize << "\n";
1617 } // end of writing out perfect atom types
1618 // Write out the types for the deformed prism blocks
1619 if (doShapeMatching) {
1620 for (int ringSize = maxDepth + 1; ringSize <= 2 * maxDepth - 2;
1621 ringSize++) {
1622 int p = ringSize - maxDepth + 2;
1623 outputFile << ringSize << " 15.999400 # deformPrism" << p << "\n";
1624 } // end of writing out perfect atom types
1625 } // Deformed prism types
1626 // Atoms
1627 outputFile << "\nAtoms\n\n";
1628 // -------
1629 // Write out the atom coordinates
1630 // Loop through atoms
1631 for (int i = 0; i < yCloud->pts.size(); i++) {
1632 iatom =
1633 yCloud->pts[i].atomID; // The actual ID can be different from the index
1634 // Write out coordinates
1635 // atomID molecule-tag atom-type q x y z
1636 outputFile << iatom << " " << yCloud->pts[i].molID << " " << atomTypes[i]
1637 << " 0 " << yCloud->pts[i].x << " " << yCloud->pts[i].y << " "
1638 << yCloud->pts[i].z << "\n";
1639
1640 } // end of loop through all atoms in pointCloud
1641
1642 // Print the bonds now!
1643 outputFile << "\nBonds\n\n";
1644 // Loop through all bonds
1645 for (int ibond = 0; ibond < bonds.size(); ibond++) {
1646 //
1647 outputFile << ibond + 1 << " 1 " << bonds[ibond][0] << " "
1648 << bonds[ibond][1] << "\n";
1649 } // end of for loop for bonds
1650
1651 outputFile.close();
1652 // Once the datafile has been printed, exit
1653 return 0;
1654}
1655
1663 std::vector<std::vector<int>> nList, std::vector<int> atomTypes,
1664 int maxDepth, std::string path, bool isMonolayer) {
1665 //
1666 std::ofstream outputFile;
1667 int iatom; // Index, not atom ID
1668 int bondTypes = 1;
1669 // Bond stuff
1670 std::vector<std::vector<int>> bonds; // Vector of vector, with each row
1671 // containing the atom IDs of each bond
1672 std::string filename =
1673 "system-rings-" + std::to_string(yCloud->currentFrame) + ".data";
1674 std::string pathName, pathFolder;
1675
1676 // ---------------
1677 // Get the bonds
1678 bonds = bond::populateBonds(nList, yCloud);
1679 //
1680 // ----------------
1681 // Make the output directory if it doesn't exist
1682 if (isMonolayer)
1683 {
1684 pathFolder = "topoMonolayer";
1685 pathName = "topoMonolayer/dataFiles/";
1686 } else{
1687 pathFolder = "bulkTopo";
1688 pathName = "bulkTopo/dataFiles/";
1689 }
1690
1691 sout::makePath(path);
1692 std::string outputDirName = path + pathFolder;
1693 sout::makePath(outputDirName);
1694 outputDirName = path + pathName;
1695 sout::makePath(outputDirName);
1696
1697 // Write output to file inside the output directory
1698 outputFile.open(path + pathName + filename);
1699
1700 // FORMAT:
1701 // Comment Line
1702 // 4 atoms
1703 // 4 bonds
1704 // 0 angles
1705 // 0 dihedrals
1706 // 0 impropers
1707 // 1 atom types
1708 // 1 bond types
1709 // 0 angle types
1710 // 0 dihedral types
1711 // 0 improper types
1712 // -1.124000 52.845002 xlo xhi
1713 // 0.000000 54.528999 ylo yhi
1714 // 1.830501 53.087501 zlo zhi
1715
1716 // Masses
1717
1718 // 1 15.999400 # O
1719
1720 // Atoms
1721
1722 // 1 1 1 0 20.239 1.298 6.873 # O
1723 // 2 1 1 0 0 5.193 6.873 # O
1724 // 3 1 1 0 2.249 1.298 6.873 # O
1725
1726 // -------
1727 // Write the header
1728 // Write comment line
1729 outputFile << "Written out by D-SEAMS\n";
1730 // Write out the number of atoms
1731 outputFile << yCloud->pts.size() << " "
1732 << "atoms"
1733 << "\n";
1734 // Number of bonds
1735 outputFile << bonds.size() << " bonds"
1736 << "\n";
1737 outputFile << "0 angles\n0 dihedrals\n0 impropers\n";
1738 // There are maxDepth-2 total types of prisms + dummy
1739 outputFile << maxDepth << " atom types\n";
1740 // Bond types
1741 outputFile
1742 << bondTypes
1743 << " bond types\n0 angle types\n0 dihedral types\n0 improper types\n";
1744 // Box lengths
1745 outputFile << yCloud->boxLow[0] << " " << yCloud->boxLow[0] + yCloud->box[0]
1746 << " xlo xhi\n";
1747 outputFile << yCloud->boxLow[1] << " " << yCloud->boxLow[1] + yCloud->box[1]
1748 << " ylo yhi\n";
1749 outputFile << yCloud->boxLow[2] << " " << yCloud->boxLow[2] + yCloud->box[2]
1750 << " zlo zhi\n";
1751 // Masses
1752 outputFile << "\nMasses\n\n";
1753 outputFile << "1 15.999400 # dummy\n";
1754 outputFile << "2 1.0 # \n";
1755 // There are maxDepth-2 other prism types
1756 for (int ringSize = 3; ringSize <= maxDepth; ringSize++) {
1757 outputFile << ringSize << " 15.999400 # ring" << ringSize << "\n";
1758 } // end of writing out atom types
1759 // Atoms
1760 outputFile << "\nAtoms\n\n";
1761 // -------
1762 // Write out the atom coordinates
1763 // Loop through atoms
1764 for (int i = 0; i < yCloud->pts.size(); i++) {
1765 iatom =
1766 yCloud->pts[i].atomID; // The actual ID can be different from the index
1767 // Write out coordinates
1768 // atomID molecule-tag atom-type q x y z
1769 outputFile << iatom << " " << yCloud->pts[i].molID << " " << atomTypes[i]
1770 << " 0 " << yCloud->pts[i].x << " " << yCloud->pts[i].y << " "
1771 << yCloud->pts[i].z << "\n";
1772
1773 } // end of loop through all atoms in pointCloud
1774
1775 // Print the bonds now!
1776 outputFile << "\nBonds\n\n";
1777 // Loop through all bonds
1778 for (int ibond = 0; ibond < bonds.size(); ibond++) {
1779 //
1780 outputFile << ibond + 1 << " 1 " << bonds[ibond][0] << " "
1781 << bonds[ibond][1] << "\n";
1782 } // end of for loop for bonds
1783
1784 outputFile.close();
1785 // Once the datafile has been printed, exit
1786 return 0;
1787}
1788
1795 std::vector<std::vector<int>> rings, bool useBondFile, std::string bondFile,
1796 std::vector<int> listPrism, std::vector<std::vector<int>> nList,
1797 std::string filename) {
1798 std::ofstream outputFile;
1799 std::vector<int> atoms; // Holds all atom IDs to print
1800 int ringSize = rings[0].size(); // Ring size of each ring in rings
1801 int iatom; // Index, not atom ID
1802 bool padAtoms = false; // Add extra atoms if the atom IDs are skipped
1803 int prevAtomID = 0; // Check for previous atom ID
1804 int dummyAtoms = 0; // Number of dummy atoms to fill
1805 int dummyID;
1806 int jatom; // Array index is 1 less than the ID (index for dummy atom)
1807 int bondTypes = 1;
1808 // Bond stuff
1809 std::vector<std::vector<int>> bonds; // Vector of vector, with each row
1810 // containing the atom IDs of each bond
1811 bool atomOne, atomTwo; // If bond atoms are in the prism or not
1812 bool isPrismBond;
1813
1814 // ----------------
1815 // Return if there are no prisms
1816 if (listPrism.size() == 0) {
1817 return 1;
1818 }
1819
1820 // ---------------
1821 // Get the bonds
1822 if (useBondFile) {
1823 // Bonds from file
1824 bonds = sinp::readBonds(bondFile);
1825 } // get bonds from file
1826 else {
1827 bonds = bond::populateBonds(nList, yCloud);
1828 } // Bonds from rings
1829 //
1830 // ----------------
1831 // Otherwise create file
1832 // Create output dir if it doesn't exist already
1833 const char *path = "../output"; // relative to the build directory
1834 fs::path dir(path);
1835 // if (fs::create_directory(dir)) {
1836 // std::cerr << "Output directory created\n";
1837 // }
1838 // ----------------
1839 // Get all the unique atomIDs of the atoms in the rings of this type
1840 // Put all atom IDs into one 1-D vector
1841 size_t total_size{0};
1842 // Get the total number of atoms (repeated)
1843 total_size = listPrism.size() * ringSize;
1844 // Reserve this size inside atoms
1845 atoms.reserve(total_size);
1846 // Fill up all these atom IDs
1847 for (int iring = 0; iring < listPrism.size(); iring++) {
1848 std::move(rings[listPrism[iring]].begin(), rings[listPrism[iring]].end(),
1849 std::back_inserter(atoms));
1850 } // end of loop through all rings in the list
1851
1852 // Sort the array according to atom ID, which will be needed to get the
1853 // unique IDs and to remove duplicates
1854 sort(atoms.begin(), atoms.end());
1855 // Get the unique atom IDs
1856 auto ip = std::unique(atoms.begin(), atoms.end());
1857 // Resize the vector to remove undefined terms
1858 atoms.resize(std::distance(atoms.begin(), ip));
1859 // If the number of atoms is less than the total nop, add dummy atoms
1860 if (atoms.size() != yCloud->nop) {
1861 padAtoms = true;
1862 bondTypes = 2;
1863 }
1864 // ----------------
1865 // Write output to file inside the output directory
1866 outputFile.open("../output/" + filename);
1867 // FORMAT:
1868 // Comment Line
1869 // 4 atoms
1870 // 4 bonds
1871 // 0 angles
1872 // 0 dihedrals
1873 // 0 impropers
1874 // 1 atom types
1875 // 1 bond types
1876 // 0 angle types
1877 // 0 dihedral types
1878 // 0 improper types
1879 // -1.124000 52.845002 xlo xhi
1880 // 0.000000 54.528999 ylo yhi
1881 // 1.830501 53.087501 zlo zhi
1882
1883 // Masses
1884
1885 // 1 15.999400 # O
1886
1887 // Atoms
1888
1889 // 1 1 1 0 20.239 1.298 6.873 # O
1890 // 2 1 1 0 0 5.193 6.873 # O
1891 // 3 1 1 0 2.249 1.298 6.873 # O
1892
1893 // -------
1894 // Write the header
1895 // Write comment line
1896 outputFile << "Written out by D-SEAMS\n";
1897 // Write out the number of atoms
1898 outputFile << yCloud->pts.size() << " "
1899 << "atoms"
1900 << "\n";
1901 // Number of bonds
1902 outputFile << bonds.size() << " bonds"
1903 << "\n";
1904 outputFile << "0 angles\n0 dihedrals\n0 impropers\n";
1905 // If padded atoms are required, two atom types will be required
1906 if (padAtoms) {
1907 outputFile << "2 atom types\n";
1908 } else {
1909 outputFile << "1 atom types\n";
1910 } // end of atom types
1911 outputFile
1912 << bondTypes
1913 << " bond types\n0 angle types\n0 dihedral types\n0 improper types\n";
1914 // Box lengths
1915 outputFile << "0 " << yCloud->box[0] << " xlo xhi\n";
1916 outputFile << "0 " << yCloud->box[1] << " ylo yhi\n";
1917 outputFile << "0 " << yCloud->box[2] << " zlo zhi\n";
1918 // Masses
1919 outputFile << "\nMasses\n\n";
1920 outputFile << "1 15.999400 # O\n";
1921 if (padAtoms) {
1922 outputFile << "2 1.0 # dummy\n";
1923 }
1924 // Atoms
1925 outputFile << "\nAtoms\n\n";
1926 // -------
1927 // Write out the atom coordinates
1928 // Loop through atoms
1929 for (int i = 0; i < atoms.size(); i++) {
1930 iatom = atoms[i] - 1; // The actual index is one less than the ID
1931 // -----------
1932 // Pad out
1933 // Fill in dummy atoms if some have been skipped
1934 if (atoms[i] != prevAtomID + 1) {
1935 dummyAtoms = atoms[i] - prevAtomID - 1;
1936 dummyID = prevAtomID;
1937 // Loop to write out dummy atoms
1938 for (int j = 0; j < dummyAtoms; j++) {
1939 dummyID++;
1940 jatom = dummyID - 1;
1941 // 1 molecule-tag atom-type q x y z
1942 outputFile << dummyID << " " << yCloud->pts[jatom].molID << " 2 0 "
1943 << yCloud->pts[jatom].x << " " << yCloud->pts[jatom].y << " "
1944 << yCloud->pts[jatom].z << "\n";
1945 } // end of dummy atom write-out
1946 } // end of check for dummy atom printing
1947 // -----------
1948 // Write out coordinates
1949 // 1 molecule-tag atom-type q x y z
1950 outputFile << atoms[i] << " " << yCloud->pts[iatom].molID << " 1 0 "
1951 << yCloud->pts[iatom].x << " " << yCloud->pts[iatom].y << " "
1952 << yCloud->pts[iatom].z << "\n";
1953 // update the previous atom ID
1954 prevAtomID = atoms[i];
1955 } // end of loop through all atoms in atomID
1956
1957 // Fill in the rest of the dummy atoms
1958 if (atoms[atoms.size() - 1] != yCloud->nop) {
1959 //
1960 for (int id = atoms[atoms.size() - 1] + 1; id <= yCloud->nop; id++) {
1961 jatom = id - 1;
1962 outputFile << id << " " << yCloud->pts[jatom].molID << " 2 0 "
1963 << yCloud->pts[jatom].x << " " << yCloud->pts[jatom].y << " "
1964 << yCloud->pts[jatom].z << "\n";
1965 } // end of printing out dummy atoms
1966 }
1967
1968 // Print the bonds now!
1969 outputFile << "\nBonds\n\n";
1970 // Loop through all bonds
1971 for (int ibond = 0; ibond < bonds.size(); ibond++) {
1972 // Init
1973 isPrismBond = false;
1974 atomOne = false;
1975 atomTwo = false;
1976 // --------
1977 // Check if the bond is in the prism or not
1978 auto it = std::find(atoms.begin() + 1, atoms.end(), bonds[ibond][0]);
1979 if (it != atoms.end()) {
1980 atomOne = true;
1981 } else if (bonds[ibond][0] == atoms[0]) {
1982 atomOne = true;
1983 } else if (bonds[ibond][0] == atoms[atoms.size() - 1]) {
1984 atomOne = true;
1985 }
1986
1987 auto it1 = std::find(atoms.begin() + 1, atoms.end(), bonds[ibond][1]);
1988 if (it1 != atoms.end()) {
1989 atomTwo = true;
1990 } else if (bonds[ibond][1] == atoms[0]) {
1991 atomTwo = true;
1992 } else if (bonds[ibond][1] == atoms[atoms.size() - 1]) {
1993 atomTwo = true;
1994 }
1995
1996 if (atomOne == false || atomTwo == false) {
1997 isPrismBond = false;
1998 } else {
1999 isPrismBond = true;
2000 }
2001 // --------
2002 if (isPrismBond) {
2003 // is inside the prism (type 1)
2004 outputFile << ibond + 1 << " 1 " << bonds[ibond][0] << " "
2005 << bonds[ibond][1] << "\n";
2006 } else {
2007 // not inside the prism (type 2)
2008 outputFile << ibond + 1 << " 2 " << bonds[ibond][0] << " "
2009 << bonds[ibond][1] << "\n";
2010 }
2011
2012 } // end of for loop for bonds
2013
2014 outputFile.close();
2015 // Once the datafile has been printed, exit
2016 return 0;
2017}
2018
2025 std::vector<std::vector<int>> rings, std::vector<cage::Cage> *cageList,
2026 cage::cageType type, int numCages, std::string filename) {
2027 std::ofstream outputFile;
2028 std::vector<int> atoms; // Holds all atom IDs to print
2029 int ringSize = rings[0].size(); // Ring size of each ring in rings
2030 int iatom; // Index, not atom ID
2031 bool padAtoms = false; // Add extra atoms if the atom IDs are skipped
2032 int prevAtomID = 0; // Check for previous atom ID
2033 int dummyAtoms = 0; // Number of dummy atoms to fill
2034 int dummyID;
2035 int iring; // Current ring index (vector index)
2036 int jatom; // Array index is 1 less than the ID (index for dummy atom)
2037 int bondTypes = 1;
2038 std::string actualCageType; // The actual name of the cage types
2039 // Bond stuff
2040 std::vector<std::vector<int>> bonds; // Vector of vector, with each row
2041 // containing the atom IDs of each bond
2042 int nRings = 0; // Number of rings
2043
2044 // ----------------
2045 // Return if there are no cages at all
2046 if ((*cageList).size() == 0) {
2047 return 1;
2048 }
2049
2050 // Return if there are no cages of the required type
2051 if (numCages == 0) {
2052 return 1;
2053 }
2054 // ---------------
2055 // Get the bonds
2056 bonds = bond::createBondsFromCages(rings, cageList, type, &nRings);
2057 //
2058 // ----------------
2059 // Otherwise create file
2060 // Create output dir if it doesn't exist already
2061 const char *path = "../output"; // relative to the build directory
2062 fs::path dir(path);
2063 // if (fs::create_directory(dir)) {
2064 // std::cerr << "Output directory created\n";
2065 // }
2066 // ----------------
2067 // Get all the unique atomIDs of the atoms in the rings of this type
2068 // Put all atom IDs into one 1-D vector
2069 size_t total_size{0};
2070 // Get the total number of atoms (repeated)
2071 total_size = nRings * ringSize;
2072 // Reserve this size inside atoms
2073 atoms.reserve(total_size);
2074 // Fill up all these atom IDs
2075 // Loop through every cage in cageList
2076 for (int icage = 0; icage < (*cageList).size(); icage++) {
2077 // Skip if the cage is of a different type
2078 if ((*cageList)[icage].type != type) {
2079 continue;
2080 }
2081 // Loop through every ring inside Cage
2082 for (int k = 0; k < (*cageList)[icage].rings.size(); k++) {
2083 iring = (*cageList)[icage].rings[k]; // Current ring index
2084 std::move(rings[iring].begin(), rings[iring].end(),
2085 std::back_inserter(atoms));
2086 } // end of loop through every ring in icage
2087
2088 } // end of loop through all cages in cageList
2089
2090 // Sort the array according to atom ID, which will be needed to get the
2091 // unique IDs and to remove duplicates
2092 sort(atoms.begin(), atoms.end());
2093 // Get the unique atom IDs
2094 auto ip = std::unique(atoms.begin(), atoms.end());
2095 // Resize the vector to remove undefined terms
2096 atoms.resize(std::distance(atoms.begin(), ip));
2097 // If the number of atoms is less than the total nop, add dummy atoms
2098 if (atoms.size() != yCloud->nop) {
2099 padAtoms = true;
2100 bondTypes = 1;
2101 }
2102 // ----------------
2103 // Write output to file inside the output directory
2104 outputFile.open("../output/" + filename);
2105 // FORMAT:
2106 // Comment Line
2107 // 4 atoms
2108 // 4 bonds
2109 // 0 angles
2110 // 0 dihedrals
2111 // 0 impropers
2112 // 1 atom types
2113 // 1 bond types
2114 // 0 angle types
2115 // 0 dihedral types
2116 // 0 improper types
2117 // -1.124000 52.845002 xlo xhi
2118 // 0.000000 54.528999 ylo yhi
2119 // 1.830501 53.087501 zlo zhi
2120
2121 // Masses
2122
2123 // 1 15.999400 # O
2124
2125 // Atoms
2126
2127 // 1 1 1 0 20.239 1.298 6.873 # O
2128 // 2 1 1 0 0 5.193 6.873 # O
2129 // 3 1 1 0 2.249 1.298 6.873 # O
2130
2131 // -------
2132 // Write the header
2133 // Write comment line
2134 outputFile << "Written out by D-SEAMS\n";
2135 // Write out the number of atoms
2136 outputFile << yCloud->pts.size() << " "
2137 << "atoms"
2138 << "\n";
2139 // Number of bonds
2140 outputFile << bonds.size() << " bonds"
2141 << "\n";
2142 outputFile << "0 angles\n0 dihedrals\n0 impropers\n";
2143 // If padded atoms are required, two atom types will be required
2144 if (padAtoms) {
2145 outputFile << "2 atom types\n";
2146 } else {
2147 outputFile << "1 atom types\n";
2148 } // end of atom types
2149 outputFile
2150 << bondTypes
2151 << " bond types\n0 angle types\n0 dihedral types\n0 improper types\n";
2152 // Box lengths
2153 outputFile << "0 " << yCloud->box[0] << " xlo xhi\n";
2154 outputFile << "0 " << yCloud->box[1] << " ylo yhi\n";
2155 outputFile << "0 " << yCloud->box[2] << " zlo zhi\n";
2156 // Masses
2157 outputFile << "\nMasses\n\n";
2158 // For DDCs and HCs
2159 if (type == cage::cageType::HexC) {
2160 actualCageType = "HC";
2161 } else if (type == cage::cageType::DoubleDiaC) {
2162 actualCageType = "DDC";
2163 } else {
2164 actualCageType = "error";
2165 }
2166 //
2167 outputFile << "1 15.999400 # " << actualCageType << "\n";
2168 if (padAtoms) {
2169 outputFile << "2 1.0 # dummy\n";
2170 }
2171 // Atoms
2172 outputFile << "\nAtoms\n\n";
2173 // -------
2174 // Write out the atom coordinates
2175 // Loop through atoms
2176 for (int i = 0; i < atoms.size(); i++) {
2177 iatom = atoms[i] - 1; // The actual index is one less than the ID
2178 // -----------
2179 // Pad out
2180 // Fill in dummy atoms if some have been skipped
2181 if (atoms[i] != prevAtomID + 1) {
2182 dummyAtoms = atoms[i] - prevAtomID - 1;
2183 dummyID = prevAtomID;
2184 // Loop to write out dummy atoms
2185 for (int j = 0; j < dummyAtoms; j++) {
2186 dummyID++;
2187 jatom = dummyID - 1;
2188 // 1 molecule-tag atom-type q x y z
2189 outputFile << dummyID << " " << yCloud->pts[jatom].molID << " 2 0 "
2190 << yCloud->pts[jatom].x << " " << yCloud->pts[jatom].y << " "
2191 << yCloud->pts[jatom].z << "\n";
2192 } // end of dummy atom write-out
2193 } // end of check for dummy atom printing
2194 // -----------
2195 // Write out coordinates
2196 // 1 molecule-tag atom-type q x y z
2197 outputFile << atoms[i] << " " << yCloud->pts[iatom].molID << " 1 0 "
2198 << yCloud->pts[iatom].x << " " << yCloud->pts[iatom].y << " "
2199 << yCloud->pts[iatom].z << "\n";
2200 // update the previous atom ID
2201 prevAtomID = atoms[i];
2202 } // end of loop through all atoms in atomID
2203
2204 // Fill in the rest of the dummy atoms
2205 if (atoms[atoms.size() - 1] != yCloud->nop) {
2206 //
2207 for (int id = atoms[atoms.size() - 1] + 1; id <= yCloud->nop; id++) {
2208 jatom = id - 1;
2209 outputFile << id << " " << yCloud->pts[jatom].molID << " 2 0 "
2210 << yCloud->pts[jatom].x << " " << yCloud->pts[jatom].y << " "
2211 << yCloud->pts[jatom].z << "\n";
2212 } // end of printing out dummy atoms
2213 }
2214
2215 // Print the bonds now!
2216 outputFile << "\nBonds\n\n";
2217 // Loop through all bonds
2218 for (int ibond = 0; ibond < bonds.size(); ibond++) {
2219 // write out the bond
2220 outputFile << ibond + 1 << " 1 " << bonds[ibond][0] << " "
2221 << bonds[ibond][1] << "\n";
2222
2223 } // end of for loop for bonds
2224
2225 outputFile.close();
2226 // Once the datafile has been printed, exit
2227 return 0;
2228}
2229
2230// Legacy
2231
2236 std::string path, std::string outFile) {
2237 std::ofstream outputFile;
2238 // ----------------
2239 // Make the output directory if it doesn't exist
2240 sout::makePath(path);
2241 // ----------------
2242 // Create a new file in the output directory
2243 outputFile.open(path + outFile, std::ios_base::app);
2244
2245 // Append stuff
2246 // -----------------------
2247 // Header
2248
2249 // The format of the LAMMPS trajectory file is:
2250 // ITEM: TIMESTEP
2251 // 0
2252 // ITEM: NUMBER OF ATOMS
2253 // 4096
2254 // ITEM: BOX BOUNDS pp pp pp
2255 // -7.9599900000000001e-01 5.0164000000000001e+01
2256 // -7.9599900000000001e-01 5.0164000000000001e+01
2257 // -7.9599900000000001e-01 5.0164000000000001e+01
2258 // ITEM: ATOMS id type x y z
2259 // 1 1 0 0 0 etc
2260 outputFile << "ITEM: TIMESTEP\n";
2261 outputFile << yCloud->currentFrame << "\n";
2262 outputFile << "ITEM: NUMBER OF ATOMS\n";
2263 outputFile << yCloud->nop << "\n";
2264 outputFile << "ITEM: BOX BOUNDS pp pp pp\n";
2265 for (int k = 0; k < yCloud->boxLow.size(); k++) {
2266 outputFile << yCloud->boxLow[k] << " "
2267 << yCloud->boxLow[k] + yCloud->box[k]; // print xlo xhi etc
2268 // print out the tilt factors too if it is a triclinic box
2269 if (yCloud->box.size() == 2 * yCloud->boxLow.size()) {
2270 outputFile << " "
2271 << yCloud->box[k + yCloud->boxLow.size()]; // this would be +2
2272 // for a 2D box
2273 }
2274 outputFile << "\n"; // print end of line
2275 } // end of printing box lengths
2276 outputFile << "ITEM: ATOMS id mol type x y z\n";
2277 // -----------------------
2278 // Atom lines
2279 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
2280 outputFile << yCloud->pts[iatom].atomID << " " << yCloud->pts[iatom].molID;
2281
2282 // Cubic ice
2283 if (yCloud->pts[iatom].iceType == molSys::atom_state_type::cubic) {
2284 outputFile << " Ic " << yCloud->pts[iatom].x << " "
2285 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2286 } // end of cubic ice
2287 // Hexagonal ice
2288 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::hexagonal) {
2289 outputFile << " Ih " << yCloud->pts[iatom].x << " "
2290 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2291 } // end hexagonal ice
2292 // water
2293 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::water) {
2294 outputFile << " wat " << yCloud->pts[iatom].x << " "
2295 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2296 } // end water
2297 // interfacial
2298 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::interfacial) {
2299 outputFile << " intFc " << yCloud->pts[iatom].x << " "
2300 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2301 } // end interfacial
2302 // clathrate
2303 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::clathrate) {
2304 outputFile << " clathrate " << yCloud->pts[iatom].x << " "
2305 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2306 } // end clathrate
2307 // interClathrate
2308 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::interClathrate) {
2309 outputFile << " interClathrate " << yCloud->pts[iatom].x << " "
2310 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2311 } // end interClathrate
2312 // unclassified
2313 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::unclassified) {
2314 outputFile << " unclassified " << yCloud->pts[iatom].x << " "
2315 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2316 } // end unclassified
2317 // reCubic
2318 else if (yCloud->pts[iatom].iceType == molSys::atom_state_type::reCubic) {
2319 outputFile << " reIc " << yCloud->pts[iatom].x << " "
2320 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2321 } // end reCubic
2322 // reHexagonal
2323 else {
2324 outputFile << " reIh " << yCloud->pts[iatom].x << " "
2325 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2326 } // end reHex
2327
2328 } // end of loop through all atoms
2329
2330 // Close the file
2331 outputFile.close();
2332 return 0;
2333}
2334
2340 std::vector<std::vector<int>> nList,
2341 std::vector<double> avgQ6) {
2342 std::ofstream cijFile;
2343 std::ofstream q3File;
2344 std::ofstream q6File;
2345 // Create a new file in the output directory
2346 int nNumNeighbours;
2347 double avgQ3;
2348
2349 cijFile.open("cij.txt", std::ofstream::out | std::ofstream::app);
2350 q3File.open("q3.txt", std::ofstream::out | std::ofstream::app);
2351 q6File.open("q6.txt", std::ofstream::out | std::ofstream::app);
2352
2353 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
2354 if (yCloud->pts[iatom].type != 1) {
2355 continue;
2356 }
2357 // Check for slice later
2358 nNumNeighbours = nList[iatom].size() - 1;
2359 avgQ3 = 0.0;
2360 for (int j = 0; j < nNumNeighbours; j++) {
2361 cijFile << yCloud->pts[iatom].c_ij[j].c_value << "\n";
2362 avgQ3 += yCloud->pts[iatom].c_ij[j].c_value;
2363 } // Loop through neighbours
2364 avgQ3 /= nNumNeighbours;
2365 q3File << avgQ3 << "\n";
2366 q6File << avgQ6[iatom] << "\n";
2367 } // loop through all atoms
2368
2369 // Close the file
2370 cijFile.close();
2371 q3File.close();
2372 q6File.close();
2373
2374 return 0;
2375}
2376
2382 std::string fileName, bool isSlice, int largestIceCluster) {
2383 std::ofstream clusterFile;
2384 // Create a new file in the output directory
2385 clusterFile.open(fileName, std::ofstream::out | std::ofstream::app);
2386 clusterFile << yCloud->currentFrame << " " << largestIceCluster << "\n";
2387 // Close the file
2388 clusterFile.close();
2389 return 0;
2390}
2391
2399 std::vector<std::vector<int>> nList, std::vector<cage::iceType> atomTypes,
2400 std::string path, bool bondsBetweenDummy) {
2401 //
2402 std::ofstream outputFile;
2403 int iatom; // Index, not atom ID
2404 int currentAtomType; // Current atom type: a value from 1 to 4
2405 int numAtomTypes = 6; // DDC, HC, Mixed, dummy, mixed2 and pnc
2406 int bondTypes = 1;
2407 // Bond stuff
2408 std::vector<std::vector<int>> bonds; // Vector of vector, with each row
2409 // containing the atom IDs of each bond
2410 std::string filename =
2411 "system-" + std::to_string(yCloud->currentFrame) + ".data";
2412
2413 // ---------------
2414 // Get the bonds
2415 if (bondsBetweenDummy) {
2416 bonds = bond::populateBonds(nList, yCloud);
2417 } // create bonds between dummy atoms
2418 else {
2419 bonds = bond::populateBonds(nList, yCloud, atomTypes);
2420 } // only create bonds between non-dummy atoms
2421 //
2422 // ----------------
2423 // Make the output directory if it doesn't exist
2424 sout::makePath(path);
2425 std::string outputDirName = path + "bulkTopo";
2426 sout::makePath(outputDirName);
2427 outputDirName = path + "bulkTopo/dataFiles/";
2428 sout::makePath(outputDirName);
2429 // ----------------
2430 // Write output to file inside the output directory
2431 outputFile.open(path + "bulkTopo/dataFiles/" + filename);
2432 // FORMAT:
2433 // Comment Line
2434 // 4 atoms
2435 // 4 bonds
2436 // 0 angles
2437 // 0 dihedrals
2438 // 0 impropers
2439 // 1 atom types
2440 // 1 bond types
2441 // 0 angle types
2442 // 0 dihedral types
2443 // 0 improper types
2444 // -1.124000 52.845002 xlo xhi
2445 // 0.000000 54.528999 ylo yhi
2446 // 1.830501 53.087501 zlo zhi
2447
2448 // Masses
2449
2450 // 1 15.999400 # O
2451
2452 // Atoms
2453
2454 // 1 1 1 0 20.239 1.298 6.873 # O
2455 // 2 1 1 0 0 5.193 6.873 # O
2456 // 3 1 1 0 2.249 1.298 6.873 # O
2457
2458 // -------
2459 // Write the header
2460 // Write comment line
2461 outputFile << "Written out by D-SEAMS\n";
2462 // Write out the number of atoms
2463 outputFile << yCloud->pts.size() << " "
2464 << "atoms"
2465 << "\n";
2466 // Number of bonds
2467 outputFile << bonds.size() << " bonds"
2468 << "\n";
2469 outputFile << "0 angles\n0 dihedrals\n0 impropers\n";
2470 // There are maxDepth-2 total types of prisms + dummy
2471 outputFile << numAtomTypes << " atom types\n";
2472 // Bond types
2473 outputFile
2474 << bondTypes
2475 << " bond types\n0 angle types\n0 dihedral types\n0 improper types\n";
2476 // Box lengths
2477 outputFile << yCloud->boxLow[0] << " " << yCloud->boxLow[0] + yCloud->box[0]
2478 << " xlo xhi\n";
2479 outputFile << yCloud->boxLow[1] << " " << yCloud->boxLow[1] + yCloud->box[1]
2480 << " ylo yhi\n";
2481 outputFile << yCloud->boxLow[2] << " " << yCloud->boxLow[2] + yCloud->box[2]
2482 << " zlo zhi\n";
2483 // Masses
2484 outputFile << "\nMasses\n\n";
2485 outputFile << "1 15.999400 # dummy\n";
2486 outputFile << "2 15.999400 # hc \n";
2487 outputFile << "3 15.999400 # ddc \n";
2488 outputFile << "4 15.999400 # mixed \n";
2489 outputFile << "5 15.999400 # pnc \n";
2490 outputFile << "6 15.999400 # pncHexaMixed \n";
2491 // Atoms
2492 outputFile << "\nAtoms\n\n";
2493 // -------
2494 // Write out the atom coordinates
2495 // Loop through atoms
2496 for (int i = 0; i < yCloud->pts.size(); i++) {
2497 iatom =
2498 yCloud->pts[i].atomID; // The actual ID can be different from the index
2499 //
2500 // Get the atom type
2501 // hc atom type
2502 if (atomTypes[i] == cage::iceType::hc) {
2503 currentAtomType = 2;
2504 } // hc
2505 else if (atomTypes[i] == cage::iceType::ddc) {
2506 currentAtomType = 3;
2507 } // ddc
2508 // mixed
2509 else if (atomTypes[i] == cage::iceType::mixed) {
2510 currentAtomType = 4;
2511 } // mixed
2512 // pnc
2513 else if (atomTypes[i] == cage::iceType::pnc) {
2514 currentAtomType = 5;
2515 } // mixed
2516 // pnc and DDCs/HCs mixed
2517 else if (atomTypes[i] == cage::iceType::mixed2) {
2518 currentAtomType = 6;
2519 } // mixed
2520 // dummy
2521 else {
2522 currentAtomType = 1;
2523 } // dummy
2524 //
2525 // Write out coordinates
2526 // atomID molecule-tag atom-type q x y z
2527 outputFile << iatom << " " << yCloud->pts[i].molID << " " << currentAtomType
2528 << " 0 " << yCloud->pts[i].x << " " << yCloud->pts[i].y << " "
2529 << yCloud->pts[i].z << "\n";
2530
2531 } // end of loop through all atoms in pointCloud
2532
2533 // Print the bonds now!
2534 outputFile << "\nBonds\n\n";
2535 // Loop through all bonds
2536 for (int ibond = 0; ibond < bonds.size(); ibond++) {
2537 //
2538 outputFile << ibond + 1 << " 1 " << bonds[ibond][0] << " "
2539 << bonds[ibond][1] << "\n";
2540 } // end of for loop for bonds
2541
2542 // Once the datafile has been printed, exit
2543 return 0;
2544}
2545
2551 std::string path, molSys::PointCloud<molSys::Point<double>, double> *yCloud,
2552 std::vector<int> atoms, int clusterID, cage::cageType type) {
2553 //
2554 std::ofstream outputFile;
2555 std::string filename = "cluster-" + std::to_string(clusterID) + ".xyz";
2556 int nAtoms = atoms.size(); // Number of atoms
2557 int iatom; // Current atom
2558 // ----------------
2559 // Make the output directory if it doesn't exist
2560 sout::makePath(path);
2561 std::string outputDirName = path + "bulkTopo";
2562 sout::makePath(outputDirName);
2563 outputDirName = path + "bulkTopo/clusterXYZ/";
2564 sout::makePath(outputDirName);
2565 outputDirName = path + "bulkTopo/clusterXYZ/frame-" +
2566 std::to_string(yCloud->currentFrame);
2567 sout::makePath(outputDirName);
2568 // ----------------
2569 // Write output to file inside the output directory
2570 outputFile.open(path + "bulkTopo/clusterXYZ/frame-" +
2571 std::to_string(yCloud->currentFrame) + "/" + filename);
2572
2573 // Format of an XYZ file:
2574 // 1970
2575 // generated by VMD
2576 // O 43.603500 16.926201 15.215700
2577 // O 39.912601 14.775100 19.379200
2578 outputFile << nAtoms << "\n"; // Number of atoms
2579 outputFile
2580 << "Generated by d-SEAMS. 0 type=hc and 1 type =ddc\n"; // Comment line
2581 //
2582 // Write out all the atom coordinates
2583 for (int i = 0; i < nAtoms; i++) {
2584 iatom = atoms[i]; // Atom index to be printed out
2585 // TODO: Should print string representation
2586 outputFile << static_cast<int>(type) << " " << yCloud->pts[iatom].x << " "
2587 << yCloud->pts[iatom].y << " " << yCloud->pts[iatom].z << "\n";
2588 } // end of loop through all atoms
2589
2590 outputFile.close();
2591
2592 return 0;
2593}
std::vector< std::vector< int > > createBondsFromCages(std::vector< std::vector< int > > rings, std::vector< cage::Cage > *cageList, cage::cageType type, int *nRings)
Definition bond.cpp:529
std::vector< std::vector< int > > populateBonds(std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
Definition bond.cpp:26
cageType
Definition cage.hpp:54
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
@ hexagonal
Ih, or particle type signifying Hexagonal Ice.
@ reCubic
Reclassified as cubic ice, according to the order parameter.
@ interfacial
Interfacial ice: ice-like molecules which do not fulfill the strict criteria of the Ic or Ih phases.
@ cubic
Ic, or particle type signifying Cubic Ice.
@ interClathrate
Interfacial clathrate ice phase.
@ water
Liquid/amorphous phase.
@ clathrate
Clathrate ice phase.
@ unclassified
Not classified into any other category.
std::vector< std::vector< int > > readBonds(std::string filename)
Reads bonds into a vector of vectors from a file with a specific format.
int writeBasalRingsPrism(std::vector< int > *basal1, std::vector< int > *basal2, int prismNum, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, bool isDeformed)
Write out the basal rings for a particular prism.
int writeMoleculeIDsInSlice(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
int writeHisto(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > nList, std::vector< double > avgQ6)
int writePrismNum(std::string path, std::vector< int > nPrisms, std::vector< int > nDefPrisms, std::vector< double > heightPercent, int maxDepth, int currentFrame, int firstFrame)
int writeRingNumBulk(std::string path, int currentFrame, std::vector< int > nRings, int maxDepth, int firstFrame)
int writeLAMMPSdumpSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::string path)
int writeRingNum(std::string path, int currentFrame, std::vector< int > nRings, std::vector< double > coverageAreaXY, std::vector< double > coverageAreaXZ, std::vector< double > coverageAreaYZ, int maxDepth, int firstFrame)
int makePath(const std::string &path)
int writeLAMMPSdataAllPrisms(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > nList, std::vector< int > atomTypes, int maxDepth, std::string path, bool doShapeMatching=false)
Write a data file for prisms of every type.
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.
int writeTopoBulkData(std::string path, int currentFrame, int numHC, int numDDC, int mixedRings, int basalRings, int prismaticRings, int firstFrame)
int writeDump(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::string path, std::string outFile)
Generic function for writing out to a dump file.
int writeLAMMPSdumpINT(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > rmsdPerAtom, std::vector< int > atomTypes, int maxDepth, std::string path)
Write out a LAMMPS dump file containing the RMSD per atom.
int writePrisms(std::vector< int > *basal1, std::vector< int > *basal2, int prismNum, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
Function for writing out each prism.
int writeLAMMPSdata(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > rings, std::vector< std::vector< int > > bonds, std::string filename="system-rings.data")
Write a data file for rings.
int printRDF(std::string fileName, std::vector< double > *rdfValues, double binwidth, int nbin)
Function for printing out the RDF, given the filename.
int writeMoleculeIDsExpressionSelectOVITO(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
int writeLAMMPSdataCages(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > rings, std::vector< cage::Cage > *cageList, cage::cageType type, int numCages, std::string filename="system-cages.data")
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)
int writeBasalRingsHex(std::vector< int > currentCage, int cageNum, std::vector< std::vector< int > > nList, std::vector< std::vector< int > > rings)
Write out the basal rings of a particular Hexagonal cage.
int writeEachCage(std::vector< int > currentCage, int cageNum, cage::cageType type, std::vector< std::vector< int > > rings, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
Write out a particular cage to a file.
int writeRings(std::vector< std::vector< int > > rings, std::string filename="rings.dat")
Function for printing out ring info, when there is no volume slice.
int writeAllCages(std::string path, std::vector< cage::Cage > *cageList, std::vector< std::vector< int > > rings, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, int currentFrame)
int writeLAMMPSdumpCages(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > rmsdPerAtom, std::vector< int > atomTypes, std::string path, int firstFrame)
Write out a LAMMPS dump file containing the RMSD per atom for bulk ice.
int writeXYZcluster(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< int > atoms, int clusterID, cage::cageType type)
Function for writing out the XYZ files for each cluster.
int writeCluster(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::string fileName="cluster.txt", bool isSlice=false, int largestIceCluster=0)
Function for printing the largest ice cluster.
int writeClusterStats(std::string path, int currentFrame, int largestCluster, int numOfClusters, int smallestCluster, double avgClusterSize, int firstFrame)
Function for writing out cluster statistics.
int writeLAMMPSdataPrisms(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > rings, bool useBondFile, std::string bondFile, std::vector< int > listPrism, std::vector< std::vector< int > > nList, std::string filename="system-prisms.data")
Write a data file for prisms of a single type.
File for functions that read in files).
This contains a collection of points; contains information for a particular frame.
Definition mol_sys.hpp:170
This contains per-particle information.
Definition mol_sys.hpp:149