OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
NameFinder.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44#include "selection/NameFinder.hpp"
45
48#include "utils/StringUtils.hpp"
49#include "utils/simError.h"
50#include "utils/wildcards.hpp"
51
52namespace OpenMD {
53
54 NameFinder::NameFinder(SimInfo* info) : info_(info) {
55 nObjects_.push_back(info_->getNGlobalAtoms() +
56 info_->getNGlobalRigidBodies());
57 nObjects_.push_back(info_->getNGlobalBonds());
58 nObjects_.push_back(info_->getNGlobalBends());
59 nObjects_.push_back(info_->getNGlobalTorsions());
60 nObjects_.push_back(info_->getNGlobalInversions());
61 nObjects_.push_back(info_->getNGlobalMolecules());
62
63 loadNames();
64 }
65
66 void NameFinder::loadNames() {
67 SimInfo::MoleculeIterator mi;
68 Molecule::AtomIterator ai;
69 Molecule::RigidBodyIterator rbIter;
70 Molecule::BondIterator bondIter;
71 Molecule::BendIterator bendIter;
72 Molecule::TorsionIterator torsionIter;
73 Molecule::InversionIterator inversionIter;
74
75 Molecule* mol;
76 Atom* atom;
77 RigidBody* rb;
78 Bond* bond;
79 Bend* bend;
80 Torsion* torsion;
81 Inversion* inversion;
82
83 root_ = std::make_shared<TreeNode>();
84 root_->bs.resize(nObjects_);
85 root_->bs.setAll(); //
86
87 for (mol = info_->beginMolecule(mi); mol != NULL;
88 mol = info_->nextMolecule(mi)) {
89 std::string molName = mol->getMoleculeName();
90 TreeNodePtr molNode = createNode(root_, molName);
91 molNode->bs.bitsets_[MOLECULE].setBitOn(mol->getGlobalIndex());
92
93 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
94 std::string atomName = atom->getType();
95 TreeNodePtr atomNode = createNode(molNode, atomName);
96
97 molNode->bs.bitsets_[STUNTDOUBLE].setBitOn(atom->getGlobalIndex());
98 atomNode->bs.bitsets_[STUNTDOUBLE].setBitOn(atom->getGlobalIndex());
99 }
100
101 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
102 rb = mol->nextRigidBody(rbIter)) {
103 std::string rbName = rb->getType();
104 TreeNodePtr rbNode = createNode(molNode, rbName);
105
106 molNode->bs.bitsets_[STUNTDOUBLE].setBitOn(rb->getGlobalIndex());
107 rbNode->bs.bitsets_[STUNTDOUBLE].setBitOn(rb->getGlobalIndex());
108
109 // COMMENTED OUT because rigid bodies are IntegrableObjects
110 // (e.g. they are independently mobile, so selecting their
111 // member atoms will give some odd results if we are computing
112 // degrees of freedom elsewhere.
113
114 // //create nodes for atoms belong to this rigidbody
115 // for(atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai))
116 // {
117 // std::string rbAtomName = atom->getType();
118 // TreeNodePtr rbAtomNode = createNode(rbNode, rbAtomName);
119
120 // rbAtomNode->bs.bitsets_[STUNTDOUBLE].setBitOn(atom->getGlobalIndex());
121 // }
122 }
123
124 for (bond = mol->beginBond(bondIter); bond != NULL;
125 bond = mol->nextBond(bondIter)) {
126 std::string bondName = bond->getName();
127 TreeNodePtr bondNode = createNode(molNode, bondName);
128
129 molNode->bs.bitsets_[BOND].setBitOn(bond->getGlobalIndex());
130 bondNode->bs.bitsets_[BOND].setBitOn(bond->getGlobalIndex());
131
132 std::vector<Atom*> atoms = bond->getAtoms();
133 std::vector<Atom*>::iterator ai;
134
135 for (ai = atoms.begin(); ai != atoms.end(); ++ai) {
136 std::string atomName = (*ai)->getType();
137 TreeNodePtr atomNode = createNode(bondNode, atomName);
138 atomNode->bs.bitsets_[STUNTDOUBLE].setBitOn((*ai)->getGlobalIndex());
139 }
140 }
141 for (bend = mol->beginBend(bendIter); bend != NULL;
142 bend = mol->nextBend(bendIter)) {
143 std::string bendName = bend->getName();
144 TreeNodePtr bendNode = createNode(molNode, bendName);
145
146 molNode->bs.bitsets_[BEND].setBitOn(bend->getGlobalIndex());
147 bendNode->bs.bitsets_[BEND].setBitOn(bend->getGlobalIndex());
148
149 std::vector<Atom*> atoms = bend->getAtoms();
150 std::vector<Atom*>::iterator ai;
151
152 for (ai = atoms.begin(); ai != atoms.end(); ++ai) {
153 std::string atomName = (*ai)->getType();
154 TreeNodePtr atomNode = createNode(bendNode, atomName);
155 atomNode->bs.bitsets_[STUNTDOUBLE].setBitOn((*ai)->getGlobalIndex());
156 }
157 }
158 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
159 torsion = mol->nextTorsion(torsionIter)) {
160 std::string torsionName = torsion->getName();
161 TreeNodePtr torsionNode = createNode(molNode, torsionName);
162
163 molNode->bs.bitsets_[TORSION].setBitOn(torsion->getGlobalIndex());
164 torsionNode->bs.bitsets_[TORSION].setBitOn(torsion->getGlobalIndex());
165
166 std::vector<Atom*> atoms = torsion->getAtoms();
167 std::vector<Atom*>::iterator ai;
168
169 for (ai = atoms.begin(); ai != atoms.end(); ++ai) {
170 std::string atomName = (*ai)->getType();
171 TreeNodePtr atomNode = createNode(torsionNode, atomName);
172 atomNode->bs.bitsets_[STUNTDOUBLE].setBitOn((*ai)->getGlobalIndex());
173 }
174 }
175 for (inversion = mol->beginInversion(inversionIter); inversion != NULL;
176 inversion = mol->nextInversion(inversionIter)) {
177 std::string inversionName = inversion->getName();
178 TreeNodePtr inversionNode = createNode(molNode, inversionName);
179
180 molNode->bs.bitsets_[INVERSION].setBitOn(inversion->getGlobalIndex());
181 inversionNode->bs.bitsets_[INVERSION].setBitOn(
182 inversion->getGlobalIndex());
183 std::vector<Atom*> atoms = inversion->getAtoms();
184 std::vector<Atom*>::iterator ai;
185
186 for (ai = atoms.begin(); ai != atoms.end(); ++ai) {
187 std::string atomName = (*ai)->getType();
188 TreeNodePtr atomNode = createNode(inversionNode, atomName);
189 atomNode->bs.bitsets_[STUNTDOUBLE].setBitOn((*ai)->getGlobalIndex());
190 }
191 }
192 }
193 }
194
195 TreeNodePtr NameFinder::createNode(TreeNodePtr parent,
196 const std::string& name) {
197 TreeNodePtr node;
198 std::map<std::string, TreeNodePtr>::iterator foundIter;
199 foundIter = parent->children.find(name);
200 if (foundIter == parent->children.end()) {
201 node = std::make_shared<TreeNode>();
202 node->name = name;
203 node->bs.resize(nObjects_);
204 parent->children.insert(std::make_pair(name, node));
205 } else {
206 node = foundIter->second;
207 }
208 return node;
209 }
210
211 SelectionSet NameFinder::match(const std::string& name) {
212 SelectionSet bs(nObjects_);
213
214 StringTokenizer tokenizer(name, ".");
215
216 std::vector<std::string> names;
217 while (tokenizer.hasMoreTokens()) {
218 names.push_back(tokenizer.nextToken());
219 }
220
221 int size = names.size();
222
223 switch (size) {
224 case 1:
225 // could be molecule name, atom name and rigidbody name
226 matchMolecule(names[0], bs);
227 matchStuntDouble("*", names[0], bs);
228 matchBond("*", names[0], bs);
229 matchBend("*", names[0], bs);
230 matchTorsion("*", names[0], bs);
231 matchInversion("*", names[0], bs);
232
233 break;
234 case 2:
235 // could be molecule.*(include atoms and rigidbodies) or rigidbody.*(atoms
236 // belong to rigidbody)
237
238 if (!isInteger(names[1])) {
239 matchRigidAtoms("*", names[0], names[1], bs);
240 matchStuntDouble(names[0], names[1], bs);
241 } else {
242 int internalIndex = lexi_cast<int>(names[1]);
243 if (internalIndex < 0) {
244 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
245 "NameFinder : Name %s.%s is an invalid name.\n",
246 names[0].c_str(), names[1].c_str());
247 painCave.severity = OPENMD_WARNING;
248 painCave.isFatal = 0;
249 simError();
250 } else {
251 matchInternalIndex(names[0], internalIndex, bs);
252 }
253 }
254
255 break;
256 case 3:
257 // must be molecule.rigidbody.*
258 matchRigidAtoms(names[0], names[1], names[2], bs);
259 break;
260 default:
261 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
262 "NameFinder : Invalid Name %s.\n", name.c_str());
263 painCave.severity = OPENMD_WARNING;
264 painCave.isFatal = 0;
265 simError();
266 break;
267 }
268 return bs;
269 }
270
271 void NameFinder::matchMolecule(const std::string& molName, SelectionSet& bs) {
272 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
273 std::vector<TreeNodePtr>::iterator i;
274 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
275 bs |= (*i)->bs;
276 }
277 }
278
279 void NameFinder::matchStuntDouble(const std::string& molName,
280 const std::string& sdName,
281 SelectionSet& bs) {
282 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
283 std::vector<TreeNodePtr>::iterator i;
284 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
285 std::vector<TreeNodePtr> sdNodes = getMatchedChildren(*i, sdName);
286 std::vector<TreeNodePtr>::iterator j;
287 for (j = sdNodes.begin(); j != sdNodes.end(); ++j) {
288 bs |= (*j)->bs;
289 }
290 }
291 }
292
293 void NameFinder::matchBond(const std::string& molName,
294 const std::string& bondName, SelectionSet& bs) {
295 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
296 std::vector<TreeNodePtr>::iterator i;
297 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
298 std::vector<TreeNodePtr> bondNodes = getMatchedChildren(*i, bondName);
299 std::vector<TreeNodePtr>::iterator j;
300 for (j = bondNodes.begin(); j != bondNodes.end(); ++j) {
301 bs |= (*j)->bs;
302 std::vector<TreeNodePtr> bondAtomNodes = getAllChildren(*j);
303 std::vector<TreeNodePtr>::iterator k;
304 for (k = bondAtomNodes.begin(); k != bondAtomNodes.end(); ++k) {
305 bs |= (*k)->bs;
306 }
307 }
308 }
309 }
310
311 void NameFinder::matchBend(const std::string& molName,
312 const std::string& bendName, SelectionSet& bs) {
313 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
314 std::vector<TreeNodePtr>::iterator i;
315 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
316 std::vector<TreeNodePtr> bendNodes = getMatchedChildren(*i, bendName);
317 std::vector<TreeNodePtr>::iterator j;
318 for (j = bendNodes.begin(); j != bendNodes.end(); ++j) {
319 std::vector<TreeNodePtr> bendAtomNodes = getAllChildren(*j);
320 std::vector<TreeNodePtr>::iterator k;
321 for (k = bendAtomNodes.begin(); k != bendAtomNodes.end(); ++k) {
322 bs |= (*k)->bs;
323 }
324 }
325 }
326 }
327 void NameFinder::matchTorsion(const std::string& molName,
328 const std::string& torsionName,
329 SelectionSet& bs) {
330 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
331 std::vector<TreeNodePtr>::iterator i;
332 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
333 std::vector<TreeNodePtr> torsionNodes =
334 getMatchedChildren(*i, torsionName);
335 std::vector<TreeNodePtr>::iterator j;
336 for (j = torsionNodes.begin(); j != torsionNodes.end(); ++j) {
337 std::vector<TreeNodePtr> torsionAtomNodes = getAllChildren(*j);
338 std::vector<TreeNodePtr>::iterator k;
339 for (k = torsionAtomNodes.begin(); k != torsionAtomNodes.end(); ++k) {
340 bs |= (*k)->bs;
341 }
342 }
343 }
344 }
345 void NameFinder::matchInversion(const std::string& molName,
346 const std::string& inversionName,
347 SelectionSet& bs) {
348 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
349 std::vector<TreeNodePtr>::iterator i;
350 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
351 std::vector<TreeNodePtr> inversionNodes =
352 getMatchedChildren(*i, inversionName);
353 std::vector<TreeNodePtr>::iterator j;
354 for (j = inversionNodes.begin(); j != inversionNodes.end(); ++j) {
355 std::vector<TreeNodePtr> inversionAtomNodes = getAllChildren(*j);
356 std::vector<TreeNodePtr>::iterator k;
357 for (k = inversionAtomNodes.begin(); k != inversionAtomNodes.end();
358 ++k) {
359 bs |= (*k)->bs;
360 }
361 }
362 }
363 }
364
365 void NameFinder::matchRigidAtoms(const std::string& molName,
366 const std::string& rbName,
367 const std::string& rbAtomName,
368 SelectionSet& bs) {
369 std::vector<TreeNodePtr> molNodes = getMatchedChildren(root_, molName);
370 std::vector<TreeNodePtr>::iterator i;
371 for (i = molNodes.begin(); i != molNodes.end(); ++i) {
372 std::vector<TreeNodePtr> rbNodes = getMatchedChildren(*i, rbName);
373 std::vector<TreeNodePtr>::iterator j;
374 for (j = rbNodes.begin(); j != rbNodes.end(); ++j) {
375 std::vector<TreeNodePtr> rbAtomNodes =
376 getMatchedChildren(*j, rbAtomName);
377 std::vector<TreeNodePtr>::iterator k;
378 for (k = rbAtomNodes.begin(); k != rbAtomNodes.end(); ++k) {
379 bs |= (*k)->bs;
380 }
381 }
382 }
383 }
384
385 std::vector<TreeNodePtr> NameFinder::getAllChildren(TreeNodePtr node) {
386 std::vector<TreeNodePtr> childNodes;
387 std::map<std::string, TreeNodePtr>::iterator i;
388 for (i = node->children.begin(); i != node->children.end(); ++i) {
389 childNodes.push_back(i->second);
390 }
391 return childNodes;
392 }
393
394 std::vector<TreeNodePtr> NameFinder::getMatchedChildren(
395 TreeNodePtr node, const std::string& name) {
396 std::vector<TreeNodePtr> matchedNodes;
397 std::map<std::string, TreeNodePtr>::iterator i;
398 for (i = node->children.begin(); i != node->children.end(); ++i) {
399 if (isMatched(i->first, name)) { matchedNodes.push_back(i->second); }
400 }
401
402 return matchedNodes;
403 }
404
405 bool NameFinder::isMatched(const std::string& str,
406 const std::string& wildcard) {
407 return Wildcard::wildcardfit(wildcard.c_str(), str.c_str()) > 0 ? true :
408 false;
409 }
410
411 void NameFinder::matchInternalIndex(const std::string& name,
412 int internalIndex, SelectionSet& bs) {
413 SimInfo::MoleculeIterator mi;
414 Molecule* mol;
415
416 for (mol = info_->beginMolecule(mi); mol != NULL;
417 mol = info_->nextMolecule(mi)) {
418 if (isMatched(mol->getMoleculeName(), name)) {
419 int natoms = mol->getNAtoms();
420 int nrigidbodies = mol->getNRigidBodies();
421 if (internalIndex >= natoms + nrigidbodies) {
422 continue;
423 } else if (internalIndex < natoms) {
424 bs.bitsets_[STUNTDOUBLE].setBitOn(
425 mol->getAtomAt(internalIndex)->getGlobalIndex());
426 continue;
427 } else if (internalIndex < natoms + nrigidbodies) {
428 bs.bitsets_[STUNTDOUBLE].setBitOn(
429 mol->getRigidBodyAt(internalIndex - natoms)->getGlobalIndex());
430 }
431 }
432 }
433 }
434
435 bool NameFinder::isInteger(const std::string& str) {
436 for (unsigned int i = 0; i < str.size(); ++i) {
437 if (!std::isdigit(str[i])) { return false; }
438 }
439 return true;
440 }
441} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
@ STUNTDOUBLE
StuntDoubles (Atoms & RigidBodies)