ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/types/MoleculeStamp.cpp
Revision: 3173
Committed: Fri Jul 13 18:10:52 2007 UTC (17 years, 2 months ago) by gezelter
File size: 25447 byte(s)
Log Message:
Just some formatting fixes

File Contents

# User Rev Content
1 gezelter 2204 /*
2 gezelter 1930 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9     * 1. Acknowledgement of the program authors must be made in any
10     * publication of scientific results based in part on use of the
11     * program. An acceptable form of acknowledgement is citation of
12     * the article in which the program was described (Matthew
13     * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14     * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15     * Parallel Simulation Engine for Molecular Dynamics,"
16     * J. Comput. Chem. 26, pp. 252-271 (2005))
17     *
18     * 2. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 3. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in the
23     * documentation and/or other materials provided with the
24     * distribution.
25     *
26     * This software is provided "AS IS," without a warranty of any
27     * kind. All express or implied conditions, representations and
28     * warranties, including any implied warranty of merchantability,
29     * fitness for a particular purpose or non-infringement, are hereby
30     * excluded. The University of Notre Dame and its licensors shall not
31     * be liable for any damages suffered by licensee as a result of
32     * using, modifying or distributing the software or its
33     * derivatives. In no event will the University of Notre Dame or its
34     * licensors be liable for any lost revenue, profit or data, or for
35     * direct, indirect, special, consequential, incidental or punitive
36     * damages, however caused and regardless of the theory of liability,
37     * arising out of the use of or inability to use software, even if the
38     * University of Notre Dame has been advised of the possibility of
39     * such damages.
40     */
41 tim 2544 #include <algorithm>
42 tim 2485 #include <functional>
43 gezelter 1490 #include <iostream>
44 tim 2485 #include <sstream>
45 tim 1492 #include "types/MoleculeStamp.hpp"
46 tim 2483 #include "utils/Tuple.hpp"
47 tim 2515 #include "utils/MemoryUtils.hpp"
48 tim 2469 namespace oopse {
49 gezelter 3173
50     template<class ContainerType>
51     bool hasDuplicateElement(const ContainerType& cont) {
52 tim 2544 ContainerType tmp = cont;
53     std::sort(tmp.begin(), tmp.end());
54     tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
55     return tmp.size() != cont.size();
56 gezelter 3173 }
57    
58     MoleculeStamp::MoleculeStamp() {
59 tim 2469 DefineParameter(Name, "name");
60    
61     deprecatedKeywords_.insert("nAtoms");
62     deprecatedKeywords_.insert("nBonds");
63     deprecatedKeywords_.insert("nBends");
64     deprecatedKeywords_.insert("nTorsions");
65     deprecatedKeywords_.insert("nRigidBodies");
66     deprecatedKeywords_.insert("nCutoffGroups");
67    
68 gezelter 3173 }
69    
70     MoleculeStamp::~MoleculeStamp() {
71 tim 2515 MemoryUtils::deletePointers(atomStamps_);
72     MemoryUtils::deletePointers(bondStamps_);
73     MemoryUtils::deletePointers(bendStamps_);
74     MemoryUtils::deletePointers(torsionStamps_);
75     MemoryUtils::deletePointers(rigidBodyStamps_);
76     MemoryUtils::deletePointers(cutoffGroupStamps_);
77     MemoryUtils::deletePointers(fragmentStamps_);
78 gezelter 3173 }
79    
80     bool MoleculeStamp::addAtomStamp( AtomStamp* atom) {
81 tim 2469 bool ret = addIndexSensitiveStamp(atomStamps_, atom);
82     if (!ret) {
83 gezelter 3173 std::ostringstream oss;
84     oss<< "Error in Molecule " << getName() <<
85     ": multiple atoms have the same indices"<< atom->getIndex() <<"\n";
86     throw OOPSEException(oss.str());
87 tim 2469 }
88     return ret;
89    
90 gezelter 3173 }
91    
92     bool MoleculeStamp::addBondStamp( BondStamp* bond) {
93 tim 2469 bondStamps_.push_back(bond);
94     return true;
95 gezelter 3173 }
96    
97     bool MoleculeStamp::addBendStamp( BendStamp* bend) {
98 tim 2469 bendStamps_.push_back(bend);
99     return true;
100 gezelter 3173 }
101    
102     bool MoleculeStamp::addTorsionStamp( TorsionStamp* torsion) {
103 tim 2469 torsionStamps_.push_back(torsion);
104     return true;
105 gezelter 3173 }
106    
107     bool MoleculeStamp::addRigidBodyStamp( RigidBodyStamp* rigidbody) {
108 tim 2469 bool ret = addIndexSensitiveStamp(rigidBodyStamps_, rigidbody);
109     if (!ret) {
110 gezelter 3173 std::ostringstream oss;
111     oss << "Error in Molecule " << getName() <<
112     ": multiple rigidbodies have the same indices: " <<
113     rigidbody->getIndex() <<"\n";
114     throw OOPSEException(oss.str());
115 tim 2469 }
116     return ret;
117 gezelter 3173 }
118    
119     bool MoleculeStamp::addCutoffGroupStamp( CutoffGroupStamp* cutoffgroup) {
120 tim 2469 cutoffGroupStamps_.push_back(cutoffgroup);
121     return true;
122 gezelter 3173 }
123    
124     bool MoleculeStamp::addFragmentStamp( FragmentStamp* fragment) {
125 tim 2469 return addIndexSensitiveStamp(fragmentStamps_, fragment);
126 gezelter 3173 }
127    
128     void MoleculeStamp::validate() {
129     DataHolder::validate();
130 gezelter 1490
131 gezelter 3173 atom2Rigidbody.resize(getNAtoms());
132 gezelter 1490
133 gezelter 3173 // A negative number means the atom is a free atom, and does not
134     // belong to rigidbody. Every element in atom2Rigidbody has unique
135     // negative number at the very beginning
136    
137 tim 2483 for(int i = 0; i < atom2Rigidbody.size(); ++i) {
138 gezelter 3173 atom2Rigidbody[i] = -1 - i;
139 tim 2483 }
140     for (int i = 0; i < getNRigidBodies(); ++i) {
141 gezelter 3173 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
142     std::vector<int> members = rbStamp->getMembers();
143     for(std::vector<int>::iterator j = members.begin();
144     j != members.end(); ++j) {
145     atom2Rigidbody[*j] = i;
146     }
147 tim 2483 }
148 gezelter 3173
149 tim 2483 checkAtoms();
150     checkBonds();
151     fillBondInfo();
152     checkBends();
153     checkTorsions();
154     checkRigidBodies();
155     checkCutoffGroups();
156     checkFragments();
157 gezelter 3173
158 tim 2483 int nrigidAtoms = 0;
159     for (int i = 0; i < getNRigidBodies(); ++i) {
160 gezelter 3173 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
161     nrigidAtoms += rbStamp->getNMembers();
162 tim 2483 }
163     nintegrable_ = getNAtoms()+ getNRigidBodies() - nrigidAtoms;
164 gezelter 3173
165     }
166    
167     void MoleculeStamp::checkAtoms() {
168     std::vector<AtomStamp*>::iterator ai = std::find(atomStamps_.begin(),
169     atomStamps_.end(),
170     static_cast<AtomStamp*>(NULL));
171 tim 2469 if (ai != atomStamps_.end()) {
172 gezelter 3173 std::ostringstream oss;
173     oss << "Error in Molecule " << getName() << ": atom[" <<
174     ai - atomStamps_.begin()<< "] is missing\n";
175     throw OOPSEException(oss.str());
176 gezelter 1490 }
177 gezelter 3173
178     }
179 gezelter 1490
180 gezelter 3173 void MoleculeStamp::checkBonds() {
181 tim 2544 std::ostringstream oss;
182 tim 2469 //make sure index is not out of range
183     int natoms = getNAtoms();
184     for(int i = 0; i < getNBonds(); ++i) {
185 gezelter 3173 BondStamp* bondStamp = getBondStamp(i);
186     if (bondStamp->getA() > natoms-1 || bondStamp->getA() < 0 ||
187     bondStamp->getB() > natoms-1 || bondStamp->getB() < 0 ||
188     bondStamp->getA() == bondStamp->getB()) {
189    
190     oss << "Error in Molecule " << getName() << ": bond(" <<
191     bondStamp->getA() << ", " << bondStamp->getB() << ") is invalid\n";
192     throw OOPSEException(oss.str());
193     }
194 gezelter 1490 }
195 tim 2485
196 tim 2483 //make sure bonds are unique
197     std::set<std::pair<int, int> > allBonds;
198     for(int i = 0; i < getNBonds(); ++i) {
199 gezelter 3173 BondStamp* bondStamp= getBondStamp(i);
200     std::pair<int, int> bondPair(bondStamp->getA(), bondStamp->getB());
201     //make sure bondTuple.first is always less than or equal to
202     //bondTuple.third
203     if (bondPair.first > bondPair.second) {
204     std::swap(bondPair.first, bondPair.second);
205     }
206    
207     std::set<std::pair<int, int> >::iterator iter = allBonds.find(bondPair);
208     if ( iter != allBonds.end()) {
209 tim 2483
210 gezelter 3173 oss << "Error in Molecule " << getName() << ": " << "bond(" <<
211     iter->first << ", "<< iter->second << ") appears multiple times\n";
212     throw OOPSEException(oss.str());
213     } else {
214     allBonds.insert(bondPair);
215     }
216 tim 2483 }
217    
218     //make sure atoms belong to same rigidbody do not bond to each other
219     for(int i = 0; i < getNBonds(); ++i) {
220 gezelter 3173 BondStamp* bondStamp = getBondStamp(i);
221     if (atom2Rigidbody[bondStamp->getA()] == atom2Rigidbody[bondStamp->getB()]) {
222    
223     oss << "Error in Molecule " << getName() << ": "<<"bond(" <<
224     bondStamp->getA() << ", " << bondStamp->getB() <<
225     ") belong to same rigidbody " <<
226     atom2Rigidbody[bondStamp->getA()] << "\n";
227     throw OOPSEException(oss.str());
228     }
229     }
230     }
231    
232     void MoleculeStamp::checkBends() {
233 tim 2544 std::ostringstream oss;
234 tim 2469 for(int i = 0; i < getNBends(); ++i) {
235 gezelter 3173 BendStamp* bendStamp = getBendStamp(i);
236     std::vector<int> bendAtoms = bendStamp->getMembers();
237     std::vector<int>::iterator j =std::find_if(bendAtoms.begin(),
238     bendAtoms.end(),
239     std::bind2nd(std::greater<int>(),
240     getNAtoms()-1));
241     std::vector<int>::iterator k =std::find_if(bendAtoms.begin(),
242     bendAtoms.end(),
243     std::bind2nd(std::less<int>(),
244     0));
245    
246     if (j != bendAtoms.end() || k != bendAtoms.end()) {
247 tim 2544
248 gezelter 3173 oss << "Error in Molecule " << getName() << " : atoms of bend" <<
249     containerToString(bendAtoms) << " have invalid indices\n";
250     throw OOPSEException(oss.str());
251     }
252    
253     if (hasDuplicateElement(bendAtoms)) {
254     oss << "Error in Molecule " << getName() << " : atoms of bend" <<
255     containerToString(bendAtoms) << " have duplicated indices\n";
256     throw OOPSEException(oss.str());
257     }
258    
259     if (bendAtoms.size() == 2 ) {
260     if (!bendStamp->haveGhostVectorSource()) {
261    
262     oss << "Error in Molecule " << getName() <<
263     ": ghostVectorSouce is missing\n";
264     throw OOPSEException(oss.str());
265     }else{
266     int ghostIndex = bendStamp->getGhostVectorSource();
267     if (ghostIndex < getNAtoms()) {
268     if (std::find(bendAtoms.begin(), bendAtoms.end(),
269     ghostIndex) == bendAtoms.end()) {
270    
271     oss << "Error in Molecule " << getName() <<
272     ": ghostVectorSouce "<< ghostIndex<<"is invalid\n";
273     throw OOPSEException(oss.str());
274 tim 2483 }
275 gezelter 3173 if (!getAtomStamp(ghostIndex)->haveOrientation()) {
276    
277     oss << "Error in Molecule " << getName() <<
278     ": ghost atom must be a directioanl atom\n";
279     throw OOPSEException(oss.str());
280     }
281     } else {
282     oss << "Error in Molecule " << getName() <<
283     ": ghostVectorSource " << ghostIndex<< " is invalid\n";
284 tim 2544 throw OOPSEException(oss.str());
285 gezelter 3173 }
286 tim 2469 }
287 gezelter 3173 } else if (bendAtoms.size() == 3 && bendStamp->haveGhostVectorSource()) {
288     oss << "Error in Molecule " << getName() <<
289     ": normal bend should not have ghostVectorSouce\n";
290     throw OOPSEException(oss.str());
291     }
292 gezelter 1490 }
293 gezelter 3173
294 tim 2469 for(int i = 0; i < getNBends(); ++i) {
295 gezelter 3173 BendStamp* bendStamp = getBendStamp(i);
296     std::vector<int> bendAtoms = bendStamp->getMembers();
297     std::vector<int> rigidSet(getNRigidBodies(), 0);
298     std::vector<int>::iterator j;
299     for( j = bendAtoms.begin(); j != bendAtoms.end(); ++j) {
300     int rigidbodyIndex = atom2Rigidbody[*j];
301     if (rigidbodyIndex >= 0) {
302     ++rigidSet[rigidbodyIndex];
303     if (rigidSet[rigidbodyIndex] > 1) {
304     oss << "Error in Molecule " << getName() << ": bend" <<
305     containerToString(bendAtoms) << " belong to same rigidbody " <<
306     rigidbodyIndex << "\n";
307     throw OOPSEException(oss.str());
308     }
309 tim 2469 }
310 gezelter 3173 }
311 tim 2483 }
312    
313    
314 tim 2507 std::set<IntTuple3> allBends;
315     std::set<IntTuple3>::iterator iter;
316 tim 2483 for(int i = 0; i < getNBends(); ++i) {
317 gezelter 3173 BendStamp* bendStamp= getBendStamp(i);
318     std::vector<int> bend = bendStamp->getMembers();
319     if (bend.size() == 2) {
320 tim 2483 // in case we have two ghost bend. For example,
321     // bend {
322     // members (0, 1);
323     // ghostVectorSource = 0;
324     // }
325     // and
326     // bend {
327     // members (0, 1);
328     // ghostVectorSource = 0;
329     // }
330     // In order to distinguish them. we expand them to Tuple3.
331 gezelter 3173 // the first one is expanded to (0, 0, 1) while the second one
332     // is expaned to (0, 1, 1)
333     int ghostIndex = bendStamp->getGhostVectorSource();
334     std::vector<int>::iterator j = std::find(bend.begin(), bend.end(),
335     ghostIndex);
336     if (j != bend.end()) {
337     bend.insert(j, ghostIndex);
338 tim 2483 }
339 gezelter 3173 }
340    
341     IntTuple3 bendTuple(bend[0], bend[1], bend[2]);
342    
343     // make sure bendTuple.first is always less than or equal to
344     // bendTuple.third
345     if (bendTuple.first > bendTuple.third) {
346     std::swap(bendTuple.first, bendTuple.third);
347     }
348    
349     iter = allBends.find(bendTuple);
350     if ( iter != allBends.end()) {
351     oss << "Error in Molecule " << getName() << ": " << "Bend" <<
352     containerToString(bend)<< " appears multiple times\n";
353     throw OOPSEException(oss.str());
354     } else {
355     allBends.insert(bendTuple);
356     }
357     }
358    
359     for (int i = 0; i < getNBonds(); ++i) {
360     BondStamp* bondStamp = getBondStamp(i);
361     int a = bondStamp->getA();
362     int b = bondStamp->getB();
363    
364     AtomStamp* atomA = getAtomStamp(a);
365     AtomStamp* atomB = getAtomStamp(b);
366    
367     //find bend c--a--b
368     AtomStamp::AtomIter ai;
369     for(int c= atomA->getFirstBondedAtom(ai);c != -1;
370     c = atomA->getNextBondedAtom(ai)) {
371     if(b == c)
372     continue;
373 tim 2483
374 gezelter 3173 IntTuple3 newBend(c, a, b);
375     if (newBend.first > newBend.third) {
376     std::swap(newBend.first, newBend.third);
377 tim 2483 }
378    
379 gezelter 3173 if (allBends.find(newBend) == allBends.end() ) {
380     allBends.insert(newBend);
381     BendStamp * newBendStamp = new BendStamp();
382     newBendStamp->setMembers(newBend);
383     addBendStamp(newBendStamp);
384 tim 2483 }
385 gezelter 3173 }
386    
387     //find bend a--b--c
388     for(int c= atomB->getFirstBondedAtom(ai);c != -1;
389     c = atomB->getNextBondedAtom(ai)) {
390     if(a == c)
391     continue;
392    
393     IntTuple3 newBend( a, b, c);
394     if (newBend.first > newBend.third) {
395     std::swap(newBend.first, newBend.third);
396     }
397     if (allBends.find(newBend) == allBends.end() ) {
398     allBends.insert(newBend);
399     BendStamp * newBendStamp = new BendStamp();
400     newBendStamp->setMembers(newBend);
401     addBendStamp(newBendStamp);
402     }
403     }
404     }
405     }
406    
407     void MoleculeStamp::checkTorsions() {
408 tim 2544 std::ostringstream oss;
409 tim 2493 for(int i = 0; i < getNTorsions(); ++i) {
410 gezelter 3173 TorsionStamp* torsionStamp = getTorsionStamp(i);
411     std::vector<int> torsionAtoms = torsionStamp ->getMembers();
412     std::vector<int>::iterator j =std::find_if(torsionAtoms.begin(),
413     torsionAtoms.end(),
414     std::bind2nd(std::greater<int>(),
415     getNAtoms()-1));
416     std::vector<int>::iterator k =std::find_if(torsionAtoms.begin(),
417     torsionAtoms.end(),
418     std::bind2nd(std::less<int>(), 0));
419    
420     if (j != torsionAtoms.end() || k != torsionAtoms.end()) {
421     oss << "Error in Molecule " << getName() << ": atoms of torsion" <<
422     containerToString(torsionAtoms) << " have invalid indices\n";
423     throw OOPSEException(oss.str());
424     }
425     if (hasDuplicateElement(torsionAtoms)) {
426     oss << "Error in Molecule " << getName() << " : atoms of torsion" <<
427     containerToString(torsionAtoms) << " have duplicated indices\n";
428     throw OOPSEException(oss.str());
429     }
430 tim 2485 }
431    
432 tim 2469 for(int i = 0; i < getNTorsions(); ++i) {
433 gezelter 3173 TorsionStamp* torsionStamp = getTorsionStamp(i);
434     std::vector<int> torsionAtoms = torsionStamp->getMembers();
435     std::vector<int> rigidSet(getNRigidBodies(), 0);
436     std::vector<int>::iterator j;
437     for( j = torsionAtoms.begin(); j != torsionAtoms.end(); ++j) {
438     int rigidbodyIndex = atom2Rigidbody[*j];
439     if (rigidbodyIndex >= 0) {
440     ++rigidSet[rigidbodyIndex];
441     if (rigidSet[rigidbodyIndex] > 1) {
442     oss << "Error in Molecule " << getName() << ": torsion" <<
443     containerToString(torsionAtoms) << "is invalid\n";
444     throw OOPSEException(oss.str());
445     }
446 tim 2469 }
447 gezelter 3173 }
448 tim 2483 }
449 gezelter 3173
450 tim 2507 std::set<IntTuple4> allTorsions;
451     std::set<IntTuple4>::iterator iter;
452 gezelter 3173 for(int i = 0; i < getNTorsions(); ++i) {
453     TorsionStamp* torsionStamp= getTorsionStamp(i);
454     std::vector<int> torsion = torsionStamp->getMembers();
455     if (torsion.size() == 3) {
456     int ghostIndex = torsionStamp->getGhostVectorSource();
457     std::vector<int>::iterator j = std::find(torsion.begin(),
458     torsion.end(), ghostIndex);
459     if (j != torsion.end()) {
460     torsion.insert(j, ghostIndex);
461     }
462     }
463    
464     IntTuple4 torsionTuple(torsion[0], torsion[1], torsion[2], torsion[3]);
465     if (torsionTuple.first > torsionTuple.fourth) {
466     std::swap(torsionTuple.first, torsionTuple.fourth);
467     std::swap(torsionTuple.second, torsionTuple.third);
468     }
469    
470     iter = allTorsions.find(torsionTuple);
471     if ( iter == allTorsions.end()) {
472     allTorsions.insert(torsionTuple);
473     } else {
474     oss << "Error in Molecule " << getName() << ": " << "Torsion" <<
475     containerToString(torsion)<< " appears multiple times\n";
476     throw OOPSEException(oss.str());
477     }
478     }
479    
480 tim 2483 for (int i = 0; i < getNBonds(); ++i) {
481 gezelter 3173 BondStamp* bondStamp = getBondStamp(i);
482     int b = bondStamp->getA();
483     int c = bondStamp->getB();
484    
485     AtomStamp* atomB = getAtomStamp(b);
486     AtomStamp* atomC = getAtomStamp(c);
487    
488     AtomStamp::AtomIter ai2;
489     AtomStamp::AtomIter ai3;
490    
491     for(int a = atomB->getFirstBondedAtom(ai2);a != -1;
492     a = atomB->getNextBondedAtom(ai2)) {
493     if(a == c)
494     continue;
495    
496     for(int d = atomC->getFirstBondedAtom(ai3);d != -1;
497     d = atomC->getNextBondedAtom(ai3)) {
498     if(d == b)
499     continue;
500    
501     IntTuple4 newTorsion(a, b, c, d);
502     //make sure the first element is always less than or equal
503     //to the fourth element in IntTuple4
504     if (newTorsion.first > newTorsion.fourth) {
505     std::swap(newTorsion.first, newTorsion.fourth);
506     std::swap(newTorsion.second, newTorsion.third);
507     }
508     if (allTorsions.find(newTorsion) == allTorsions.end() ) {
509     allTorsions.insert(newTorsion);
510     TorsionStamp * newTorsionStamp = new TorsionStamp();
511     newTorsionStamp->setMembers(newTorsion);
512     addTorsionStamp(newTorsionStamp);
513     }
514     }
515     }
516 tim 2483 }
517 gezelter 3173
518     }
519    
520     void MoleculeStamp::checkRigidBodies() {
521     std::ostringstream oss;
522     std::vector<RigidBodyStamp*>::iterator ri = std::find(rigidBodyStamps_.begin(),
523     rigidBodyStamps_.end(),
524     static_cast<RigidBodyStamp*>(NULL));
525     if (ri != rigidBodyStamps_.end()) {
526     oss << "Error in Molecule " << getName() << ":rigidBody[" <<
527     ri - rigidBodyStamps_.begin()<< "] is missing\n";
528     throw OOPSEException(oss.str());
529     }
530    
531 tim 2469 for (int i = 0; i < getNRigidBodies(); ++i) {
532 gezelter 3173 RigidBodyStamp* rbStamp = getRigidBodyStamp(i);
533     std::vector<int> rigidAtoms = rbStamp ->getMembers();
534     std::vector<int>::iterator j =std::find_if(rigidAtoms.begin(),
535     rigidAtoms.end(),
536     std::bind2nd(std::greater<int>(),
537     getNAtoms()-1));
538     if (j != rigidAtoms.end()) {
539     oss << "Error in Molecule " << getName();
540     throw OOPSEException(oss.str());
541     }
542 tim 2483 }
543 gezelter 3173 }
544    
545     void MoleculeStamp::checkCutoffGroups() {
546 tim 2483 for(int i = 0; i < getNCutoffGroups(); ++i) {
547 gezelter 3173 CutoffGroupStamp* cutoffGroupStamp = getCutoffGroupStamp(i);
548     std::vector<int> cutoffGroupAtoms = cutoffGroupStamp ->getMembers();
549     std::vector<int>::iterator j =std::find_if(cutoffGroupAtoms.begin(),
550     cutoffGroupAtoms.end(),
551     std::bind2nd(std::greater<int>(),
552     getNAtoms()-1));
553     if (j != cutoffGroupAtoms.end()) {
554     std::ostringstream oss;
555     oss << "Error in Molecule " << getName() << ": cutoffGroup" <<
556     " is out of range\n";
557     throw OOPSEException(oss.str());
558     }
559 tim 2483 }
560 gezelter 3173 }
561 gezelter 1490
562 gezelter 3173 void MoleculeStamp::checkFragments() {
563 gezelter 1490
564 gezelter 3173 std::vector<FragmentStamp*>::iterator fi = std::find(fragmentStamps_.begin(),
565     fragmentStamps_.end(),
566     static_cast<FragmentStamp*>(NULL));
567 tim 2483 if (fi != fragmentStamps_.end()) {
568 gezelter 3173 std::ostringstream oss;
569     oss << "Error in Molecule " << getName() << ":fragment[" <<
570     fi - fragmentStamps_.begin()<< "] is missing\n";
571     throw OOPSEException(oss.str());
572 tim 2483 }
573    
574 gezelter 3173 }
575    
576     void MoleculeStamp::fillBondInfo() {
577    
578 tim 2483 for (int i = 0; i < getNBonds(); ++i) {
579 gezelter 3173 BondStamp* bondStamp = getBondStamp(i);
580     int a = bondStamp->getA();
581     int b = bondStamp->getB();
582     AtomStamp* atomA = getAtomStamp(a);
583     AtomStamp* atomB = getAtomStamp(b);
584     atomA->addBond(i);
585     atomA->addBondedAtom(b);
586     atomB->addBond(i);
587     atomB->addBondedAtom(a);
588 tim 2483
589     }
590 gezelter 3173 }
591 gezelter 1490
592 tim 2483
593    
594 gezelter 3173 // Function Name: isBondInSameRigidBody
595     // Returns true is both atoms of the bond belong to the same rigid
596     // body, otherwise return false
597     bool MoleculeStamp::isBondInSameRigidBody(BondStamp* bond){
598     int rbA;
599     int rbB;
600     int consAtomA;
601     int consAtomB;
602 gezelter 1490
603 gezelter 3173 if (!isAtomInRigidBody(bond->getA(),rbA, consAtomA))
604     return false;
605 gezelter 1490
606 gezelter 3173 if(!isAtomInRigidBody(bond->getB(),rbB, consAtomB) )
607     return false;
608 gezelter 1490
609 gezelter 3173 if(rbB == rbA)
610     return true;
611     else
612     return false;
613     }
614 gezelter 1490
615 gezelter 3173 // Function Name: isAtomInRigidBody
616     // Returns false if atom does not belong to a rigid body, otherwise
617     // returns true
618     bool MoleculeStamp::isAtomInRigidBody(int atomIndex){
619     return atom2Rigidbody[atomIndex] >=0 ;
620     }
621 tim 2485
622 gezelter 3173 // Function Name: isAtomInRigidBody
623     // Returns false if atom does not belong to a rigid body otherwise
624     // returns true and sets whichRigidBody and consAtomIndex
625     // atomIndex : the index of atom in component
626     // whichRigidBody: the index of the rigidbody in the component
627     // consAtomIndex: the position the joint atom appears in the rigidbody's
628     // definition
629     bool MoleculeStamp::isAtomInRigidBody(int atomIndex, int& whichRigidBody,
630     int& consAtomIndex){
631     whichRigidBody = -1;
632     consAtomIndex = -1;
633    
634     if (atom2Rigidbody[atomIndex] >=0) {
635     whichRigidBody = atom2Rigidbody[atomIndex];
636     RigidBodyStamp* rbStamp = getRigidBodyStamp(whichRigidBody);
637     int numAtom = rbStamp->getNMembers();
638     for(int j = 0; j < numAtom; j++) {
639     if (rbStamp->getMemberAt(j) == atomIndex){
640     consAtomIndex = j;
641     return true;
642     }
643 gezelter 1490 }
644 tim 2485 }
645 gezelter 3173
646     return false;
647 gezelter 1490 }
648    
649 gezelter 3173 // Returns the position of joint atoms apearing in a rigidbody's definition
650     // For the time being, we will use the most inefficient algorithm,
651     // the complexity is O(N^2). We could improve the
652     // complexity to O(NlogN) by sorting the atom index in rigid body
653     // first
654     std::vector<std::pair<int, int> > MoleculeStamp::getJointAtoms(int rb1,
655     int rb2){
656     RigidBodyStamp* rbStamp1;
657     RigidBodyStamp* rbStamp2;
658     int natomInRb1;
659     int natomInRb2;
660     int atomIndex1;
661     int atomIndex2;
662     std::vector<std::pair<int, int> > jointAtomIndexPair;
663    
664     rbStamp1 = this->getRigidBodyStamp(rb1);
665     natomInRb1 =rbStamp1->getNMembers();
666    
667     rbStamp2 = this->getRigidBodyStamp(rb2);
668     natomInRb2 =rbStamp2->getNMembers();
669 gezelter 1490
670 gezelter 3173 for(int i = 0; i < natomInRb1; i++){
671     atomIndex1 = rbStamp1->getMemberAt(i);
672    
673     for(int j= 0; j < natomInRb1; j++){
674     atomIndex2 = rbStamp2->getMemberAt(j);
675 gezelter 1490
676 gezelter 3173 if(atomIndex1 == atomIndex2){
677     jointAtomIndexPair.push_back(std::make_pair(i, j));
678     break;
679     }
680 gezelter 1490
681 gezelter 3173 }
682 gezelter 1490
683 tim 2469 }
684 gezelter 1490
685 gezelter 3173 return jointAtomIndexPair;
686 tim 2469 }
687 gezelter 1490
688     }