Molmodel

AtomSubsystem.h

Go to the documentation of this file.
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_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines