Molmodel
|
00001 #ifndef ATOM_SUBSYSTEM_HPP_ 00002 #define ATOM_SUBSYSTEM_HPP_ 00003 00004 #include "SimTKsimbody.h" 00005 #include "molmodel/internal/common.h" 00006 #include "VoxelHash.h" 00007 #include <iterator> 00008 #include <set> 00009 00010 // #include "md_units.hpp" 00011 00012 // Subystem for managing atom locations. 00013 // Depends on matter subsystem 00014 00015 namespace SimTK { 00016 00017 using SimTK::units::md::nanometers; 00018 using SimTK::units::md::daltons; 00019 00020 class SimTK_MOLMODEL_EXPORT AtomSubsystem : public SimTK::Subsystem 00021 { 00022 protected: 00023 class Impl; 00024 const Impl& getRep() const; 00025 Impl& updRep(); 00026 00027 public: 00028 enum NeighborAlgorithm {N_SQUARED, VOXEL_HASH, AUTOMATIC}; 00029 00030 typedef SimTK::units::md::mass_t mass_t; 00031 typedef SimTK::units::md::length_t length_t; 00032 typedef SimTK::units::md::location_t location_t; 00033 typedef SimTK::units::md::area_t area_t; 00034 00035 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(AtomSubsystem, AtomIndex); // index within this subsystem 00036 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(AtomSubsystem, BodyAtomIndex); // index within one body 00037 // Mobilized body index within this subsystem, not the same as MultibodySystem MobilizedBodyIndex 00038 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(AtomSubsystem, LocalBodyIndex); 00039 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(AtomSubsystem, BondIndex); 00040 00041 typedef std::vector<AtomIndex> AtomIndexList; 00042 00043 class Atom 00044 { 00045 friend class AtomSubsystem; 00046 00047 private: 00048 // required static "Topology" stage properties 00049 AtomIndex atomIx; 00050 mass_t mass; // optional, unless used to set mass of bodies 00051 SimTK::MobilizedBodyIndex bodyIx; 00052 location_t stationInBody; 00053 std::set<AtomIndex> bonds; 00054 00055 // optional identifying information of possible use to force subsystems 00056 char atomType[5]; 00057 char residueType[5]; 00058 int residueNumber; 00059 bool isFirstResidue; 00060 bool isFinalResidue; 00061 00062 // private addBond method, so users will use AtomSubsystem::addBond method instead 00063 Atom& addBond(AtomIndex partnerIx) { 00064 bonds.insert(partnerIx); 00065 00066 return *this; 00067 } 00068 00069 // use AtomSubsystem::setAtomMobilizedBodyIndex() instead 00070 Atom& setMobilizedBodyIndex(MobilizedBodyIndex ix) { 00071 bodyIx = ix; 00072 return *this; 00073 } 00074 00075 public: 00076 Atom( 00077 AtomIndex atomIx, 00078 mass_t mass ) 00079 : atomIx(atomIx), mass(mass) 00080 {} 00081 00082 AtomIndex getAtomIndex() const {return atomIx;} 00083 00084 MobilizedBodyIndex getMobilizedBodyIndex() const {return bodyIx;} 00085 00086 const Vec3& getStationInBodyFrame() const {return stationInBody;} 00087 Atom& setStationInBodyFrame(const Vec3& s) { 00088 stationInBody = s; 00089 return *this; 00090 } 00091 00092 mass_t getMass() const {return mass;} 00093 Atom& setMass(mass_t m) { 00094 mass = m; 00095 return *this; 00096 } 00097 }; 00098 00099 class AtomsByBody { 00100 public: 00101 explicit AtomsByBody(MobilizedBodyIndex bodyIx) 00102 : bodyIx(bodyIx) 00103 {} 00104 00105 MobilizedBodyIndex bodyIx; 00106 AtomIndexList atoms; 00107 std::set<MobilizedBodyIndex> bodyExclusions; 00108 }; 00109 00110 typedef std::vector<AtomsByBody> AtomicBodies; 00111 00112 class Bond { 00113 public: 00114 Bond(AtomIndex a1, AtomIndex a2) 00115 { 00116 assert(a1 != a2); 00117 if (a1 < a2) { 00118 atom1Ix = a1; 00119 atom2Ix = a2; 00120 } 00121 else { 00122 atom1Ix = a2; 00123 atom2Ix = a1; 00124 } 00125 } 00126 00127 private: 00128 AtomIndex atom1Ix; 00129 AtomIndex atom2Ix; 00130 }; 00131 00132 00133 class PairIterator; 00134 PairIterator pairBegin( 00135 const State& state, 00136 length_t cutoff = 0.0 * nanometers, 00137 NeighborAlgorithm algorithm = AUTOMATIC) const; 00138 PairIterator pairEnd() const; 00139 00140 explicit AtomSubsystem(SimTK::MultibodySystem& system); 00141 00142 MultibodySystem& updMultibodySystem(); 00143 const MultibodySystem& getMultibodySystem() const; 00144 00145 AtomSubsystem& setAtomMobilizedBodyIndex(AtomIndex atomIx, MobilizedBodyIndex bodyIx); 00146 00147 // Fetch atom list by local body ID in this subsystem 00148 const AtomIndexList& getBodyAtoms( LocalBodyIndex bodyIx ) const; 00149 // Fetch atom list by body ID in MultibodySystem 00150 const AtomIndexList& getBodyAtoms( SimTK::MobilizedBodyIndex bodyIx ) const; 00151 00152 AtomIndex addAtom( mass_t mass = 0.0 * daltons ); 00153 00154 size_t getNumAtoms() const; 00155 00156 const Vec3& getAtomLocationInGround(const SimTK::State& state, AtomIndex atom) const; 00157 const Vec3& getAtomVelocityInGround(const SimTK::State& state, AtomIndex atom) const; 00158 00159 // useful for calculating body forces 00160 const Vec3& getAtomBodyStationInGround(const SimTK::State& state, AtomIndex atom) const; 00161 00162 const Atom& getAtom( AtomIndex ix ) const; 00163 Atom& updAtom( AtomIndex ix ) ; 00164 00165 BondIndex addBond(AtomIndex a1, AtomIndex a2); 00166 size_t getNumBonds() const; 00167 const Bond& getBond(BondIndex ix) const; 00168 Bond& updBond(BondIndex ix); 00169 00170 size_t getNumBodies() const; 00171 00172 void addBodyExclusion(MobilizedBodyIndex bodyIx1, MobilizedBodyIndex bodyIx2); 00173 00174 SimbodyMatterSubsystem& updMatterSubsystem(); 00175 }; 00176 00177 // Iterates over pairs of atoms not in the same body 00178 // Intended to use neighbor list if enough atoms and cutoff is supplied 00179 class AtomSubsystem::PairIterator 00180 : public std::iterator<std::forward_iterator_tag, std::pair<AtomSubsystem::AtomIndex, AtomSubsystem::AtomIndex> > 00181 { 00182 public: 00183 typedef std::pair<AtomIndex, AtomIndex> Pair; 00184 00185 private: 00186 Pair currentPair; 00187 const AtomSubsystem* atomSubsystem; 00188 const State* state; 00189 length_t cutoff; 00190 area_t cutoffSquared; 00191 const AtomicBodies* atomsByBody; 00192 AtomicBodies::const_iterator body1; 00193 AtomicBodies::const_iterator body2; 00194 AtomIndexList::const_iterator atom1; 00195 // atom2 iterator might point to a local container, when voxel hash is used. 00196 // which could become invalid when this iterator is copied. 00197 // So use an index for atom2, instead of an iterator 00198 // (body1, body2, and atom1 iterators always refer to atomsByBody pointee, and thus remain valid) 00199 size_t atom2Index; 00200 00201 NeighborAlgorithm algorithm; 00202 bool bUseVoxelHash; 00203 VoxelHash<AtomSubsystem::AtomIndex> voxelHash; // for use in O(n) neighbor list 00204 std::set<AtomicBodies::const_iterator> pendingBodies; 00205 AtomIndexList currentNeighborAtoms; 00206 00207 void trialIncrementAtoms(); 00208 void trialIncrementBodies(); 00209 void populateVoxelHash(AtomicBodies::const_iterator bodyIter); 00210 00211 public: 00212 // 0.0 means no cutoff applied 00213 SimTK_MOLMODEL_EXPORT PairIterator( 00214 const AtomSubsystem& a, 00215 const State& state, 00216 length_t cutoff = 0.0 * nanometers, 00217 NeighborAlgorithm algorithm = AUTOMATIC 00218 ); 00219 SimTK_MOLMODEL_EXPORT PairIterator(); // need default constructor for what? 00220 00221 SimTK_MOLMODEL_EXPORT bool operator!=(const PairIterator& rhs) const; 00222 SimTK_MOLMODEL_EXPORT bool operator==(const PairIterator& rhs) const; 00223 SimTK_MOLMODEL_EXPORT bool atEnd() const; 00224 00225 // postfix increment, defined in terms of prefix increment 00226 SimTK_MOLMODEL_EXPORT PairIterator operator++(int); 00227 00228 // prefix increment 00229 // TODO - the meat of the neighbor list algorithm must go in here 00230 SimTK_MOLMODEL_EXPORT PairIterator& operator++(); 00231 00232 SimTK_MOLMODEL_EXPORT const Pair& operator*() const; 00233 SimTK_MOLMODEL_EXPORT const Pair* operator->() const; 00234 }; 00235 00236 } // namespace SimTK 00237 00238 #endif /* ATOM_SUBSYSTEM_HPP_ */