44#include "types/MoleculeStamp.hpp"
58 template<
class ContainerType>
59 bool hasDuplicateElement(
const ContainerType& cont) {
60 ContainerType tmp = cont;
61 std::sort(tmp.begin(), tmp.end());
62 tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
63 return tmp.size() != cont.size();
66 MoleculeStamp::MoleculeStamp() : nintegrable_(0) {
67 DefineParameter(Name,
"name");
68 DefineOptionalParameter(ConstrainTotalCharge,
"constrainTotalCharge");
70 deprecatedKeywords_.insert(
"nAtoms");
71 deprecatedKeywords_.insert(
"nBonds");
72 deprecatedKeywords_.insert(
"nBends");
73 deprecatedKeywords_.insert(
"nTorsions");
74 deprecatedKeywords_.insert(
"nInversions");
75 deprecatedKeywords_.insert(
"nRigidBodies");
76 deprecatedKeywords_.insert(
"nCutoffGroups");
79 MoleculeStamp::~MoleculeStamp() {
80 Utils::deletePointers(atomStamps_);
81 Utils::deletePointers(bondStamps_);
82 Utils::deletePointers(bendStamps_);
83 Utils::deletePointers(torsionStamps_);
84 Utils::deletePointers(inversionStamps_);
85 Utils::deletePointers(rigidBodyStamps_);
86 Utils::deletePointers(cutoffGroupStamps_);
87 Utils::deletePointers(fragmentStamps_);
88 Utils::deletePointers(constraintStamps_);
91 bool MoleculeStamp::addAtomStamp(AtomStamp* atom) {
92 bool ret = addIndexSensitiveStamp(atomStamps_, atom);
94 std::ostringstream oss;
95 oss <<
"Error in Molecule " << getName()
96 <<
": multiple atoms have the same indices" << atom->getIndex()
98 throw OpenMDException(oss.str());
103 bool MoleculeStamp::addBondStamp(BondStamp* bond) {
104 bondStamps_.push_back(bond);
108 bool MoleculeStamp::addBendStamp(BendStamp* bend) {
109 bendStamps_.push_back(bend);
113 bool MoleculeStamp::addTorsionStamp(TorsionStamp* torsion) {
114 torsionStamps_.push_back(torsion);
118 bool MoleculeStamp::addInversionStamp(InversionStamp* inversion) {
119 inversionStamps_.push_back(inversion);
123 bool MoleculeStamp::addRigidBodyStamp(RigidBodyStamp* rigidbody) {
124 bool ret = addIndexSensitiveStamp(rigidBodyStamps_, rigidbody);
126 std::ostringstream oss;
127 oss <<
"Error in Molecule " << getName()
128 <<
": multiple rigidbodies have the same indices: "
129 << rigidbody->getIndex() <<
"\n";
130 throw OpenMDException(oss.str());
135 bool MoleculeStamp::addCutoffGroupStamp(CutoffGroupStamp* cutoffgroup) {
136 cutoffGroupStamps_.push_back(cutoffgroup);
140 bool MoleculeStamp::addFragmentStamp(FragmentStamp* fragment) {
141 return addIndexSensitiveStamp(fragmentStamps_, fragment);
144 bool MoleculeStamp::addConstraintStamp(ConstraintStamp* constraint) {
145 constraintStamps_.push_back(constraint);
149 void MoleculeStamp::validate() {
150 DataHolder::validate();
152 atom2Rigidbody.resize(getNAtoms());
158 for (
unsigned int i = 0; i < atom2Rigidbody.size(); ++i) {
159 atom2Rigidbody[i] = -1 - int(i);
161 for (std::size_t i = 0; i < getNRigidBodies(); ++i) {
162 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
163 std::vector<int> members = rbStamp->getMembers();
164 for (std::vector<int>::iterator j = members.begin(); j != members.end();
166 atom2Rigidbody[*j] = i;
181 size_t nrigidAtoms = 0;
182 for (std::size_t i = 0; i < getNRigidBodies(); ++i) {
183 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
184 nrigidAtoms += rbStamp->getNMembers();
186 nintegrable_ = getNAtoms() + getNRigidBodies() - nrigidAtoms;
189 void MoleculeStamp::checkAtoms() {
190 std::vector<AtomStamp*>::iterator ai = std::find(
191 atomStamps_.begin(), atomStamps_.end(),
static_cast<AtomStamp*
>(NULL));
192 if (ai != atomStamps_.end()) {
193 std::ostringstream oss;
194 oss <<
"Error in Molecule " << getName() <<
": atom["
195 << ai - atomStamps_.begin() <<
"] is missing\n";
196 throw OpenMDException(oss.str());
200 void MoleculeStamp::checkBonds() {
201 std::ostringstream oss;
203 int natoms =
static_cast<int>(getNAtoms());
204 for (std::size_t i = 0; i < getNBonds(); ++i) {
205 BondStamp* bondStamp = getBondStamp(i);
206 if (bondStamp->getA() > natoms - 1 || bondStamp->getA() < 0 ||
207 bondStamp->getB() > natoms - 1 || bondStamp->getB() < 0 ||
208 bondStamp->getA() == bondStamp->getB()) {
209 oss <<
"Error in Molecule " << getName() <<
": bond("
210 << bondStamp->getA() <<
", " << bondStamp->getB()
212 throw OpenMDException(oss.str());
217 std::set<std::pair<int, int>> allBonds;
218 for (std::size_t i = 0; i < getNBonds(); ++i) {
219 BondStamp* bondStamp = getBondStamp(i);
220 std::pair<int, int> bondPair(bondStamp->getA(), bondStamp->getB());
223 if (bondPair.first > bondPair.second) {
224 std::swap(bondPair.first, bondPair.second);
227 std::set<std::pair<int, int>>::iterator iter = allBonds.find(bondPair);
228 if (iter != allBonds.end()) {
229 oss <<
"Error in Molecule " << getName() <<
": "
230 <<
"bond(" << iter->first <<
", " << iter->second
231 <<
") appears multiple times\n";
232 throw OpenMDException(oss.str());
234 allBonds.insert(bondPair);
239 for (std::size_t i = 0; i < getNBonds(); ++i) {
240 BondStamp* bondStamp = getBondStamp(i);
241 if (atom2Rigidbody[bondStamp->getA()] ==
242 atom2Rigidbody[bondStamp->getB()]) {
243 oss <<
"Error in Molecule " << getName() <<
": "
244 <<
"bond(" << bondStamp->getA() <<
", " << bondStamp->getB()
245 <<
") belong to same rigidbody "
246 << atom2Rigidbody[bondStamp->getA()] <<
"\n";
247 throw OpenMDException(oss.str());
252 void MoleculeStamp::checkBends() {
253 std::ostringstream oss;
254 for (std::size_t i = 0; i < getNBends(); ++i) {
255 BendStamp* bendStamp = getBendStamp(i);
256 std::vector<int> bendAtoms = bendStamp->getMembers();
257 std::vector<int>::iterator j =
258 std::find_if(bendAtoms.begin(), bendAtoms.end(),
259 std::bind(std::greater<int>(), std::placeholders::_1,
261 std::vector<int>::iterator k =
262 std::find_if(bendAtoms.begin(), bendAtoms.end(),
263 std::bind(std::less<int>(), std::placeholders::_1, 0));
265 if (j != bendAtoms.end() || k != bendAtoms.end()) {
266 oss <<
"Error in Molecule " << getName() <<
" : atoms of bend"
267 << containerToString(bendAtoms) <<
" have invalid indices\n";
268 throw OpenMDException(oss.str());
271 if (hasDuplicateElement(bendAtoms)) {
272 oss <<
"Error in Molecule " << getName() <<
" : atoms of bend"
273 << containerToString(bendAtoms) <<
" have duplicated indices\n";
274 throw OpenMDException(oss.str());
277 if (bendAtoms.size() == 2) {
278 if (!bendStamp->haveGhostVectorSource()) {
279 oss <<
"Error in Molecule " << getName()
280 <<
": ghostVectorSouce is missing\n";
281 throw OpenMDException(oss.str());
283 std::size_t ghostIndex = bendStamp->getGhostVectorSource();
284 if (ghostIndex < getNAtoms()) {
285 if (std::find(bendAtoms.begin(), bendAtoms.end(), ghostIndex) ==
287 oss <<
"Error in Molecule " << getName() <<
": ghostVectorSouce "
288 << ghostIndex <<
"is invalid\n";
289 throw OpenMDException(oss.str());
291 if (!getAtomStamp(ghostIndex)->haveOrientation()) {
292 oss <<
"Error in Molecule " << getName()
293 <<
": ghost atom must be a directional atom\n";
294 throw OpenMDException(oss.str());
297 oss <<
"Error in Molecule " << getName() <<
": ghostVectorSource "
298 << ghostIndex <<
" is invalid\n";
299 throw OpenMDException(oss.str());
302 }
else if (bendAtoms.size() == 3 && bendStamp->haveGhostVectorSource()) {
303 oss <<
"Error in Molecule " << getName()
304 <<
": normal bend should not have ghostVectorSouce\n";
305 throw OpenMDException(oss.str());
309 for (std::size_t i = 0; i < getNBends(); ++i) {
310 BendStamp* bendStamp = getBendStamp(i);
311 std::vector<int> bendAtoms = bendStamp->getMembers();
312 std::vector<int> rigidSet(getNRigidBodies(), 0);
313 std::vector<int>::iterator j;
314 for (j = bendAtoms.begin(); j != bendAtoms.end(); ++j) {
315 int rigidbodyIndex = atom2Rigidbody[*j];
316 if (rigidbodyIndex >= 0) {
317 ++rigidSet[rigidbodyIndex];
318 if (rigidSet[rigidbodyIndex] > 2) {
319 oss <<
"Error in Molecule " << getName() <<
": bend"
320 << containerToString(bendAtoms)
321 <<
"has three atoms on the same rigid body\n";
322 throw OpenMDException(oss.str());
328 std::set<std::tuple<int, int, int>> allBends;
329 std::set<std::tuple<int, int, int>>::iterator iter;
331 for (std::size_t i = 0; i < getNBends(); ++i) {
332 BendStamp* bendStamp = getBendStamp(i);
333 std::vector<int> bend = bendStamp->getMembers();
334 if (bend.size() == 2) {
348 int ghostIndex = bendStamp->getGhostVectorSource();
349 std::vector<int>::iterator j =
350 std::find(bend.begin(), bend.end(), ghostIndex);
351 if (j != bend.end()) { bend.insert(j, ghostIndex); }
354 std::tuple<int, int, int> bendTuple {bend[0], bend[1], bend[2]};
355 auto& [first, second, third] = bendTuple;
359 if (first > third) { std::swap(first, third); }
361 iter = allBends.find(bendTuple);
362 if (iter != allBends.end()) {
363 oss <<
"Error in Molecule " << getName() <<
": "
364 <<
"Bend" << containerToString(bend) <<
" appears multiple times\n";
365 throw OpenMDException(oss.str());
367 allBends.insert(bendTuple);
371 for (std::size_t i = 0; i < getNBonds(); ++i) {
372 BondStamp* bondStamp = getBondStamp(i);
373 int a = bondStamp->getA();
374 int b = bondStamp->getB();
376 AtomStamp* atomA = getAtomStamp(a);
377 AtomStamp* atomB = getAtomStamp(b);
380 AtomStamp::AtomIter ai;
381 for (
int c = atomA->getFirstBondedAtom(ai); c != -1;
382 c = atomA->getNextBondedAtom(ai)) {
383 if (b == c)
continue;
385 std::tuple<int, int, int> newBend {c, a, b};
386 auto [first, second, third] = newBend;
387 if (first > third) { std::swap(first, third); }
389 if (allBends.find(newBend) == allBends.end()) {
390 allBends.insert(newBend);
391 BendStamp* newBendStamp =
new BendStamp();
392 newBendStamp->setMembers(newBend);
393 addBendStamp(newBendStamp);
398 for (
int c = atomB->getFirstBondedAtom(ai); c != -1;
399 c = atomB->getNextBondedAtom(ai)) {
400 if (a == c)
continue;
402 std::tuple<int, int, int> newBend {a, b, c};
403 auto [first, second, third] = newBend;
404 if (first > third) { std::swap(first, third); }
406 if (allBends.find(newBend) == allBends.end()) {
407 allBends.insert(newBend);
408 BendStamp* newBendStamp =
new BendStamp();
409 newBendStamp->setMembers(newBend);
410 addBendStamp(newBendStamp);
416 void MoleculeStamp::checkTorsions() {
417 std::ostringstream oss;
418 for (std::size_t i = 0; i < getNTorsions(); ++i) {
419 TorsionStamp* torsionStamp = getTorsionStamp(i);
420 std::vector<int> torsionAtoms = torsionStamp->getMembers();
421 std::vector<int>::iterator j =
422 std::find_if(torsionAtoms.begin(), torsionAtoms.end(),
423 std::bind(std::greater<int>(), std::placeholders::_1,
425 std::vector<int>::iterator k =
426 std::find_if(torsionAtoms.begin(), torsionAtoms.end(),
427 std::bind(std::less<int>(), std::placeholders::_1, 0));
429 if (j != torsionAtoms.end() || k != torsionAtoms.end()) {
430 oss <<
"Error in Molecule " << getName() <<
": atoms of torsion"
431 << containerToString(torsionAtoms) <<
" have invalid indices\n";
432 throw OpenMDException(oss.str());
434 if (hasDuplicateElement(torsionAtoms)) {
435 oss <<
"Error in Molecule " << getName() <<
" : atoms of torsion"
436 << containerToString(torsionAtoms) <<
" have duplicated indices\n";
437 throw OpenMDException(oss.str());
441 for (std::size_t i = 0; i < getNTorsions(); ++i) {
442 TorsionStamp* torsionStamp = getTorsionStamp(i);
443 std::vector<int> torsionAtoms = torsionStamp->getMembers();
444 std::vector<int> rigidSet(getNRigidBodies(), 0);
445 std::vector<int>::iterator j;
446 for (j = torsionAtoms.begin(); j != torsionAtoms.end(); ++j) {
447 int rigidbodyIndex = atom2Rigidbody[*j];
448 if (rigidbodyIndex >= 0) {
449 ++rigidSet[rigidbodyIndex];
450 if (rigidSet[rigidbodyIndex] > 3) {
451 oss <<
"Error in Molecule " << getName() <<
": torsion"
452 << containerToString(torsionAtoms)
453 <<
"has four atoms on the same rigid body\n";
454 throw OpenMDException(oss.str());
460 std::set<std::tuple<int, int, int, int>> allTorsions;
461 std::set<std::tuple<int, int, int, int>>::iterator iter;
463 for (std::size_t i = 0; i < getNTorsions(); ++i) {
464 TorsionStamp* torsionStamp = getTorsionStamp(i);
465 std::vector<int> torsion = torsionStamp->getMembers();
466 if (torsion.size() == 3) {
467 int ghostIndex = torsionStamp->getGhostVectorSource();
468 std::vector<int>::iterator j =
469 std::find(torsion.begin(), torsion.end(), ghostIndex);
470 if (j != torsion.end()) { torsion.insert(j, ghostIndex); }
473 std::tuple<int, int, int, int> torsionTuple {torsion[0], torsion[1],
474 torsion[2], torsion[3]};
475 auto& [first, second, third, fourth] = torsionTuple;
477 if (first > fourth) {
478 std::swap(first, fourth);
479 std::swap(second, third);
482 iter = allTorsions.find(torsionTuple);
483 if (iter == allTorsions.end()) {
484 allTorsions.insert(torsionTuple);
486 oss <<
"Error in Molecule " << getName() <<
": "
487 <<
"Torsion" << containerToString(torsion)
488 <<
" appears multiple times\n";
489 throw OpenMDException(oss.str());
493 for (std::size_t i = 0; i < getNBonds(); ++i) {
494 BondStamp* bondStamp = getBondStamp(i);
495 int b = bondStamp->getA();
496 int c = bondStamp->getB();
498 AtomStamp* atomB = getAtomStamp(b);
499 AtomStamp* atomC = getAtomStamp(c);
501 AtomStamp::AtomIter ai2;
502 AtomStamp::AtomIter ai3;
504 for (
int a = atomB->getFirstBondedAtom(ai2); a != -1;
505 a = atomB->getNextBondedAtom(ai2)) {
506 if (a == c)
continue;
508 for (
int d = atomC->getFirstBondedAtom(ai3); d != -1;
509 d = atomC->getNextBondedAtom(ai3)) {
510 if (d == b)
continue;
512 std::tuple<int, int, int, int> newTorsion {a, b, c, d};
513 auto [first, second, third, fourth] = newTorsion;
517 if (first > fourth) {
518 std::swap(first, fourth);
519 std::swap(second, third);
522 if (allTorsions.find(newTorsion) == allTorsions.end()) {
523 allTorsions.insert(newTorsion);
524 TorsionStamp* newTorsionStamp =
new TorsionStamp();
525 newTorsionStamp->setMembers(newTorsion);
526 addTorsionStamp(newTorsionStamp);
533 void MoleculeStamp::checkInversions() {
534 std::ostringstream oss;
539 for (std::size_t i = 0; i < getNInversions(); ++i) {
540 InversionStamp* inversionStamp = getInversionStamp(i);
541 int center = inversionStamp->getCenter();
542 std::vector<int> satellites;
547 if (inversionStamp->getNSatellites() != 3) {
548 for (std::size_t j = 0; j < getNBonds(); ++j) {
549 BondStamp* bondStamp = getBondStamp(j);
550 int a = bondStamp->getA();
551 int b = bondStamp->getB();
553 if (a == center) { satellites.push_back(b); }
554 if (b == center) { satellites.push_back(a); }
557 if (satellites.size() == 3) {
558 std::sort(satellites.begin(), satellites.end());
559 inversionStamp->setSatellites(satellites);
561 oss <<
"Error in Molecule " << getName() <<
": found wrong number"
562 <<
" of bonds for inversion center " << center;
563 throw OpenMDException(oss.str());
570 for (std::size_t i = 0; i < getNInversions(); ++i) {
571 InversionStamp* inversionStamp = getInversionStamp(i);
573 std::vector<int> inversionAtoms = inversionStamp->getSatellites();
575 inversionAtoms.insert(inversionAtoms.begin(),
576 inversionStamp->getCenter());
578 std::vector<int>::iterator j =
579 std::find_if(inversionAtoms.begin(), inversionAtoms.end(),
580 std::bind(std::greater<int>(), std::placeholders::_1,
582 std::vector<int>::iterator k =
583 std::find_if(inversionAtoms.begin(), inversionAtoms.end(),
584 std::bind(std::less<int>(), std::placeholders::_1, 0));
586 if (j != inversionAtoms.end() || k != inversionAtoms.end()) {
587 oss <<
"Error in Molecule " << getName() <<
": atoms of inversion"
588 << containerToString(inversionAtoms) <<
" have invalid indices\n";
589 throw OpenMDException(oss.str());
592 if (hasDuplicateElement(inversionAtoms)) {
593 oss <<
"Error in Molecule " << getName() <<
" : atoms of inversion"
594 << containerToString(inversionAtoms)
595 <<
" have duplicated indices\n";
596 throw OpenMDException(oss.str());
600 for (std::size_t i = 0; i < getNInversions(); ++i) {
601 InversionStamp* inversionStamp = getInversionStamp(i);
602 std::vector<int> inversionAtoms = inversionStamp->getSatellites();
603 inversionAtoms.push_back(inversionStamp->getCenter());
604 std::vector<int> rigidSet(getNRigidBodies(), 0);
605 std::vector<int>::iterator j;
606 for (j = inversionAtoms.begin(); j != inversionAtoms.end(); ++j) {
607 int rigidbodyIndex = atom2Rigidbody[*j];
608 if (rigidbodyIndex >= 0) {
609 ++rigidSet[rigidbodyIndex];
610 if (rigidSet[rigidbodyIndex] > 3) {
611 oss <<
"Error in Molecule " << getName()
612 <<
": inversion centered on atom "
613 << inversionStamp->getCenter()
614 <<
" has four atoms that belong to same rigidbody "
615 << rigidbodyIndex <<
"\n";
616 throw OpenMDException(oss.str());
622 std::set<std::tuple<int, int, int, int>> allInversions;
623 std::set<std::tuple<int, int, int, int>>::iterator iter;
624 for (std::size_t i = 0; i < getNInversions(); ++i) {
625 InversionStamp* inversionStamp = getInversionStamp(i);
626 int cent = inversionStamp->getCenter();
627 std::vector<int> inversion = inversionStamp->getSatellites();
629 std::tuple<int, int, int, int> inversionTuple {
630 cent, inversion[0], inversion[1], inversion[2]};
631 auto& [first, second, third, fourth] = inversionTuple;
638 if (third > fourth) std::swap(third, fourth);
639 if (second > third) std::swap(second, third);
640 if (third > fourth) std::swap(third, fourth);
642 iter = allInversions.find(inversionTuple);
643 if (iter == allInversions.end()) {
644 allInversions.insert(inversionTuple);
646 oss <<
"Error in Molecule " << getName() <<
": "
647 <<
"Inversion" << containerToString(inversion)
648 <<
" appears multiple times\n";
649 throw OpenMDException(oss.str());
658 for (std::size_t i = 0; i < getNAtoms(); ++i) {
659 AtomStamp* ai = getAtomStamp(i);
660 if (ai->getCoordination() == 3) {
661 AtomStamp::AtomIter ai2;
662 std::vector<int> satellites;
663 for (
int a = ai->getFirstBondedAtom(ai2); a != -1;
664 a = ai->getNextBondedAtom(ai2)) {
665 satellites.push_back(a);
667 if (satellites.size() == 3) {
668 int cent = ai->getIndex();
669 std::sort(satellites.begin(), satellites.end());
671 std::tuple<int, int, int, int> newInversion {
672 cent, satellites[0], satellites[1], satellites[2]};
673 auto [first, second, third, fourth] = newInversion;
675 if (third > fourth) std::swap(third, fourth);
676 if (second > third) std::swap(second, third);
677 if (third > fourth) std::swap(third, fourth);
679 if (allInversions.find(newInversion) == allInversions.end()) {
680 allInversions.insert(newInversion);
681 InversionStamp* newInversionStamp =
new InversionStamp();
682 newInversionStamp->setCenter(cent);
683 newInversionStamp->setSatellites(satellites);
684 addInversionStamp(newInversionStamp);
688 oss <<
"Error in Molecule " << getName() <<
": found bond mismatch"
689 <<
" when detecting inversion centers.";
690 throw OpenMDException(oss.str());
696 void MoleculeStamp::checkRigidBodies() {
697 std::ostringstream oss;
698 std::vector<RigidBodyStamp*>::iterator ri =
699 std::find(rigidBodyStamps_.begin(), rigidBodyStamps_.end(),
700 static_cast<RigidBodyStamp*
>(NULL));
701 if (ri != rigidBodyStamps_.end()) {
702 oss <<
"Error in Molecule " << getName() <<
":rigidBody["
703 << ri - rigidBodyStamps_.begin() <<
"] is missing\n";
704 throw OpenMDException(oss.str());
707 for (std::size_t i = 0; i < getNRigidBodies(); ++i) {
708 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
709 std::vector<int> rigidAtoms = rbStamp->getMembers();
710 std::vector<int>::iterator j =
711 std::find_if(rigidAtoms.begin(), rigidAtoms.end(),
712 std::bind(std::greater<int>(), std::placeholders::_1,
714 if (j != rigidAtoms.end()) {
715 oss <<
"Error in Molecule " << getName();
716 throw OpenMDException(oss.str());
721 void MoleculeStamp::checkCutoffGroups() {
722 std::vector<AtomStamp*>::iterator ai;
723 std::vector<int>::iterator fai;
726 for (ai = atomStamps_.begin(); ai != atomStamps_.end(); ++ai) {
727 freeAtoms_.push_back((*ai)->getIndex());
730 for (std::size_t i = 0; i < getNCutoffGroups(); ++i) {
731 CutoffGroupStamp* cutoffGroupStamp = getCutoffGroupStamp(i);
732 std::vector<int> cutoffGroupAtoms = cutoffGroupStamp->getMembers();
733 std::vector<int>::iterator j =
734 std::find_if(cutoffGroupAtoms.begin(), cutoffGroupAtoms.end(),
735 std::bind(std::greater<int>(), std::placeholders::_1,
737 if (j != cutoffGroupAtoms.end()) {
738 std::ostringstream oss;
739 oss <<
"Error in Molecule " << getName() <<
": cutoffGroup"
740 <<
" is out of range\n";
741 throw OpenMDException(oss.str());
744 for (fai = cutoffGroupAtoms.begin(); fai != cutoffGroupAtoms.end();
748 std::remove(freeAtoms_.begin(), freeAtoms_.end(), (*fai)),
754 void MoleculeStamp::checkFragments() {
755 std::vector<FragmentStamp*>::iterator fi =
756 std::find(fragmentStamps_.begin(), fragmentStamps_.end(),
757 static_cast<FragmentStamp*
>(NULL));
758 if (fi != fragmentStamps_.end()) {
759 std::ostringstream oss;
760 oss <<
"Error in Molecule " << getName() <<
":fragment["
761 << fi - fragmentStamps_.begin() <<
"] is missing\n";
762 throw OpenMDException(oss.str());
766 void MoleculeStamp::checkConstraints() {
767 std::ostringstream oss;
769 int natoms = getNAtoms();
770 for (std::size_t i = 0; i < getNConstraints(); ++i) {
771 ConstraintStamp* constraintStamp = getConstraintStamp(i);
772 if (constraintStamp->getA() > natoms - 1 || constraintStamp->getA() < 0 ||
773 constraintStamp->getB() > natoms - 1 || constraintStamp->getB() < 0 ||
774 constraintStamp->getA() == constraintStamp->getB()) {
775 oss <<
"Error in Molecule " << getName() <<
": constraint("
776 << constraintStamp->getA() <<
", " << constraintStamp->getB()
778 throw OpenMDException(oss.str());
783 std::set<std::pair<int, int>> allConstraints;
784 for (std::size_t i = 0; i < getNConstraints(); ++i) {
785 ConstraintStamp* constraintStamp = getConstraintStamp(i);
786 std::pair<int, int> constraintPair(constraintStamp->getA(),
787 constraintStamp->getB());
790 if (constraintPair.first > constraintPair.second) {
791 std::swap(constraintPair.first, constraintPair.second);
794 std::set<std::pair<int, int>>::iterator iter =
795 allConstraints.find(constraintPair);
796 if (iter != allConstraints.end()) {
797 oss <<
"Error in Molecule " << getName() <<
": "
798 <<
"constraint(" << iter->first <<
", " << iter->second
799 <<
") appears multiple times\n";
800 throw OpenMDException(oss.str());
802 allConstraints.insert(constraintPair);
808 for (std::size_t i = 0; i < getNConstraints(); ++i) {
809 ConstraintStamp* constraintStamp = getConstraintStamp(i);
810 if (atom2Rigidbody[constraintStamp->getA()] ==
811 atom2Rigidbody[constraintStamp->getB()]) {
812 oss <<
"Error in Molecule " << getName() <<
": "
813 <<
"constraint(" << constraintStamp->getA() <<
", "
814 << constraintStamp->getB() <<
") belong to same rigidbody "
815 << atom2Rigidbody[constraintStamp->getA()] <<
"\n";
816 throw OpenMDException(oss.str());
821 void MoleculeStamp::fillBondInfo() {
822 for (std::size_t i = 0; i < getNBonds(); ++i) {
823 BondStamp* bondStamp = getBondStamp(i);
824 int a = bondStamp->getA();
825 int b = bondStamp->getB();
826 AtomStamp* atomA = getAtomStamp(a);
827 AtomStamp* atomB = getAtomStamp(b);
829 atomA->addBondedAtom(b);
831 atomB->addBondedAtom(a);
838 bool MoleculeStamp::isBondInSameRigidBody(BondStamp* bond) {
844 if (!isAtomInRigidBody(bond->getA(), rbA, consAtomA))
return false;
846 if (!isAtomInRigidBody(bond->getB(), rbB, consAtomB))
return false;
857 bool MoleculeStamp::isAtomInRigidBody(
int atomIndex) {
858 return atom2Rigidbody[atomIndex] >= 0;
868 bool MoleculeStamp::isAtomInRigidBody(
int atomIndex,
int& whichRigidBody,
869 int& consAtomIndex) {
873 if (atom2Rigidbody[atomIndex] >= 0) {
874 whichRigidBody = atom2Rigidbody[atomIndex];
875 RigidBodyStamp* rbStamp = getRigidBodyStamp(whichRigidBody);
876 int numAtom = rbStamp->getNMembers();
877 for (
int j = 0; j < numAtom; j++) {
878 if (rbStamp->getMemberAt(j) == atomIndex) {
893 std::vector<std::pair<int, int>> MoleculeStamp::getJointAtoms(
int rb1,
895 RigidBodyStamp* rbStamp1;
896 RigidBodyStamp* rbStamp2;
901 std::vector<std::pair<int, int>> jointAtomIndexPair;
903 rbStamp1 = this->getRigidBodyStamp(rb1);
904 natomInRb1 = rbStamp1->getNMembers();
906 rbStamp2 = this->getRigidBodyStamp(rb2);
907 natomInRb2 = rbStamp2->getNMembers();
909 for (
int i = 0; i < natomInRb1; i++) {
910 atomIndex1 = rbStamp1->getMemberAt(i);
912 for (
int j = 0; j < natomInRb2; j++) {
913 atomIndex2 = rbStamp2->getMemberAt(j);
915 if (atomIndex1 == atomIndex2) {
916 jointAtomIndexPair.push_back(std::make_pair(i, j));
922 return jointAtomIndexPair;
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.