47#include "types/MoleculeStamp.hpp"
61 template<
class ContainerType>
62 bool hasDuplicateElement(
const ContainerType& cont) {
63 ContainerType tmp = cont;
64 std::sort(tmp.begin(), tmp.end());
65 tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
66 return tmp.size() != cont.size();
69 MoleculeStamp::MoleculeStamp() : nintegrable_(0), ident_ {-1} {
70 DefineParameter(Name,
"name");
71 DefineOptionalParameter(ConstrainTotalCharge,
"constrainTotalCharge");
73 deprecatedKeywords_.insert(
"nAtoms");
74 deprecatedKeywords_.insert(
"nBonds");
75 deprecatedKeywords_.insert(
"nBends");
76 deprecatedKeywords_.insert(
"nTorsions");
77 deprecatedKeywords_.insert(
"nInversions");
78 deprecatedKeywords_.insert(
"nRigidBodies");
79 deprecatedKeywords_.insert(
"nCutoffGroups");
82 MoleculeStamp::~MoleculeStamp() {
83 Utils::deletePointers(atomStamps_);
84 Utils::deletePointers(bondStamps_);
85 Utils::deletePointers(bendStamps_);
86 Utils::deletePointers(torsionStamps_);
87 Utils::deletePointers(inversionStamps_);
88 Utils::deletePointers(rigidBodyStamps_);
89 Utils::deletePointers(cutoffGroupStamps_);
90 Utils::deletePointers(fragmentStamps_);
91 Utils::deletePointers(constraintStamps_);
94 bool MoleculeStamp::addAtomStamp(AtomStamp* atom) {
95 bool ret = addIndexSensitiveStamp(atomStamps_, atom);
97 std::ostringstream oss;
98 oss <<
"Error in Molecule " << getName()
99 <<
": multiple atoms have the same indices" << atom->getIndex()
101 throw OpenMDException(oss.str());
106 bool MoleculeStamp::addBondStamp(BondStamp* bond) {
107 bondStamps_.push_back(bond);
111 bool MoleculeStamp::addBendStamp(BendStamp* bend) {
112 bendStamps_.push_back(bend);
116 bool MoleculeStamp::addTorsionStamp(TorsionStamp* torsion) {
117 torsionStamps_.push_back(torsion);
121 bool MoleculeStamp::addInversionStamp(InversionStamp* inversion) {
122 inversionStamps_.push_back(inversion);
126 bool MoleculeStamp::addRigidBodyStamp(RigidBodyStamp* rigidbody) {
127 bool ret = addIndexSensitiveStamp(rigidBodyStamps_, rigidbody);
129 std::ostringstream oss;
130 oss <<
"Error in Molecule " << getName()
131 <<
": multiple rigidbodies have the same indices: "
132 << rigidbody->getIndex() <<
"\n";
133 throw OpenMDException(oss.str());
138 bool MoleculeStamp::addCutoffGroupStamp(CutoffGroupStamp* cutoffgroup) {
139 cutoffGroupStamps_.push_back(cutoffgroup);
143 bool MoleculeStamp::addFragmentStamp(FragmentStamp* fragment) {
144 return addIndexSensitiveStamp(fragmentStamps_, fragment);
147 bool MoleculeStamp::addConstraintStamp(ConstraintStamp* constraint) {
148 constraintStamps_.push_back(constraint);
152 void MoleculeStamp::validate() {
153 DataHolder::validate();
155 atom2Rigidbody.resize(getNAtoms());
161 for (
unsigned int i = 0; i < atom2Rigidbody.size(); ++i) {
162 atom2Rigidbody[i] = -1 - int(i);
164 for (std::size_t i = 0; i < getNRigidBodies(); ++i) {
165 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
166 std::vector<int> members = rbStamp->getMembers();
167 for (std::vector<int>::iterator j = members.begin(); j != members.end();
169 atom2Rigidbody[*j] = i;
184 size_t nrigidAtoms = 0;
185 for (std::size_t i = 0; i < getNRigidBodies(); ++i) {
186 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
187 nrigidAtoms += rbStamp->getNMembers();
189 nintegrable_ = getNAtoms() + getNRigidBodies() - nrigidAtoms;
192 void MoleculeStamp::checkAtoms() {
193 std::vector<AtomStamp*>::iterator ai = std::find(
194 atomStamps_.begin(), atomStamps_.end(),
static_cast<AtomStamp*
>(NULL));
195 if (ai != atomStamps_.end()) {
196 std::ostringstream oss;
197 oss <<
"Error in Molecule " << getName() <<
": atom["
198 << ai - atomStamps_.begin() <<
"] is missing\n";
199 throw OpenMDException(oss.str());
203 void MoleculeStamp::checkBonds() {
204 std::ostringstream oss;
206 int natoms =
static_cast<int>(getNAtoms());
207 for (std::size_t i = 0; i < getNBonds(); ++i) {
208 BondStamp* bondStamp = getBondStamp(i);
209 if (bondStamp->getA() > natoms - 1 || bondStamp->getA() < 0 ||
210 bondStamp->getB() > natoms - 1 || bondStamp->getB() < 0 ||
211 bondStamp->getA() == bondStamp->getB()) {
212 oss <<
"Error in Molecule " << getName() <<
": bond("
213 << bondStamp->getA() <<
", " << bondStamp->getB()
215 throw OpenMDException(oss.str());
220 std::set<std::pair<int, int>> allBonds;
221 for (std::size_t i = 0; i < getNBonds(); ++i) {
222 BondStamp* bondStamp = getBondStamp(i);
223 std::pair<int, int> bondPair(bondStamp->getA(), bondStamp->getB());
226 if (bondPair.first > bondPair.second) {
227 std::swap(bondPair.first, bondPair.second);
230 std::set<std::pair<int, int>>::iterator iter = allBonds.find(bondPair);
231 if (iter != allBonds.end()) {
232 oss <<
"Error in Molecule " << getName() <<
": "
233 <<
"bond(" << iter->first <<
", " << iter->second
234 <<
") appears multiple times\n";
235 throw OpenMDException(oss.str());
237 allBonds.insert(bondPair);
242 for (std::size_t i = 0; i < getNBonds(); ++i) {
243 BondStamp* bondStamp = getBondStamp(i);
244 if (atom2Rigidbody[bondStamp->getA()] ==
245 atom2Rigidbody[bondStamp->getB()]) {
246 oss <<
"Error in Molecule " << getName() <<
": "
247 <<
"bond(" << bondStamp->getA() <<
", " << bondStamp->getB()
248 <<
") belong to same rigidbody "
249 << atom2Rigidbody[bondStamp->getA()] <<
"\n";
250 throw OpenMDException(oss.str());
255 void MoleculeStamp::checkBends() {
256 std::ostringstream oss;
257 for (std::size_t i = 0; i < getNBends(); ++i) {
258 BendStamp* bendStamp = getBendStamp(i);
259 std::vector<int> bendAtoms = bendStamp->getMembers();
260 std::vector<int>::iterator j =
261 std::find_if(bendAtoms.begin(), bendAtoms.end(),
262 std::bind(std::greater<int>(), std::placeholders::_1,
264 std::vector<int>::iterator k =
265 std::find_if(bendAtoms.begin(), bendAtoms.end(),
266 std::bind(std::less<int>(), std::placeholders::_1, 0));
268 if (j != bendAtoms.end() || k != bendAtoms.end()) {
269 oss <<
"Error in Molecule " << getName() <<
" : atoms of bend"
270 << containerToString(bendAtoms) <<
" have invalid indices\n";
271 throw OpenMDException(oss.str());
274 if (hasDuplicateElement(bendAtoms)) {
275 oss <<
"Error in Molecule " << getName() <<
" : atoms of bend"
276 << containerToString(bendAtoms) <<
" have duplicated indices\n";
277 throw OpenMDException(oss.str());
280 if (bendAtoms.size() == 2) {
281 if (!bendStamp->haveGhostVectorSource()) {
282 oss <<
"Error in Molecule " << getName()
283 <<
": ghostVectorSouce is missing\n";
284 throw OpenMDException(oss.str());
286 std::size_t ghostIndex = bendStamp->getGhostVectorSource();
287 if (ghostIndex < getNAtoms()) {
288 if (std::find(bendAtoms.begin(), bendAtoms.end(), ghostIndex) ==
290 oss <<
"Error in Molecule " << getName() <<
": ghostVectorSouce "
291 << ghostIndex <<
"is invalid\n";
292 throw OpenMDException(oss.str());
294 if (!getAtomStamp(ghostIndex)->haveOrientation()) {
295 oss <<
"Error in Molecule " << getName()
296 <<
": ghost atom must be a directional atom\n";
297 throw OpenMDException(oss.str());
300 oss <<
"Error in Molecule " << getName() <<
": ghostVectorSource "
301 << ghostIndex <<
" is invalid\n";
302 throw OpenMDException(oss.str());
305 }
else if (bendAtoms.size() == 3 && bendStamp->haveGhostVectorSource()) {
306 oss <<
"Error in Molecule " << getName()
307 <<
": normal bend should not have ghostVectorSouce\n";
308 throw OpenMDException(oss.str());
312 for (std::size_t i = 0; i < getNBends(); ++i) {
313 BendStamp* bendStamp = getBendStamp(i);
314 std::vector<int> bendAtoms = bendStamp->getMembers();
315 std::vector<int> rigidSet(getNRigidBodies(), 0);
316 std::vector<int>::iterator j;
317 for (j = bendAtoms.begin(); j != bendAtoms.end(); ++j) {
318 int rigidbodyIndex = atom2Rigidbody[*j];
319 if (rigidbodyIndex >= 0) {
320 ++rigidSet[rigidbodyIndex];
321 if (rigidSet[rigidbodyIndex] > 2) {
322 oss <<
"Error in Molecule " << getName() <<
": bend"
323 << containerToString(bendAtoms)
324 <<
"has three atoms on the same rigid body\n";
325 throw OpenMDException(oss.str());
331 std::set<std::tuple<int, int, int>> allBends;
332 std::set<std::tuple<int, int, int>>::iterator iter;
334 for (std::size_t i = 0; i < getNBends(); ++i) {
335 BendStamp* bendStamp = getBendStamp(i);
336 std::vector<int> bend = bendStamp->getMembers();
337 if (bend.size() == 2) {
351 int ghostIndex = bendStamp->getGhostVectorSource();
352 std::vector<int>::iterator j =
353 std::find(bend.begin(), bend.end(), ghostIndex);
354 if (j != bend.end()) { bend.insert(j, ghostIndex); }
357 std::tuple<int, int, int> bendTuple {bend[0], bend[1], bend[2]};
358 auto& [first, second, third] = bendTuple;
362 if (first > third) { std::swap(first, third); }
364 iter = allBends.find(bendTuple);
365 if (iter != allBends.end()) {
366 oss <<
"Error in Molecule " << getName() <<
": "
367 <<
"Bend" << containerToString(bend) <<
" appears multiple times\n";
368 throw OpenMDException(oss.str());
370 allBends.insert(bendTuple);
374 for (std::size_t i = 0; i < getNBonds(); ++i) {
375 BondStamp* bondStamp = getBondStamp(i);
376 int a = bondStamp->getA();
377 int b = bondStamp->getB();
379 AtomStamp* atomA = getAtomStamp(a);
380 AtomStamp* atomB = getAtomStamp(b);
383 AtomStamp::AtomIter ai;
384 for (
int c = atomA->getFirstBondedAtom(ai); c != -1;
385 c = atomA->getNextBondedAtom(ai)) {
386 if (b == c)
continue;
388 std::tuple<int, int, int> newBend {c, a, b};
389 auto [first, second, third] = newBend;
390 if (first > third) { std::swap(first, third); }
392 if (allBends.find(newBend) == allBends.end()) {
393 allBends.insert(newBend);
394 BendStamp* newBendStamp =
new BendStamp();
395 newBendStamp->setMembers(newBend);
396 addBendStamp(newBendStamp);
401 for (
int c = atomB->getFirstBondedAtom(ai); c != -1;
402 c = atomB->getNextBondedAtom(ai)) {
403 if (a == c)
continue;
405 std::tuple<int, int, int> newBend {a, b, c};
406 auto [first, second, third] = newBend;
407 if (first > third) { std::swap(first, third); }
409 if (allBends.find(newBend) == allBends.end()) {
410 allBends.insert(newBend);
411 BendStamp* newBendStamp =
new BendStamp();
412 newBendStamp->setMembers(newBend);
413 addBendStamp(newBendStamp);
419 void MoleculeStamp::checkTorsions() {
420 std::ostringstream oss;
421 for (std::size_t i = 0; i < getNTorsions(); ++i) {
422 TorsionStamp* torsionStamp = getTorsionStamp(i);
423 std::vector<int> torsionAtoms = torsionStamp->getMembers();
424 std::vector<int>::iterator j =
425 std::find_if(torsionAtoms.begin(), torsionAtoms.end(),
426 std::bind(std::greater<int>(), std::placeholders::_1,
428 std::vector<int>::iterator k =
429 std::find_if(torsionAtoms.begin(), torsionAtoms.end(),
430 std::bind(std::less<int>(), std::placeholders::_1, 0));
432 if (j != torsionAtoms.end() || k != torsionAtoms.end()) {
433 oss <<
"Error in Molecule " << getName() <<
": atoms of torsion"
434 << containerToString(torsionAtoms) <<
" have invalid indices\n";
435 throw OpenMDException(oss.str());
437 if (hasDuplicateElement(torsionAtoms)) {
438 oss <<
"Error in Molecule " << getName() <<
" : atoms of torsion"
439 << containerToString(torsionAtoms) <<
" have duplicated indices\n";
440 throw OpenMDException(oss.str());
444 for (std::size_t i = 0; i < getNTorsions(); ++i) {
445 TorsionStamp* torsionStamp = getTorsionStamp(i);
446 std::vector<int> torsionAtoms = torsionStamp->getMembers();
447 std::vector<int> rigidSet(getNRigidBodies(), 0);
448 std::vector<int>::iterator j;
449 for (j = torsionAtoms.begin(); j != torsionAtoms.end(); ++j) {
450 int rigidbodyIndex = atom2Rigidbody[*j];
451 if (rigidbodyIndex >= 0) {
452 ++rigidSet[rigidbodyIndex];
453 if (rigidSet[rigidbodyIndex] > 3) {
454 oss <<
"Error in Molecule " << getName() <<
": torsion"
455 << containerToString(torsionAtoms)
456 <<
"has four atoms on the same rigid body\n";
457 throw OpenMDException(oss.str());
463 std::set<std::tuple<int, int, int, int>> allTorsions;
464 std::set<std::tuple<int, int, int, int>>::iterator iter;
466 for (std::size_t i = 0; i < getNTorsions(); ++i) {
467 TorsionStamp* torsionStamp = getTorsionStamp(i);
468 std::vector<int> torsion = torsionStamp->getMembers();
469 if (torsion.size() == 3) {
470 int ghostIndex = torsionStamp->getGhostVectorSource();
471 std::vector<int>::iterator j =
472 std::find(torsion.begin(), torsion.end(), ghostIndex);
473 if (j != torsion.end()) { torsion.insert(j, ghostIndex); }
476 std::tuple<int, int, int, int> torsionTuple {torsion[0], torsion[1],
477 torsion[2], torsion[3]};
478 auto& [first, second, third, fourth] = torsionTuple;
480 if (first > fourth) {
481 std::swap(first, fourth);
482 std::swap(second, third);
485 iter = allTorsions.find(torsionTuple);
486 if (iter == allTorsions.end()) {
487 allTorsions.insert(torsionTuple);
489 oss <<
"Error in Molecule " << getName() <<
": "
490 <<
"Torsion" << containerToString(torsion)
491 <<
" appears multiple times\n";
492 throw OpenMDException(oss.str());
496 for (std::size_t i = 0; i < getNBonds(); ++i) {
497 BondStamp* bondStamp = getBondStamp(i);
498 int b = bondStamp->getA();
499 int c = bondStamp->getB();
501 AtomStamp* atomB = getAtomStamp(b);
502 AtomStamp* atomC = getAtomStamp(c);
504 AtomStamp::AtomIter ai2;
505 AtomStamp::AtomIter ai3;
507 for (
int a = atomB->getFirstBondedAtom(ai2); a != -1;
508 a = atomB->getNextBondedAtom(ai2)) {
509 if (a == c)
continue;
511 for (
int d = atomC->getFirstBondedAtom(ai3); d != -1;
512 d = atomC->getNextBondedAtom(ai3)) {
513 if (d == b)
continue;
515 std::tuple<int, int, int, int> newTorsion {a, b, c, d};
516 auto [first, second, third, fourth] = newTorsion;
520 if (first > fourth) {
521 std::swap(first, fourth);
522 std::swap(second, third);
525 if (allTorsions.find(newTorsion) == allTorsions.end()) {
526 allTorsions.insert(newTorsion);
527 TorsionStamp* newTorsionStamp =
new TorsionStamp();
528 newTorsionStamp->setMembers(newTorsion);
529 addTorsionStamp(newTorsionStamp);
536 void MoleculeStamp::checkInversions() {
537 std::ostringstream oss;
542 for (std::size_t i = 0; i < getNInversions(); ++i) {
543 InversionStamp* inversionStamp = getInversionStamp(i);
544 int center = inversionStamp->getCenter();
545 std::vector<int> satellites;
550 if (inversionStamp->getNSatellites() != 3) {
551 for (std::size_t j = 0; j < getNBonds(); ++j) {
552 BondStamp* bondStamp = getBondStamp(j);
553 int a = bondStamp->getA();
554 int b = bondStamp->getB();
556 if (a == center) { satellites.push_back(b); }
557 if (b == center) { satellites.push_back(a); }
560 if (satellites.size() == 3) {
561 std::sort(satellites.begin(), satellites.end());
562 inversionStamp->setSatellites(satellites);
564 oss <<
"Error in Molecule " << getName() <<
": found wrong number"
565 <<
" of bonds for inversion center " << center;
566 throw OpenMDException(oss.str());
573 for (std::size_t i = 0; i < getNInversions(); ++i) {
574 InversionStamp* inversionStamp = getInversionStamp(i);
576 std::vector<int> inversionAtoms = inversionStamp->getSatellites();
578 inversionAtoms.insert(inversionAtoms.begin(),
579 inversionStamp->getCenter());
581 std::vector<int>::iterator j =
582 std::find_if(inversionAtoms.begin(), inversionAtoms.end(),
583 std::bind(std::greater<int>(), std::placeholders::_1,
585 std::vector<int>::iterator k =
586 std::find_if(inversionAtoms.begin(), inversionAtoms.end(),
587 std::bind(std::less<int>(), std::placeholders::_1, 0));
589 if (j != inversionAtoms.end() || k != inversionAtoms.end()) {
590 oss <<
"Error in Molecule " << getName() <<
": atoms of inversion"
591 << containerToString(inversionAtoms) <<
" have invalid indices\n";
592 throw OpenMDException(oss.str());
595 if (hasDuplicateElement(inversionAtoms)) {
596 oss <<
"Error in Molecule " << getName() <<
" : atoms of inversion"
597 << containerToString(inversionAtoms)
598 <<
" have duplicated indices\n";
599 throw OpenMDException(oss.str());
603 for (std::size_t i = 0; i < getNInversions(); ++i) {
604 InversionStamp* inversionStamp = getInversionStamp(i);
605 std::vector<int> inversionAtoms = inversionStamp->getSatellites();
606 inversionAtoms.push_back(inversionStamp->getCenter());
607 std::vector<int> rigidSet(getNRigidBodies(), 0);
608 std::vector<int>::iterator j;
609 for (j = inversionAtoms.begin(); j != inversionAtoms.end(); ++j) {
610 int rigidbodyIndex = atom2Rigidbody[*j];
611 if (rigidbodyIndex >= 0) {
612 ++rigidSet[rigidbodyIndex];
613 if (rigidSet[rigidbodyIndex] > 3) {
614 oss <<
"Error in Molecule " << getName()
615 <<
": inversion centered on atom "
616 << inversionStamp->getCenter()
617 <<
" has four atoms that belong to same rigidbody "
618 << rigidbodyIndex <<
"\n";
619 throw OpenMDException(oss.str());
625 std::set<std::tuple<int, int, int, int>> allInversions;
626 std::set<std::tuple<int, int, int, int>>::iterator iter;
627 for (std::size_t i = 0; i < getNInversions(); ++i) {
628 InversionStamp* inversionStamp = getInversionStamp(i);
629 int cent = inversionStamp->getCenter();
630 std::vector<int> inversion = inversionStamp->getSatellites();
632 std::tuple<int, int, int, int> inversionTuple {
633 cent, inversion[0], inversion[1], inversion[2]};
634 auto& [first, second, third, fourth] = inversionTuple;
641 if (third > fourth) std::swap(third, fourth);
642 if (second > third) std::swap(second, third);
643 if (third > fourth) std::swap(third, fourth);
645 iter = allInversions.find(inversionTuple);
646 if (iter == allInversions.end()) {
647 allInversions.insert(inversionTuple);
649 oss <<
"Error in Molecule " << getName() <<
": "
650 <<
"Inversion" << containerToString(inversion)
651 <<
" appears multiple times\n";
652 throw OpenMDException(oss.str());
661 for (std::size_t i = 0; i < getNAtoms(); ++i) {
662 AtomStamp* ai = getAtomStamp(i);
663 if (ai->getCoordination() == 3) {
664 AtomStamp::AtomIter ai2;
665 std::vector<int> satellites;
666 for (
int a = ai->getFirstBondedAtom(ai2); a != -1;
667 a = ai->getNextBondedAtom(ai2)) {
668 satellites.push_back(a);
670 if (satellites.size() == 3) {
671 int cent = ai->getIndex();
672 std::sort(satellites.begin(), satellites.end());
674 std::tuple<int, int, int, int> newInversion {
675 cent, satellites[0], satellites[1], satellites[2]};
676 auto [first, second, third, fourth] = newInversion;
678 if (third > fourth) std::swap(third, fourth);
679 if (second > third) std::swap(second, third);
680 if (third > fourth) std::swap(third, fourth);
682 if (allInversions.find(newInversion) == allInversions.end()) {
683 allInversions.insert(newInversion);
684 InversionStamp* newInversionStamp =
new InversionStamp();
685 newInversionStamp->setCenter(cent);
686 newInversionStamp->setSatellites(satellites);
687 addInversionStamp(newInversionStamp);
691 oss <<
"Error in Molecule " << getName() <<
": found bond mismatch"
692 <<
" when detecting inversion centers.";
693 throw OpenMDException(oss.str());
699 void MoleculeStamp::checkRigidBodies() {
700 std::ostringstream oss;
701 std::vector<RigidBodyStamp*>::iterator ri =
702 std::find(rigidBodyStamps_.begin(), rigidBodyStamps_.end(),
703 static_cast<RigidBodyStamp*
>(NULL));
704 if (ri != rigidBodyStamps_.end()) {
705 oss <<
"Error in Molecule " << getName() <<
":rigidBody["
706 << ri - rigidBodyStamps_.begin() <<
"] is missing\n";
707 throw OpenMDException(oss.str());
710 for (std::size_t i = 0; i < getNRigidBodies(); ++i) {
711 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
712 std::vector<int> rigidAtoms = rbStamp->getMembers();
713 std::vector<int>::iterator j =
714 std::find_if(rigidAtoms.begin(), rigidAtoms.end(),
715 std::bind(std::greater<int>(), std::placeholders::_1,
717 if (j != rigidAtoms.end()) {
718 oss <<
"Error in Molecule " << getName();
719 throw OpenMDException(oss.str());
724 void MoleculeStamp::checkCutoffGroups() {
725 std::vector<AtomStamp*>::iterator ai;
726 std::vector<int>::iterator fai;
729 for (ai = atomStamps_.begin(); ai != atomStamps_.end(); ++ai) {
730 freeAtoms_.push_back((*ai)->getIndex());
733 for (std::size_t i = 0; i < getNCutoffGroups(); ++i) {
734 CutoffGroupStamp* cutoffGroupStamp = getCutoffGroupStamp(i);
735 std::vector<int> cutoffGroupAtoms = cutoffGroupStamp->getMembers();
736 std::vector<int>::iterator j =
737 std::find_if(cutoffGroupAtoms.begin(), cutoffGroupAtoms.end(),
738 std::bind(std::greater<int>(), std::placeholders::_1,
740 if (j != cutoffGroupAtoms.end()) {
741 std::ostringstream oss;
742 oss <<
"Error in Molecule " << getName() <<
": cutoffGroup"
743 <<
" is out of range\n";
744 throw OpenMDException(oss.str());
747 for (fai = cutoffGroupAtoms.begin(); fai != cutoffGroupAtoms.end();
751 std::remove(freeAtoms_.begin(), freeAtoms_.end(), (*fai)),
757 void MoleculeStamp::checkFragments() {
758 std::vector<FragmentStamp*>::iterator fi =
759 std::find(fragmentStamps_.begin(), fragmentStamps_.end(),
760 static_cast<FragmentStamp*
>(NULL));
761 if (fi != fragmentStamps_.end()) {
762 std::ostringstream oss;
763 oss <<
"Error in Molecule " << getName() <<
":fragment["
764 << fi - fragmentStamps_.begin() <<
"] is missing\n";
765 throw OpenMDException(oss.str());
769 void MoleculeStamp::checkConstraints() {
770 std::ostringstream oss;
772 int natoms = getNAtoms();
773 for (std::size_t i = 0; i < getNConstraints(); ++i) {
774 ConstraintStamp* constraintStamp = getConstraintStamp(i);
775 if (constraintStamp->getA() > natoms - 1 || constraintStamp->getA() < 0 ||
776 constraintStamp->getB() > natoms - 1 || constraintStamp->getB() < 0 ||
777 constraintStamp->getA() == constraintStamp->getB()) {
778 oss <<
"Error in Molecule " << getName() <<
": constraint("
779 << constraintStamp->getA() <<
", " << constraintStamp->getB()
781 throw OpenMDException(oss.str());
786 std::set<std::pair<int, int>> allConstraints;
787 for (std::size_t i = 0; i < getNConstraints(); ++i) {
788 ConstraintStamp* constraintStamp = getConstraintStamp(i);
789 std::pair<int, int> constraintPair(constraintStamp->getA(),
790 constraintStamp->getB());
793 if (constraintPair.first > constraintPair.second) {
794 std::swap(constraintPair.first, constraintPair.second);
797 std::set<std::pair<int, int>>::iterator iter =
798 allConstraints.find(constraintPair);
799 if (iter != allConstraints.end()) {
800 oss <<
"Error in Molecule " << getName() <<
": "
801 <<
"constraint(" << iter->first <<
", " << iter->second
802 <<
") appears multiple times\n";
803 throw OpenMDException(oss.str());
805 allConstraints.insert(constraintPair);
811 for (std::size_t i = 0; i < getNConstraints(); ++i) {
812 ConstraintStamp* constraintStamp = getConstraintStamp(i);
813 if (atom2Rigidbody[constraintStamp->getA()] ==
814 atom2Rigidbody[constraintStamp->getB()]) {
815 oss <<
"Error in Molecule " << getName() <<
": "
816 <<
"constraint(" << constraintStamp->getA() <<
", "
817 << constraintStamp->getB() <<
") belong to same rigidbody "
818 << atom2Rigidbody[constraintStamp->getA()] <<
"\n";
819 throw OpenMDException(oss.str());
824 void MoleculeStamp::fillBondInfo() {
825 for (std::size_t i = 0; i < getNBonds(); ++i) {
826 BondStamp* bondStamp = getBondStamp(i);
827 int a = bondStamp->getA();
828 int b = bondStamp->getB();
829 AtomStamp* atomA = getAtomStamp(a);
830 AtomStamp* atomB = getAtomStamp(b);
832 atomA->addBondedAtom(b);
834 atomB->addBondedAtom(a);
841 bool MoleculeStamp::isBondInSameRigidBody(BondStamp* bond) {
847 if (!isAtomInRigidBody(bond->getA(), rbA, consAtomA))
return false;
849 if (!isAtomInRigidBody(bond->getB(), rbB, consAtomB))
return false;
860 bool MoleculeStamp::isAtomInRigidBody(
int atomIndex) {
861 return atom2Rigidbody[atomIndex] >= 0;
871 bool MoleculeStamp::isAtomInRigidBody(
int atomIndex,
int& whichRigidBody,
872 int& consAtomIndex) {
876 if (atom2Rigidbody[atomIndex] >= 0) {
877 whichRigidBody = atom2Rigidbody[atomIndex];
878 RigidBodyStamp* rbStamp = getRigidBodyStamp(whichRigidBody);
879 int numAtom = rbStamp->getNMembers();
880 for (
int j = 0; j < numAtom; j++) {
881 if (rbStamp->getMemberAt(j) == atomIndex) {
896 std::vector<std::pair<int, int>> MoleculeStamp::getJointAtoms(
int rb1,
898 RigidBodyStamp* rbStamp1;
899 RigidBodyStamp* rbStamp2;
904 std::vector<std::pair<int, int>> jointAtomIndexPair;
906 rbStamp1 = this->getRigidBodyStamp(rb1);
907 natomInRb1 = rbStamp1->getNMembers();
909 rbStamp2 = this->getRigidBodyStamp(rb2);
910 natomInRb2 = rbStamp2->getNMembers();
912 for (
int i = 0; i < natomInRb1; i++) {
913 atomIndex1 = rbStamp1->getMemberAt(i);
915 for (
int j = 0; j < natomInRb2; j++) {
916 atomIndex2 = rbStamp2->getMemberAt(j);
918 if (atomIndex1 == atomIndex2) {
919 jointAtomIndexPair.push_back(std::make_pair(i, j));
925 return jointAtomIndexPair;
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.