// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == crystal growth group == // == == // == Stiftung caesar == // == Ludwig-Erhard-Allee 2 == // == 53175 Bonn == // == germany == // == == // ============================================================================ // == == // == http://www.caesar.de/cg/AMDiS == // == == // ============================================================================ /** \file Traverse.h */ /** \defgroup Traverse Traverse module * @{ @} * * \brief * Contains classes used for mesh traversal. */ #ifndef AMDIS_TRAVERSE_H #define AMDIS_TRAVERSE_H #include "Flag.h" #include "Global.h" #include "ElInfo.h" #include "ElInfoStack.h" #include "MemoryManager.h" #include #include namespace AMDiS { class MacroElement; class Mesh; // =========================================================================== // ===== class TraverseStack ================================================= // =========================================================================== /** \ingroup Traverse * \brief * Mesh refinement and coarsening routines are examples of functions which * need a non-recursive access to the mesh elements. * The implementation of the non-recursive mesh traversal routines uses a * stack to save the tree path from a macro element to the current element. * TraverseStack holds such information. Before calling the non-recursive mesh * traversal routines, such a stack must be allocated. The stack is * initialized by each call to \ref traverseFirst(). */ class TraverseStack { public: MEMORY_MANAGED(TraverseStack); /** \brief * Creates an empty TraverseStack */ TraverseStack() : traverse_mel(NULL), stack_size(0), stack_used(0), save_stack_used(0), myThreadId_(0), maxThreads_(1) { id = ElInfo::traverseIdCounter++; }; /** \brief * Destructor */ ~TraverseStack() { for (int i = 0; i < static_cast(elinfo_stack.size()); i++) { DELETE elinfo_stack[i]; } for (int i = 0; i < static_cast(save_elinfo_stack.size()); i++) { DELETE save_elinfo_stack[i]; } }; public: /** \brief * Returns the first ElInfo of a non recursive traversal which fullfills the * selection criterion specified by level and fill_flag and initializes the * stack. After a call of traverseFirst the next Elements are traversed via * \ref traverseNext(). */ ElInfo* traverseFirst(Mesh *mesh, int level, Flag fill_flag); /** \brief * Returns the next ElInfo in a traversal initiated by \ref traverseFirst() * If NULL is returned, the traversal is finished. */ ElInfo* traverseNext(ElInfo* elinfo_old); /** \brief * Returns the neighbour-th neighbour of elInfoOld */ ElInfo* traverseNeighbour(ElInfo* elInfoOld, int neighbour); /** \brief * Returns the neighbour-th neighbour of elInfoOld */ ElInfo* traverseNeighbour3d(ElInfo* elInfoOld, int neighbour); /** \brief * Returns the neighbour-th neighbour of elInfoOld */ ElInfo* traverseNeighbour2d(ElInfo* elInfoOld, int neighbour); /** \brief * Not yet implemented */ ElInfo* traverseMultiGridLevel(); /** \brief * Preorder traversal of all elements */ ElInfo* traverseEveryElementPreorder(); /** \brief * Inorder traversal of all elements */ ElInfo* traverseEveryElementInorder(); /** \brief * Postorder traversal of all elements */ ElInfo* traverseEveryElementPostorder(); /** \brief * Only for 3d: Calls update of all ElInfo3d onjects in \ref elinfo_stack */ void update(); void getCoordsInElem(const ElInfo *upperElInfo, VectorOfFixVecs > *coords); /** \brief * */ inline void setMyThreadId(int myThreadId) { myThreadId_ = myThreadId; } /** \brief * */ inline void setMaxThreads(int maxThreads) { maxThreads_ = maxThreads; } private: /** \brief * Enlargement of the stack */ void enlargeTraverseStack(); /** \brief * Used by \ref traverseFirst() \ref traverseNext() */ ElInfo* traverseLeafElement(); /** \brief * Used by \ref traverseFirst() \ref traverseNext() */ ElInfo* traverseLeafElementLevel(); /** \brief * Used by \ref traverseFirst() \ref traverseNext() */ ElInfo* traverseElementLevel(); /** \brief * Avoids copy of a traverse stack. If copy should be possible * the operator must be implemented (deep copy not flat copy!) */ void operator=(const TraverseStack& /*rhs*/) { FUNCNAME("TraverseStack::operator="); ERROR_EXIT("not implemented"); }; /** \brief * Avoids copy of a traverse stack. If copy should be possible * the operator must be implemented (deep copy not flat copy!) */ TraverseStack(const TraverseStack&) { FUNCNAME("TraverseStack::TraverseStack(const TraverseStack&)"); ERROR_EXIT("not implemented"); }; private: /** \brief * Iterator to the current MacroElement */ std::deque::const_iterator currentMacro; /** \brief * Mesh which is currently traversed */ Mesh* traverse_mesh; /** \brief * Traverse level. Used if CALL_EL_LEVEL or CALL_LEAF_EL_LEVEL are set in * \ref traverse_fill_flag */ int traverse_level; /** \brief * Flags for traversal. Specifies which elements are visited and which * information are filled to the ElInfo objects. */ Flag traverse_fill_flag; /** \brief * current macro element */ const MacroElement *traverse_mel; /** \brief * Current size of the stack */ int stack_size; /** \brief * Used size of the stack */ int stack_used; /** \brief * */ std::vector elinfo_stack; /** \brief * */ std::vector info_stack; /** \brief * */ const MacroElement *save_traverse_mel; /** \brief * */ std::vector save_elinfo_stack; /** \brief * */ std::vector save_info_stack; /** \brief * */ int save_stack_used; /** \brief * */ int id; /** \brief * Is used for parallel mesh traverse. The thread with the id * myThreadId is only allowed to access coarse elements, which id * satisfies: elId % maxThreads = myThreadId. */ int myThreadId_; /** \brief * Is used for parallel mesh traverse. The thread with the id * myThreadId is only allowed to access coarse elements, which id * satisfies: elId % maxThreads = myThreadId. */ int maxThreads_; }; // ============================================================================ // ===== class Traverse ======================================================= // ============================================================================ /** \ingroup Traverse * \brief * Class for recursive mesh traversal. Used in \ref Mesh::traverse() */ class Traverse { public: MEMORY_MANAGED(Traverse); /** \brief * Creates a Traverse object for Mesh m with fill flags f and level l. * el_fct is a pointer to a the function that will be called for every * visited element. */ Traverse(Mesh* m, const Flag f, const unsigned char l, int (*ef)(ElInfo*)) : mesh(m), flag(f), level(l), el_fct(ef) { TEST_EXIT(m)("No traverse without mesh!\n"); id = ElInfo::traverseIdCounter++; }; /** \brief * Performs the recursive traversal */ // int recursive(ElInfo*); int recursive(ElInfoStack*); private: Mesh *mesh; Flag flag; unsigned char level; int (*el_fct)(ElInfo*); int id; Traverse(); Traverse(const Traverse&); }; } #endif // AMDIS_TRAVERSE_H