/* * World.hpp * * Created on: Feb 3, 2010 * Author: crueger */ #ifndef WORLD_HPP_ #define WORLD_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif /*********************************************** includes ***********************************/ #include #include #include #include #include #include #include "Actions/ActionTrait.hpp" #include "Atom/AtomSet.hpp" #include "Descriptors/SelectiveIterator.hpp" #include "CodePatterns/Observer/Observable.hpp" #include "CodePatterns/Observer/Observer.hpp" #include "CodePatterns/Cacheable.hpp" #include "CodePatterns/Singleton.hpp" #include "CodePatterns/Observer/ObservedContainer.hpp" #include "CodePatterns/Range.hpp" #include "IdPool_policy.hpp" #include "IdPool.hpp" #include "LinkedCell/LinkedCell_View.hpp" #include "types.hpp" // forward declarations class atom; class AtomDescriptor; class AtomDescriptor_impl; class BondGraph; class Box; class config; class RealSpaceMatrix; class molecule; class MoleculeDescriptor; class MoleculeDescriptor_impl; class MoleculeListClass; class periodentafel; class ThermoStatContainer; namespace LinkedCell { class LinkedCell_Controller; } namespace MoleCuilder { class ManipulateAtomsProcess; template class AtomsCalculation; } /****************************************** forward declarations *****************************/ /********************************************** Class World *******************************/ namespace detail { template const T* lastChanged() { ASSERT(0, "detail::lastChanged() - only specializations may be used."); return NULL; } } class World : public Singleton, public Observable { // Make access to constructor and destructor possible from inside the singleton friend class Singleton; // necessary for coupling with descriptors friend class AtomDescriptor_impl; friend class AtomDescriptor; friend class MoleculeDescriptor_impl; friend class MoleculeDescriptor; // coupling with descriptors over selection friend class AtomSelectionDescriptor_impl; friend class AtomOfMoleculeSelectionDescriptor_impl; friend class AtomOrderDescriptor_impl; friend class MoleculeOfAtomSelectionDescriptor_impl; friend class MoleculeOrderDescriptor_impl; friend class MoleculeSelectionDescriptor_impl; // Actions, calculations etc associated with the World friend class MoleCuilder::ManipulateAtomsProcess; template friend class MoleCuilder::AtomsCalculation; public: // some typedefs for the CONSTRUCT_... macros (no "," allows in a single parameter name) typedef std::map AtomSTLSet; typedef std::map MoleculeSTLSet; // Types for Atom and Molecule structures typedef ObservedContainer< AtomSTLSet > AtomSet; typedef ObservedContainer< MoleculeSTLSet > MoleculeSet; typedef ATOMSET(std::vector) AtomComposite; /******* Notifications *******/ //!> enumeration of present notification types: only insertion/removal of atoms or molecules enum NotificationType { AtomInserted, AtomRemoved, MoleculeInserted, MoleculeRemoved, SelectionChanged, NotificationType_MAX }; //>! access to last changed element (atom or molecule) template const T* lastChanged() const { return detail::lastChanged(); } /***** getter and setter *****/ // reference to pointer is used for legacy reason... reference will be removed latter to keep encapsulation of World object /** * returns the periodentafel for the world. */ periodentafel *&getPeriode(); /** Returns the BondGraph for the World. * * @return reference to BondGraph */ BondGraph *&getBondGraph(); /** Sets the World's BondGraph. * * @param _BG new BondGraph */ void setBondGraph(BondGraph *_BG); /** * returns the configuration for the world. */ config *&getConfig(); /** Returns a notification_ptr for a specific type. * * @param type request type * @return reference to instance */ Notification_ptr getNotification(enum NotificationType type) const; /** * returns the first atom that matches a given descriptor. * Do not rely on ordering for descriptors that match more than one atom. */ atom* getAtom(AtomDescriptor descriptor); /** * returns a vector containing all atoms that match a given descriptor */ AtomComposite getAllAtoms(AtomDescriptor descriptor); AtomComposite getAllAtoms(); /** * returns a calculation that calls a given function on all atoms matching a descriptor. * the calculation is not called at this point and can be used as an action, i.e. be stored in * menus, be kept around for later use etc. */ template MoleCuilder::AtomsCalculation* calcOnAtoms(boost::function,const MoleCuilder::ActionTrait &_trait,AtomDescriptor); template MoleCuilder::AtomsCalculation* calcOnAtoms(boost::function,const MoleCuilder::ActionTrait &_trait); /** * get the number of atoms in the World */ int numAtoms(); /** * returns the first molecule that matches a given descriptor. * Do not rely on ordering for descriptors that match more than one molecule. */ molecule *getMolecule(MoleculeDescriptor descriptor); /** * returns a vector containing all molecules that match a given descriptor */ std::vector getAllMolecules(MoleculeDescriptor descriptor); std::vector getAllMolecules(); /** * get the number of molecules in the World */ int numMolecules(); /** * get the domain size as a symmetric matrix (6 components) */ Box& getDomain(); /** * Set the domain size from a matrix object * * Matrix needs to be symmetric */ void setDomain(const RealSpaceMatrix &mat); /** * set the domain size as a symmetric matrix (6 components) */ void setDomain(double * matrix); /** Returns a LinkedCell structure for obtaining neighbors quickly. * * @param distance desired linked cell edge length * @return view of restricted underlying LinkedCell_Model */ LinkedCell::LinkedCell_View getLinkedCell(const double distance); /** * set the current time of the world. * * @param _step time step to set to */ void setTime(const unsigned int _step); /** * get the default name */ std::string getDefaultName(); /** * set the default name */ void setDefaultName(std::string name); /** * get pointer to World's ThermoStatContainer */ ThermoStatContainer * getThermostats(); /* * get the ExitFlag */ int getExitFlag(); /* * set the ExitFlag */ void setExitFlag(int flag); /***** Methods to work with the World *****/ /** * create a new molecule. This method should be used whenever any kind of molecule is needed. Assigns a unique * ID to the molecule and stores it in the World for later retrieval. Do not create molecules directly. */ molecule *createMolecule(); void destroyMolecule(molecule*); void destroyMolecule(moleculeId_t); /** * Create a new atom. This method should be used whenever any atom is needed. Assigns a unique ID and stores * the atom in the World. If the atom is not destroyed it will automatically be destroyed when the world ends. */ atom *createAtom(); /** * Registers a Atom unknown to world. Needed in some rare cases, e.g. when cloning atoms, or in some unittests. * Do not re-register Atoms already known to the world since this will cause double-frees. */ int registerAtom(atom*); /** * Delete some atom and erase it from the world. Use this whenever you need to destroy any atom. Do not call delete on * atom directly since this will leave the pointer inside the world. */ void destroyAtom(atom*); /** * Delete some atom and erase it from the world. Use this whenever you need to destroy any atom. Do not call delete on * atom directly since this will leave the pointer inside the world. */ void destroyAtom(atomId_t); /** * used when changing an atom Id. * Unless you are calling this method from inside an atom don't fiddle with the third parameter. * * Return value indicates whether the change could be done or not. */ bool changeAtomId(atomId_t oldId, atomId_t newId, atom* target=0); /** * used when changing an molecule Id. * Unless you are calling this method from inside an molecule don't fiddle with the third parameter. * * Return value indicates whether the change could be done or not. */ bool changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target=0); /** * Produces a process that calls a function on all Atoms matching a given descriptor. The process is not * called at this time, so it can be passed around, stored inside menuItems etc. */ MoleCuilder::ManipulateAtomsProcess* manipulateAtoms(boost::function,std::string,AtomDescriptor); MoleCuilder::ManipulateAtomsProcess* manipulateAtoms(boost::function,std::string); /**** * Iterators to use internal data structures * All these iterators are observed to track changes. * There is a corresponding protected section with unobserved iterators, * which can be used internally when the extra speed is needed */ typedef SelectiveIterator AtomIterator; /** * returns an iterator over all Atoms matching a given descriptor. * This iterator is observed, so don't keep it around unnecessary to * avoid unintended blocking. */ AtomIterator getAtomIter(AtomDescriptor descr); AtomIterator getAtomIter(); AtomIterator atomEnd(); typedef SelectiveIterator MoleculeIterator; /** * returns an iterator over all Molecules matching a given descriptor. * This iterator is observed, so don't keep it around unnecessary to * avoid unintended blocking. */ MoleculeIterator getMoleculeIter(MoleculeDescriptor descr); MoleculeIterator getMoleculeIter(); MoleculeIterator moleculeEnd(); /******** Selections of molecules and Atoms *************/ void clearAtomSelection(); void invertAtomSelection(); void selectAtom(const atom*); void selectAtom(const atomId_t); void selectAllAtoms(AtomDescriptor); void selectAtomsOfMolecule(const molecule*); void selectAtomsOfMolecule(const moleculeId_t); void unselectAtom(const atom*); void unselectAtom(const atomId_t); void unselectAllAtoms(AtomDescriptor); void unselectAtomsOfMolecule(const molecule*); void unselectAtomsOfMolecule(const moleculeId_t); size_t countSelectedAtoms() const; bool isSelected(const atom *_atom) const; bool isAtomSelected(const atomId_t no) const; const std::vector getSelectedAtoms() const; void clearMoleculeSelection(); void invertMoleculeSelection(); void selectMolecule(const molecule*); void selectMolecule(const moleculeId_t); void selectAllMolecules(MoleculeDescriptor); void selectMoleculeOfAtom(const atom*); void selectMoleculeOfAtom(const atomId_t); void unselectMolecule(const molecule*); void unselectMolecule(const moleculeId_t); void unselectAllMolecules(MoleculeDescriptor); void unselectMoleculeOfAtom(const atom*); void unselectMoleculeOfAtom(const atomId_t); size_t countSelectedMolecules() const; bool isSelected(const molecule *_mol) const; bool isMoleculeSelected(const moleculeId_t no) const; const std::vector getSelectedMolecules() const; /******************** Iterators to selections *****************/ typedef AtomSet::iterator AtomSelectionIterator; AtomSelectionIterator beginAtomSelection(); AtomSelectionIterator endAtomSelection(); typedef AtomSet::const_iterator AtomSelectionConstIterator; AtomSelectionConstIterator beginAtomSelection() const; AtomSelectionConstIterator endAtomSelection() const; typedef MoleculeSet::iterator MoleculeSelectionIterator; MoleculeSelectionIterator beginMoleculeSelection(); MoleculeSelectionIterator endMoleculeSelection(); typedef MoleculeSet::const_iterator MoleculeSelectionConstIterator; MoleculeSelectionConstIterator beginMoleculeSelection() const; MoleculeSelectionConstIterator endMoleculeSelection() const; protected: /**** * Iterators to use internal data structures * All these iterators are unobserved for speed reasons. * There is a corresponding public section to these methods, * which produce observed iterators.*/ // Atoms typedef SelectiveIterator internal_AtomIterator; /** * returns an iterator over all Atoms matching a given descriptor. * used for internal purposes, like AtomProcesses and AtomCalculations. */ internal_AtomIterator getAtomIter_internal(AtomDescriptor descr); /** * returns an iterator to the end of the AtomSet. Due to overloading this iterator * can be compared to iterators produced by getAtomIter (see the mis-matching types). * Thus it can be used to detect when such an iterator is at the end of the list. * used for internal purposes, like AtomProcesses and AtomCalculations. */ internal_AtomIterator atomEnd_internal(); // Molecules typedef SelectiveIterator internal_MoleculeIterator; /** * returns an iterator over all Molecules matching a given descriptor. * used for internal purposes, like MoleculeProcesses and MoleculeCalculations. */ internal_MoleculeIterator getMoleculeIter_internal(MoleculeDescriptor descr); /** * returns an iterator to the end of the MoleculeSet. Due to overloading this iterator * can be compared to iterators produced by getMoleculeIter (see the mis-matching types). * Thus it can be used to detect when such an iterator is at the end of the list. * used for internal purposes, like MoleculeProcesses and MoleculeCalculations. */ internal_MoleculeIterator moleculeEnd_internal(); /******* Internal manipulation routines for double callback and Observer mechanism ******/ void doManipulate(MoleCuilder::ManipulateAtomsProcess *); private: friend const atom *detail::lastChanged(); friend const molecule *detail::lastChanged(); static atom *_lastchangedatom; static molecule*_lastchangedmol; BondGraph *BG; periodentafel *periode; config *configuration; Box *cell_size; LinkedCell::LinkedCell_Controller *LCcontroller; std::string defaultName; class ThermoStatContainer *Thermostats; int ExitFlag; private: AtomSet atoms; AtomSet selectedAtoms; /** * stores the pool for all available AtomIds below currAtomId * * The pool contains ranges of free ids in the form [bottom,top). */ IdPool atomIdPool; MoleculeSet molecules; MoleculeSet selectedMolecules; /** * stores the pool for all available AtomIds below currAtomId * * The pool contains ranges of free ids in the form [bottom,top). */ IdPool moleculeIdPool; private: /** * private constructor to ensure creation of the world using * the singleton pattern. */ World(); /** * private destructor to ensure destruction of the world using the * singleton pattern. */ virtual ~World(); /***** * some legacy stuff that is include for now but will be removed later *****/ public: MoleculeListClass *&getMolecules(); private: MoleculeListClass *molecules_deprecated; }; /** Externalized stuff as member functions cannot be specialized without * specializing the class, too. */ namespace detail { template <> inline const atom* lastChanged() { return World::_lastchangedatom; } template <> inline const molecule* lastChanged() { return World::_lastchangedmol; } } #endif /* WORLD_HPP_ */