OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
SelectionManager.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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include "selection/SelectionManager.hpp"
49
50#ifdef IS_MPI
51#include <mpi.h>
52#endif
53
54#include "brains/SimInfo.hpp"
55
56namespace OpenMD {
57 SelectionManager::SelectionManager(SimInfo* info) : info_(info) {
58 nObjects_.push_back(info_->getNGlobalAtoms() +
59 info_->getNGlobalRigidBodies());
60 nObjects_.push_back(info_->getNGlobalBonds());
61 nObjects_.push_back(info_->getNGlobalBends());
62 nObjects_.push_back(info_->getNGlobalTorsions());
63 nObjects_.push_back(info_->getNGlobalInversions());
64 nObjects_.push_back(info_->getNGlobalMolecules());
65
66 stuntdoubles_.resize(nObjects_[STUNTDOUBLE]);
67 bonds_.resize(nObjects_[BOND]);
68 bends_.resize(nObjects_[BEND]);
69 torsions_.resize(nObjects_[TORSION]);
70 inversions_.resize(nObjects_[INVERSION]);
71 molecules_.resize(nObjects_[MOLECULE]);
72
73 ss_.resize(nObjects_);
74
75 SimInfo::MoleculeIterator mi;
76 Molecule::AtomIterator ai;
77 Molecule::RigidBodyIterator rbIter;
78 Molecule::BondIterator bondIter;
79 Molecule::BendIterator bendIter;
80 Molecule::TorsionIterator torsionIter;
81 Molecule::InversionIterator inversionIter;
82
83 Molecule* mol;
84 Atom* atom;
85 RigidBody* rb;
86 Bond* bond;
87 Bend* bend;
88 Torsion* torsion;
89 Inversion* inversion;
90
91 for (mol = info_->beginMolecule(mi); mol != NULL;
92 mol = info_->nextMolecule(mi)) {
93 molecules_[mol->getGlobalIndex()] = mol;
94
95 for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
96 stuntdoubles_[atom->getGlobalIndex()] = atom;
97 }
98 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
99 rb = mol->nextRigidBody(rbIter)) {
100 stuntdoubles_[rb->getGlobalIndex()] = rb;
101 }
102 for (bond = mol->beginBond(bondIter); bond != NULL;
103 bond = mol->nextBond(bondIter)) {
104 bonds_[bond->getGlobalIndex()] = bond;
105 }
106 for (bend = mol->beginBend(bendIter); bend != NULL;
107 bend = mol->nextBend(bendIter)) {
108 bends_[bend->getGlobalIndex()] = bend;
109 }
110 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
111 torsion = mol->nextTorsion(torsionIter)) {
112 torsions_[torsion->getGlobalIndex()] = torsion;
113 }
114 for (inversion = mol->beginInversion(inversionIter); inversion != NULL;
115 inversion = mol->nextInversion(inversionIter)) {
116 inversions_[inversion->getGlobalIndex()] = inversion;
117 }
118 }
119 }
120
122#ifdef IS_MPI
123 i = 0;
124 while (i < static_cast<int>(ss_.bitsets_[STUNTDOUBLE].size())) {
125 if (ss_.bitsets_[STUNTDOUBLE][i]) {
126 // check that this processor owns this stuntdouble
127 if (stuntdoubles_[i] != NULL) return stuntdoubles_[i];
128 }
129 ++i;
130 }
131 return NULL;
132#else
133 i = ss_.bitsets_[STUNTDOUBLE].firstOnBit();
134 return i == -1 ? NULL : stuntdoubles_[i];
135#endif
136 }
137
139#ifdef IS_MPI
140 ++i;
141 while (i < static_cast<int>(ss_.bitsets_[STUNTDOUBLE].size())) {
142 if (ss_.bitsets_[STUNTDOUBLE][i]) {
143 // check that this processor owns this stuntdouble
144 if (stuntdoubles_[i] != NULL) return stuntdoubles_[i];
145 }
146 ++i;
147 }
148 return NULL;
149#else
150 i = ss_.bitsets_[STUNTDOUBLE].nextOnBit(i);
151 return i == -1 ? NULL : stuntdoubles_[i];
152#endif
153 }
154
156#ifdef IS_MPI
157 i = 0;
158 while (i < static_cast<int>(ss_.bitsets_[STUNTDOUBLE].size())) {
159 if (!ss_.bitsets_[STUNTDOUBLE][i]) {
160 // check that this processor owns this stuntdouble
161 if (stuntdoubles_[i] != NULL) return stuntdoubles_[i];
162 }
163 ++i;
164 }
165 return NULL;
166#else
167 i = ss_.bitsets_[STUNTDOUBLE].firstOffBit();
168 return i == -1 ? NULL : stuntdoubles_[i];
169#endif
170 }
171
173#ifdef IS_MPI
174 ++i;
175 while (i < static_cast<int>(ss_.bitsets_[STUNTDOUBLE].size())) {
176 if (!ss_.bitsets_[STUNTDOUBLE][i]) {
177 // check that this processor owns this stuntdouble
178 if (stuntdoubles_[i] != NULL) return stuntdoubles_[i];
179 }
180 ++i;
181 }
182 return NULL;
183#else
184 i = ss_.bitsets_[STUNTDOUBLE].nextOffBit(i);
185 return i == -1 ? NULL : stuntdoubles_[i];
186#endif
187 }
188
190#ifdef IS_MPI
191 i = 0;
192 while (i < static_cast<int>(ss_.bitsets_[BOND].size())) {
193 if (ss_.bitsets_[BOND][i]) {
194 // check that this processor owns this bond
195 if (bonds_[i] != NULL) return bonds_[i];
196 }
197 ++i;
198 }
199 return NULL;
200#else
201 i = ss_.bitsets_[BOND].firstOnBit();
202 return i == -1 ? NULL : bonds_[i];
203#endif
204 }
205
207#ifdef IS_MPI
208 ++i;
209 while (i < static_cast<int>(ss_.bitsets_[BOND].size())) {
210 if (ss_.bitsets_[BOND][i]) {
211 // check that this processor owns this bond
212 if (bonds_[i] != NULL) return bonds_[i];
213 }
214 ++i;
215 }
216 return NULL;
217#else
218 i = ss_.bitsets_[BOND].nextOnBit(i);
219 return i == -1 ? NULL : bonds_[i];
220#endif
221 }
222
224#ifdef IS_MPI
225 i = 0;
226 while (i < static_cast<int>(ss_.bitsets_[BOND].size())) {
227 if (!ss_.bitsets_[BOND][i]) {
228 // check that this processor owns this bond
229 if (bonds_[i] != NULL) return bonds_[i];
230 }
231 ++i;
232 }
233 return NULL;
234#else
235 i = ss_.bitsets_[BOND].firstOffBit();
236 return i == -1 ? NULL : bonds_[i];
237#endif
238 }
239
241#ifdef IS_MPI
242 ++i;
243 while (i < static_cast<int>(ss_.bitsets_[BOND].size())) {
244 if (!ss_.bitsets_[BOND][i]) {
245 // check that this processor owns this bond
246 if (bonds_[i] != NULL) return bonds_[i];
247 }
248 ++i;
249 }
250 return NULL;
251#else
252 i = ss_.bitsets_[BOND].nextOffBit(i);
253 return i == -1 ? NULL : bonds_[i];
254#endif
255 }
256
258#ifdef IS_MPI
259 i = 0;
260 while (i < static_cast<int>(ss_.bitsets_[BEND].size())) {
261 if (ss_.bitsets_[BEND][i]) {
262 // check that this processor owns this bend
263 if (bends_[i] != NULL) return bends_[i];
264 }
265 ++i;
266 }
267 return NULL;
268#else
269 i = ss_.bitsets_[BEND].firstOnBit();
270 return i == -1 ? NULL : bends_[i];
271#endif
272 }
273
275#ifdef IS_MPI
276 ++i;
277 while (i < static_cast<int>(ss_.bitsets_[BEND].size())) {
278 if (ss_.bitsets_[BEND][i]) {
279 // check that this processor owns this bend
280 if (bends_[i] != NULL) return bends_[i];
281 }
282 ++i;
283 }
284 return NULL;
285#else
286 i = ss_.bitsets_[BEND].nextOnBit(i);
287 return i == -1 ? NULL : bends_[i];
288#endif
289 }
290
292#ifdef IS_MPI
293 i = 0;
294 while (i < static_cast<int>(ss_.bitsets_[BEND].size())) {
295 if (!ss_.bitsets_[BEND][i]) {
296 // check that this processor owns this bend
297 if (bends_[i] != NULL) return bends_[i];
298 }
299 ++i;
300 }
301 return NULL;
302#else
303 i = ss_.bitsets_[BEND].firstOffBit();
304 return i == -1 ? NULL : bends_[i];
305#endif
306 }
307
309#ifdef IS_MPI
310 ++i;
311 while (i < static_cast<int>(ss_.bitsets_[BEND].size())) {
312 if (!ss_.bitsets_[BEND][i]) {
313 // check that this processor owns this bend
314 if (bends_[i] != NULL) return bends_[i];
315 }
316 ++i;
317 }
318 return NULL;
319#else
320 i = ss_.bitsets_[BEND].nextOffBit(i);
321 return i == -1 ? NULL : bends_[i];
322#endif
323 }
324
326#ifdef IS_MPI
327 i = 0;
328 while (i < static_cast<int>(ss_.bitsets_[TORSION].size())) {
329 if (ss_.bitsets_[TORSION][i]) {
330 // check that this processor owns this torsion
331 if (torsions_[i] != NULL) return torsions_[i];
332 }
333 ++i;
334 }
335 return NULL;
336#else
337 i = ss_.bitsets_[TORSION].firstOnBit();
338 return i == -1 ? NULL : torsions_[i];
339#endif
340 }
341
343#ifdef IS_MPI
344 ++i;
345 while (i < static_cast<int>(ss_.bitsets_[TORSION].size())) {
346 if (ss_.bitsets_[TORSION][i]) {
347 // check that this processor owns this torsion
348 if (torsions_[i] != NULL) return torsions_[i];
349 }
350 ++i;
351 }
352 return NULL;
353#else
354 i = ss_.bitsets_[TORSION].nextOnBit(i);
355 return i == -1 ? NULL : torsions_[i];
356#endif
357 }
358
360#ifdef IS_MPI
361 i = 0;
362 while (i < static_cast<int>(ss_.bitsets_[TORSION].size())) {
363 if (!ss_.bitsets_[TORSION][i]) {
364 // check that this processor owns this torsion
365 if (torsions_[i] != NULL) return torsions_[i];
366 }
367 ++i;
368 }
369 return NULL;
370#else
371 i = ss_.bitsets_[TORSION].firstOffBit();
372 return i == -1 ? NULL : torsions_[i];
373#endif
374 }
375
377#ifdef IS_MPI
378 ++i;
379 while (i < static_cast<int>(ss_.bitsets_[TORSION].size())) {
380 if (!ss_.bitsets_[TORSION][i]) {
381 // check that this processor owns this torsion
382 if (torsions_[i] != NULL) return torsions_[i];
383 }
384 ++i;
385 }
386 return NULL;
387#else
388 i = ss_.bitsets_[TORSION].nextOffBit(i);
389 return i == -1 ? NULL : torsions_[i];
390#endif
391 }
392
394#ifdef IS_MPI
395 i = 0;
396 while (i < static_cast<int>(ss_.bitsets_[INVERSION].size())) {
397 if (ss_.bitsets_[INVERSION][i]) {
398 // check that this processor owns this inversion
399 if (inversions_[i] != NULL) return inversions_[i];
400 }
401 ++i;
402 }
403 return NULL;
404#else
405 i = ss_.bitsets_[INVERSION].firstOnBit();
406 return i == -1 ? NULL : inversions_[i];
407#endif
408 }
409
411#ifdef IS_MPI
412 ++i;
413 while (i < static_cast<int>(ss_.bitsets_[INVERSION].size())) {
414 if (ss_.bitsets_[INVERSION][i]) {
415 // check that this processor owns this inversion
416 if (inversions_[i] != NULL) return inversions_[i];
417 }
418 ++i;
419 }
420 return NULL;
421#else
422 i = ss_.bitsets_[INVERSION].nextOnBit(i);
423 return i == -1 ? NULL : inversions_[i];
424#endif
425 }
426
428#ifdef IS_MPI
429 i = 0;
430 while (i < static_cast<int>(ss_.bitsets_[INVERSION].size())) {
431 if (!ss_.bitsets_[INVERSION][i]) {
432 // check that this processor owns this inversion
433 if (inversions_[i] != NULL) return inversions_[i];
434 }
435 ++i;
436 }
437 return NULL;
438#else
439 i = ss_.bitsets_[INVERSION].firstOffBit();
440 return i == -1 ? NULL : inversions_[i];
441#endif
442 }
443
445#ifdef IS_MPI
446 ++i;
447 while (i < static_cast<int>(ss_.bitsets_[INVERSION].size())) {
448 if (!ss_.bitsets_[INVERSION][i]) {
449 // check that this processor owns this inversion
450 if (inversions_[i] != NULL) return inversions_[i];
451 }
452 ++i;
453 }
454 return NULL;
455#else
456 i = ss_.bitsets_[INVERSION].nextOffBit(i);
457 return i == -1 ? NULL : inversions_[i];
458#endif
459 }
460
462#ifdef IS_MPI
463 i = 0;
464 while (i < static_cast<int>(ss_.bitsets_[MOLECULE].size())) {
465 if (ss_.bitsets_[MOLECULE][i]) {
466 // check that this processor owns this molecule
467 if (molecules_[i] != NULL) return molecules_[i];
468 }
469 ++i;
470 }
471 return NULL;
472#else
473 i = ss_.bitsets_[MOLECULE].firstOnBit();
474 return i == -1 ? NULL : molecules_[i];
475#endif
476 }
477
479#ifdef IS_MPI
480 ++i;
481 while (i < static_cast<int>(ss_.bitsets_[MOLECULE].size())) {
482 if (ss_.bitsets_[MOLECULE][i]) {
483 // check that this processor owns this molecule
484 if (molecules_[i] != NULL) return molecules_[i];
485 }
486 ++i;
487 }
488 return NULL;
489#else
490 i = ss_.bitsets_[MOLECULE].nextOnBit(i);
491 return i == -1 ? NULL : molecules_[i];
492#endif
493 }
494
496#ifdef IS_MPI
497 i = 0;
498 while (i < static_cast<int>(ss_.bitsets_[MOLECULE].size())) {
499 if (!ss_.bitsets_[MOLECULE][i]) {
500 // check that this processor owns this molecule
501 if (molecules_[i] != NULL) return molecules_[i];
502 }
503 ++i;
504 }
505 return NULL;
506#else
507 i = ss_.bitsets_[MOLECULE].firstOffBit();
508 return i == -1 ? NULL : molecules_[i];
509#endif
510 }
511
513#ifdef IS_MPI
514 ++i;
515 while (i < static_cast<int>(ss_.bitsets_[MOLECULE].size())) {
516 if (!ss_.bitsets_[MOLECULE][i]) {
517 // check that this processor owns this molecule
518 if (molecules_[i] != NULL) return molecules_[i];
519 }
520 ++i;
521 }
522 return NULL;
523#else
524 i = ss_.bitsets_[MOLECULE].nextOffBit(i);
525 return i == -1 ? NULL : molecules_[i];
526#endif
527 }
528
530 int i;
531#ifdef IS_MPI
532 i = ss_.bitsets_[MOLECULE].nthOnBit(n);
533 if (i == -1) return NULL;
534 // check that this processor owns this molecule
535 if (molecules_[i] != NULL) return molecules_[i];
536 return NULL;
537#else
538 i = ss_.bitsets_[MOLECULE].nthOnBit(n);
539 return i == -1 ? NULL : molecules_[i];
540#endif
541 }
542
543 /**
544 * getSelectedAtomTypes
545 *
546 * Returns an STL set of AtomType* that are actually selected.
547 * Must query all processors to assemble this information.
548 *
549 */
551 AtomTypeSet atomTypes;
552
553 for (size_t i = 0; i < ss_.bitsets_[STUNTDOUBLE].size(); ++i) {
554 if (ss_.bitsets_[STUNTDOUBLE][i]) {
555 // check that this processor owns this stuntdouble
556 if (stuntdoubles_[i] != NULL) {
557 if (stuntdoubles_[i]->isAtom()) {
558 Atom* atom = static_cast<Atom*>(stuntdoubles_[i]);
559 atomTypes.insert(atom->getAtomType());
560 }
561 }
562 }
563 }
564
565#ifdef IS_MPI
566 // loop over the found atom types on this processor, and add their
567 // numerical idents to a vector:
568
569 std::vector<int> foundTypes;
570 AtomTypeSet::iterator i;
571 for (i = atomTypes.begin(); i != atomTypes.end(); ++i)
572 foundTypes.push_back((*i)->getIdent());
573
574 // count_local holds the number of found types on this processor
575 int count_local = foundTypes.size();
576
577 int nproc;
578 MPI_Comm_size(MPI_COMM_WORLD, &nproc);
579
580 // we need arrays to hold the counts and displacement vectors for
581 // all processors
582 std::vector<int> counts(nproc, 0);
583 std::vector<int> disps(nproc, 0);
584
585 // fill the counts array
586 MPI_Allgather(&count_local, 1, MPI_INT, &counts[0], 1, MPI_INT,
587 MPI_COMM_WORLD);
588
589 // use the processor counts to compute the displacement array
590 disps[0] = 0;
591 int totalCount = counts[0];
592 for (int iproc = 1; iproc < nproc; iproc++) {
593 disps[iproc] = disps[iproc - 1] + counts[iproc - 1];
594 totalCount += counts[iproc];
595 }
596
597 if (totalCount > 0) {
598 // we need a (possibly redundant) set of all found types:
599 std::vector<int> ftGlobal(totalCount);
600
601 // now spray out the foundTypes to all the other processors:
602 MPI_Allgatherv(&foundTypes[0], count_local, MPI_INT, &ftGlobal[0],
603 &counts[0], &disps[0], MPI_INT, MPI_COMM_WORLD);
604
605 std::vector<int>::iterator j;
606
607 // foundIdents is a stl set, so inserting an already found ident
608 // will have no effect.
609 std::set<int> foundIdents;
610
611 for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j)
612 foundIdents.insert((*j));
613
614 // now iterate over the foundIdents and get the actual atom types
615 // that correspond to these:
616 ForceField* forceField_ = info_->getForceField();
617 std::set<int>::iterator it;
618 for (it = foundIdents.begin(); it != foundIdents.end(); ++it)
619 atomTypes.insert(forceField_->getAtomType((*it)));
620 }
621#endif
622
623 return atomTypes;
624 }
625
626 MoleculeStampSet SelectionManager::getSelectedMoleculeStamps() {
627 MoleculeStampSet moleculeStamps;
628
629 for (size_t i = 0; i < ss_.bitsets_[MOLECULE].size(); ++i) {
630 if (ss_.bitsets_[MOLECULE][i]) {
631 // check that this processor owns this molecule
632 if (molecules_[i] != NULL) {
633 Molecule* mol = static_cast<Molecule*>(molecules_[i]);
634 moleculeStamps.insert(mol->getMolStamp());
635 }
636 }
637 }
638
639#ifdef IS_MPI
640 std::vector<int> foundStamps;
641 MoleculeStampSet::iterator i;
642 for (i = moleculeStamps.begin(); i != moleculeStamps.end(); ++i)
643 foundStamps.push_back((*i)->getIdent());
644
645 // count_local holds the number of found stamps on this processor
646 int count_local = foundStamps.size();
647
648 int nproc;
649 MPI_Comm_size(MPI_COMM_WORLD, &nproc);
650
651 // we need arrays to hold the counts and displacement vectors for
652 // all processors
653 std::vector<int> counts(nproc, 0);
654 std::vector<int> disps(nproc, 0);
655
656 // fill the counts array
657 MPI_Allgather(&count_local, 1, MPI_INT, &counts[0], 1, MPI_INT,
658 MPI_COMM_WORLD);
659
660 // use the processor counts to compute the displacement array
661 disps[0] = 0;
662 int totalCount = counts[0];
663 for (int iproc = 1; iproc < nproc; iproc++) {
664 disps[iproc] = disps[iproc - 1] + counts[iproc - 1];
665 totalCount += counts[iproc];
666 }
667
668 if (totalCount > 0) {
669 // we need a (possibly redundant) set of all found stamps:
670 std::vector<int> fsGlobal(totalCount);
671
672 // now spray out the foundStamps to all the other processors:
673 MPI_Allgatherv(&foundStamps[0], count_local, MPI_INT, &fsGlobal[0],
674 &counts[0], &disps[0], MPI_INT, MPI_COMM_WORLD);
675
676 std::vector<int>::iterator j;
677
678 for (j = fsGlobal.begin(); j != fsGlobal.end(); ++j)
679 moleculeStamps.insert(info_->getMoleculeStamp(*j));
680 }
681#endif
682
683 return moleculeStamps;
684 }
685
686 SelectionManager SelectionManager::replaceRigidBodiesWithAtoms() const {
687 SelectionSet ssAtoms(nObjects_);
688 ssAtoms.clearAll();
689
690 SelectionSet ssRBs(nObjects_);
691 ssRBs.clearAll();
692
693 SelectionManager tempSeleMan = *this;
694
695 StuntDouble* sd;
696 int isd;
697 std::vector<Atom*>::iterator ai;
698 Atom* atom;
699 for (sd = tempSeleMan.beginSelected(isd); sd != NULL;
700 sd = tempSeleMan.nextSelected(isd)) {
701 if (sd->isRigidBody()) {
702 RigidBody* rb = static_cast<RigidBody*>(sd);
703 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
704 ssAtoms.bitsets_[STUNTDOUBLE].setBitOn(atom->getGlobalIndex());
705 }
706
707 ssRBs.bitsets_[STUNTDOUBLE].setBitOn(rb->getGlobalIndex());
708 }
709 }
710
711 // Add the atoms in rigid bodies and remove those rigid bodies from our
712 // selection set.
713 tempSeleMan.ss_ |= ssAtoms;
714 tempSeleMan.ss_ -= ssRBs;
715
716 return tempSeleMan;
717 }
718
719 SelectionManager SelectionManager::removeAtomsInRigidBodies() const {
720 SelectionSet ssAtoms(nObjects_);
721 ssAtoms.clearAll();
722
723 SelectionManager tempSeleMan = *this;
724
725 StuntDouble* sd;
726 int isd;
727 std::vector<Atom*>::iterator ai;
728 Atom* atom;
729 for (sd = tempSeleMan.beginSelected(isd); sd != NULL;
730 sd = tempSeleMan.nextSelected(isd)) {
731 if (sd->isRigidBody()) {
732 RigidBody* rb = static_cast<RigidBody*>(sd);
733 for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) {
734 ssAtoms.bitsets_[STUNTDOUBLE].setBitOn(atom->getGlobalIndex());
735 }
736 }
737 }
738
739 // Remove the atoms in rigid bodies from our selection set.
740 tempSeleMan.ss_ -= ssAtoms;
741
742 return tempSeleMan;
743 }
744
745 SelectionManager operator|(const SelectionManager& sman1,
746 const SelectionManager& sman2) {
747 SelectionManager result(sman1);
748 result |= sman2;
749 return result;
750 }
751
752 SelectionManager operator&(const SelectionManager& sman1,
753 const SelectionManager& sman2) {
754 SelectionManager result(sman1);
755 result &= sman2;
756 return result;
757 }
758
759 SelectionManager operator^(const SelectionManager& sman1,
760 const SelectionManager& sman2) {
761 SelectionManager result(sman1);
762 result ^= sman2;
763 return result;
764 }
765
766 SelectionManager operator-(const SelectionManager& sman1,
767 const SelectionManager& sman2) {
768 SelectionManager result(sman1);
769 result -= sman2;
770 return result;
771 }
772
773} // namespace OpenMD
AtomType * getAtomType()
Returns the AtomType of this Atom.
Definition Atom.hpp:86
AtomType * getAtomType(const std::string &at)
getAtomType by string
Bend * nextUnselectedBend(int &i)
Finds the next unselected Bend.
Bend * beginUnselectedBend(int &i)
Finds the first unselected Bend.
Bend * nextSelectedBend(int &i)
Finds the next selected Bend in the selection.
Bond * nextUnselectedBond(int &i)
Finds the next unselected Bond.
Torsion * nextUnselectedTorsion(int &i)
Finds the next unselected Torsion.
Molecule * nthSelectedMolecule(int &n)
Finds the n^th selected Molecule in the selection.
Bend * beginSelectedBend(int &i)
Finds the first selected Bend in the selection.
Bond * nextSelectedBond(int &i)
Finds the next selected Bond in the selection.
Bond * beginSelectedBond(int &i)
Finds the first selected Bond in the selection.
AtomTypeSet getSelectedAtomTypes()
getSelectedAtomTypes
Molecule * nextSelectedMolecule(int &i)
Finds the next selected Molecule in the selection.
StuntDouble * nextSelected(int &i)
Finds the next selected StuntDouble in the selection.
StuntDouble * nextUnselected(int &i)
Finds the next unselected StuntDouble.
Inversion * beginUnselectedInversion(int &i)
Finds the first unselected Inversion.
Inversion * beginSelectedInversion(int &i)
Finds the first selected Inversion in the selection.
StuntDouble * beginSelected(int &i)
Finds the first selected StuntDouble in the selection.
Bond * beginUnselectedBond(int &i)
Finds the first unselected Bond.
Molecule * beginSelectedMolecule(int &i)
Finds the first selected Molecule in the selection.
Torsion * beginSelectedTorsion(int &i)
Finds the first selected Torsion in the selection.
Torsion * beginUnselectedTorsion(int &i)
Finds the first unselected Torsion.
Inversion * nextSelectedInversion(int &i)
Finds the next selected Inversion in the selection.
Inversion * nextUnselectedInversion(int &i)
Finds the next unselected Inversion.
Molecule * beginUnselectedMolecule(int &i)
Finds the first unselected Molecule.
Molecule * nextUnselectedMolecule(int &i)
Finds the next unselected Molecule.
StuntDouble * beginUnselected(int &i)
Finds the first unselected StuntDouble.
Torsion * nextSelectedTorsion(int &i)
Finds the next selected Torsion in the selection.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
"Don't move, or you're dead! Stand up! Captain, we've got them!"
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
DynamicRectMatrix< Real > operator-(const DynamicRectMatrix< Real > &m)
Negate the value of every element of this matrix.
@ INVERSION
Inversions.
@ STUNTDOUBLE
StuntDoubles (Atoms & RigidBodies).
@ TORSION
Torsions.
@ BEND
Bends.
@ BOND
Bonds.
@ MOLECULE
Molecules.