selection.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 <selection.hpp>
16
17#include <icecream.hpp>
18
19// -----------------------------------------------------------------------------------------------------
20// FUNCTIONS FOR SELECTIONS
21// -----------------------------------------------------------------------------------------------------
22
40 int atomTypeI, bool isSlice, std::array<double, 3> coordLow,
41 std::array<double, 3> coordHigh) {
42 //
43 int natoms = 0; // Number of atoms of the desired type
44 bool pointInSlice = true; // If the current point is in the slice, this is true (otherwise this is false)
45
46 // --------
47 // Before filling up the PointCloud, if the vectors are filled
48 // empty them
49 *outCloud = molSys::clearPointCloud(outCloud);
50 // --------
51
52 // Loop through every iatom and check the type
53 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
54 // Skip if the atom is not of the desired type
55 if (yCloud->pts[iatom].type != atomTypeI) {
56 continue;
57 } // end of checking for the type
58 // ----------------
59 // only if a slice has been requested
60 if (isSlice) {
61 pointInSlice = sinp::atomInSlice(yCloud->pts[iatom].x, yCloud->pts[iatom].y, yCloud->pts[iatom].z,
62 coordLow, coordHigh);
63 // Skip if the atom is not part of the slice
64 if (!pointInSlice) {
65 continue;
66 } // skipped for atoms not in the slice
67 } // end of slice handling
68 //
69 // Actually add the atoms to the outCloud
70 natoms++; // Update the number of atoms in outCloud
71 outCloud->pts.push_back(yCloud->pts[iatom]); // Update the pts vector
72 outCloud->idIndexMap[yCloud->pts[iatom].atomID] =
73 outCloud->pts.size() - 1; // array index
74 }
75
76 // Update the number of particles in the PointCloud
77 outCloud->nop = outCloud->pts.size();
78
79 // Box and box lengths
80 outCloud->box = yCloud->box;
81 outCloud->boxLow = yCloud->boxLow;
82
83 // Update the frame number
84 outCloud->currentFrame = yCloud->currentFrame;
85
86 return *outCloud;
87}
88
103 bool clearPreviousSliceSelection,
104 std::array<double, 3> coordLow,
105 std::array<double, 3> coordHigh) {
106 //
107 bool pointInSlice = true; // If the current point is in the slice, this is true (otherwise this is false)
108
109 // --------------------
110 // Set inSlice to false for every atom first
111 if (clearPreviousSliceSelection)
112 {
113 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
114 yCloud->pts[iatom].inSlice = false;
115 }
116 } // end of init
117 // --------------------
118
119 // Loop through every iatom and check if the atom is in the slice or not
120 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
121 // Check if the current atom is in the slice
122 pointInSlice = sinp::atomInSlice(yCloud->pts[iatom].x, yCloud->pts[iatom].y, yCloud->pts[iatom].z,
123 coordLow, coordHigh);
124
125 yCloud->pts[iatom].inSlice = pointInSlice; // iatom is inside the slice
126 //
127 }
128
129 return;
130}
131
149 bool clearPreviousSliceSelection,
150 std::array<double, 3> coordLow,
151 std::array<double, 3> coordHigh) {
152 //
153 bool pointInSlice = true; // If the current point is in the slice, this is true (otherwise this is false)
154 std::unordered_multimap<int, int>
155 molIDAtomIDmap; // Unordered multimap with molecule IDs of the atoms as the keys and the
156 // atom IDs as the values. More than one atom can have the same molecule ID
157 int iatomMolID; // molID of the current iatom
158 int jatomID; // atom ID of the current jatom
159 int jatomIndex; // index of jatom
160
161 // --------------------
162 // Get the unordered map of the atom IDs (keys) and the molecular IDs
163 // (values)
164 molIDAtomIDmap = molSys::createMolIDAtomIDMultiMap(yCloud);
165 // --------------------
166 // Set inSlice to false for every atom first
167 if (clearPreviousSliceSelection)
168 {
169 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
170 yCloud->pts[iatom].inSlice = false;
171 }
172 } // end of init
173 // --------------------
174
175 // Loop through every iatom and check if the atom is in the slice or not
176 for (int iatom = 0; iatom < yCloud->nop; iatom++) {
177 // Check if the current atom is in the slice
178 pointInSlice = sinp::atomInSlice(yCloud->pts[iatom].x, yCloud->pts[iatom].y, yCloud->pts[iatom].z,
179 coordLow, coordHigh);
180 //
181 // Set the inSlice bool for the particular Point
182 if (pointInSlice)
183 {
184 yCloud->pts[iatom].inSlice = true; // iatom is inside the slice
185 // Find mol ID and atoms with that particular molecular ID
186 iatomMolID = yCloud->pts[iatom].molID; // molecule ID
187 // -----------
188 // Find all atoms with iatomMolID and set the inSlice bool
189 // to true
190 auto range = molIDAtomIDmap.equal_range(iatomMolID);
191 // Loop through all atoms with iatomMolID
192 for (auto it = range.first; it != range.second; it++)
193 {
194 // it->second gives the value (in this case, the atom ID)
195 jatomID = it->second; // Atom ID with molecule ID equal to iatomMolID
196 auto gotJ = yCloud->idIndexMap.find(jatomID);
197 jatomIndex = gotJ->second;
198 // Set the jatom inSlice bool to true
199 yCloud->pts[jatomIndex].inSlice = true; // jatomIndex is inside the slice
200 }
201 // -----------
202 } // the atom is in the slice
203 else{
204 yCloud->pts[iatom].inSlice = false; // iatom is not in the slice
205 } // atom is not in the slice
206 }
207
208 return;
209}
210
227 std::unordered_multimap<int,int> molIDAtomIDmap,
228 int molID, bool inSliceValue) {
229 //
230 int jatomID; // atom ID of the current jatom
231 int jatomIndex; // index of jatom
232
233 // Find all atoms with molID and set the inSlice bool to inSliceValue
234 auto range = molIDAtomIDmap.equal_range(molID);
235
236 // Loop through all atoms with molID
237 for (auto it = range.first; it != range.second; it++){
238 // it->second gives the value (in this case, the atom ID)
239 jatomID = it->second; // Atom ID with molecule ID equal to iatomMolID
240 auto gotJ = yCloud->idIndexMap.find(jatomID);
241 jatomIndex = gotJ->second;
242 // Set the jatom inSlice bool to true
243 yCloud->pts[jatomIndex].inSlice = inSliceValue; // jatomIndex is assigned inSliceValue
244 } // end of loop through all atoms with molID
245
246 // IC(yCloud->pts[jatomIndex]);
247
248 return;
249}
250
266 std::vector<std::vector<int>> rings, molSys::PointCloud<molSys::Point<double>, double> *oCloud,
268 std::array<double, 3> coordLow, std::array<double, 3> coordHigh, bool identicalCloud) {
269 //
270 // A vector of bool values, such that every ring has a value of true (in the slice) or false (not in the slice)
271 std::vector<bool> ringInSlice(rings.size(), false); // all set to false initially.
272 int jatomIndex, jatomID; // Index and ID in oCloud
273 int jatomIndex1; // Index in yCloud
274 std::unordered_multimap<int, int>
275 molIDAtomIDmap; // Unordered multimap with molecule IDs of the atoms as the keys and the
276 // atom IDs as the values. More than one atom can have the same molecule ID
277
278 // --------------------
279 // Sets all O atoms within the slice to an inSlice bool value of true. If a single atom of a molecule is in the
280 // slice, then all atoms in the molecule will also be inside the slice
281 gen::moleculesInSingleSlice(oCloud, true, coordLow, coordHigh);
282 // --------------------
283 // Get the unordered map of the atom IDs (keys) and the molecular IDs
284 // (values)
285 molIDAtomIDmap = molSys::createMolIDAtomIDMultiMap(yCloud);
286 // --------------------
287
288 // Loop through every iatom present in the slice in oCloud
289 // Check to see if iatom is in any ring. If it is present in a ring, set that ring to true
290 // Change the inSlice bool of every iatom in the ring to true if false. Set also the inSlice bool
291 // of the output cloud if it is not identical.
292
293 // Loop through every iatom present in the slice in oCloud to determine which rings are in the slice
294 // The indices of oCloud and rings should match (or this will produce unexpected results)
295 for (int iatom = 0; iatom < oCloud->nop; iatom++) {
296 // Skip if iatom is not in the slice
297 if (!oCloud->pts[iatom].inSlice)
298 {
299 continue;
300 } // skip for iatom not in slice
301 //
302 // For iatom in the slice,
303 // loop through all rings to find all the rings it is a part of
304 for (int iring = 0; iring < rings.size(); iring++)
305 {
306 // Skip if iring is in the slice already
307 if (ringInSlice[iring])
308 {
309 continue;
310 } // skip for iring in slice
311 // Check and see if iatom is in iring
312 if(std::find(rings[iring].begin(), rings[iring].end(), iatom)!=rings[iring].end()){
313 // Found iatom; ring is part of the slice
314 ringInSlice[iring] = true; // update the vector of bool values
315 // --------------------------
316 // Change the inSlice bool of every iatom in oCloud
317 // (and optionally, yCloud) in the ring to true
318 // Loop through the elements of the ring
319 for (int j = 0; j < rings[iring].size(); j++)
320 {
321 jatomIndex = rings[iring][j]; // Index of the atom in oCloud
322 // Set this to true in oCloud
323 oCloud->pts[jatomIndex].inSlice = true; // part of slice
324 jatomID = oCloud->pts[jatomIndex].atomID; // Atom ID
325 // Now if oCloud and yCloud are not the same, use the
326 // atom ID to set the inSlice bool value in yCloud
327 if (!identicalCloud)
328 {
329 // Find the index corresponding to the same atom in yCloud
330 auto gotJ = yCloud->idIndexMap.find(jatomID);
331 jatomIndex1 = gotJ->second;
332 // throw if not found ?
333 // Set the jatom inSlice bool to true
334 yCloud->pts[jatomIndex1].inSlice = true; // jatomIndex is inside the slice
335 // set the inSlice value of all atoms in yCloud with the current molecule ID
336 gen::setAtomsWithSameMolID(yCloud, molIDAtomIDmap,
337 yCloud->pts[jatomIndex1].molID, true);
338 } // end of setting values in yCloud
339 } // end of loop through the elements of the current ring
340 // --------------------------
341 } // found iatom in the ring
342 //
343 } // end of loop through all rings searching for iatom
344 //
345 } // end of loop through atoms in oCloud in the slice
346
347
348 // Optionally add support for molecule slice update if yCloud and oCloud are not identical?
349 // Some other bool?
350 // IC(ringInSlice);
351
352 return;
353}
354
355// -----------------------------------------------------------------------------------------------------
356// FUNCTIONS FOR SELECTIONS (RINGS)
357// -----------------------------------------------------------------------------------------------------
358
376 std::string path, std::vector<std::vector<int>> rings,
379 std::array<double, 3> coordLow, std::array<double, 3> coordHigh, bool identicalCloud) {
380 //
381
382 //Given the full yCloud PointCloud, set the inSlice bool for every atom,
383 // if the molecules are inside the specified (single) region.
384 // gen::atomsInSingleSlice(yCloud, true, coordLow, coordHigh);
385 gen::moleculesInSingleSlice(yCloud, true, coordLow, coordHigh);
386
387 // Make sure that molecules which participate in the rings inside the slice are also
388 // in the selection
389 ring::getEdgeMoleculesInRings(rings, oCloud, yCloud, coordLow, coordHigh, identicalCloud);
390
391 // Print out the molecule IDs of all the atoms in the slice
392 sout::writeMoleculeIDsInSlice(path, yCloud);
393 // Print out a command that could be used for an expression select command in OVITO
395
396 // Print out the dump of all atoms and molecules, with an inSlice value printed in a separate column
397 // H atoms not included in the slice (TODO: fix)
398 sout::writeLAMMPSdumpSlice(yCloud, path);
399
400 IC(rings[0]);
401
402 return;
403}
std::unordered_multimap< int, int > createMolIDAtomIDMultiMap(molSys::PointCloud< molSys::Point< double >, double > *yCloud)
Definition mol_sys.cpp:67
molSys::PointCloud< molSys::Point< double >, double > clearPointCloud(molSys::PointCloud< molSys::Point< double >, double > *yCloud)
//! Function for clearing vectors in PointCloud after multiple usage
Definition mol_sys.cpp:24
molSys::PointCloud< molSys::Point< double >, double > getPointCloudOneAtomType(molSys::PointCloud< molSys::Point< double >, double > *yCloud, molSys::PointCloud< molSys::Point< double >, double > *outCloud, int atomTypeI, bool isSlice=false, std::array< double, 3 > coordLow=std::array< double, 3 >{0, 0, 0}, std::array< double, 3 > coordHigh=std::array< double, 3 >{0, 0, 0})
Definition selection.cpp:37
void atomsInSingleSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, bool clearPreviousSliceSelection=true, std::array< double, 3 > coordLow=std::array< double, 3 >{0, 0, 0}, std::array< double, 3 > coordHigh=std::array< double, 3 >{0, 0, 0})
void getEdgeMoleculesInRings(std::vector< std::vector< int > > rings, molSys::PointCloud< molSys::Point< double >, double > *oCloud, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::array< double, 3 > coordLow, std::array< double, 3 > coordHigh, bool identicalCloud=false)
void setAtomsWithSameMolID(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::unordered_multimap< int, int > molIDAtomIDmap, int molID, bool inSliceValue=true)
void moleculesInSingleSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, bool clearPreviousSliceSelection=true, std::array< double, 3 > coordLow=std::array< double, 3 >{0, 0, 0}, std::array< double, 3 > coordHigh=std::array< double, 3 >{0, 0, 0})
void printSliceGetEdgeMoleculesInRings(std::string path, std::vector< std::vector< int > > rings, molSys::PointCloud< molSys::Point< double >, double > *oCloud, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::array< double, 3 > coordLow, std::array< double, 3 > coordHigh, bool identicalCloud=false)
bool atomInSlice(double x, double y, double z, std::array< double, 3 > coordLow, std::array< double, 3 > coordHigh)
int writeMoleculeIDsInSlice(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
int writeLAMMPSdumpSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::string path)
int writeMoleculeIDsExpressionSelectOVITO(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
File containing functions used to define 'selections' in a given range, using ring information.
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