// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == crystal growth group == // == == // == Stiftung caesar == // == Ludwig-Erhard-Allee 2 == // == 53175 Bonn == // == germany == // == == // ============================================================================ // == == // == http://www.caesar.de/cg/AMDiS == // == == // ============================================================================ /** \file Mesh.h */ /** \defgroup Triangulation Triangulation module * @{ @} * * Example: * * @{ @} * * \brief * Contains all triangulation classes. */ #ifndef AMDIS_MESH_H #define AMDIS_MESH_H // ============================================================================ // ===== includes ============================================================= // ============================================================================ #include "DOFAdmin.h" #include "Line.h" #include "Triangle.h" #include "Tetrahedron.h" #include "Element.h" #include "ElInfo.h" #include "FixVec.h" #include "MemoryManager.h" #include "Serializable.h" #include "BoundaryCondition.h" #include #include #include namespace AMDiS { // ============================================================================ // ===== forward declarations ================================================= // ============================================================================ template class DimVec; template class VectorOfFixVecs; class Boundary; class Projection; class ElInfo; class Element; class MacroElement; class DOFAdmin; class MacroInfo; template class WorldVector; class Quadrature; class Parametric; class PeriodicBC; class DOFVectorDOF; class VertexVector; // ============================================================================ // ===== class Mesh =========================================================== // ============================================================================ /** \ingroup Triangulation * \brief * A Mesh holds all information about a triangulation. */ class Mesh : public Serializable { public: MEMORY_MANAGED(Mesh); /** \brief * Creates a mesh with the given name of dimension dim */ Mesh(const std::string& name, int dim); /** \brief * Destructor */ virtual ~Mesh(); /** \brief * Reads macro triangulation. */ void initialize(); /** \brief * Assignment operator */ Mesh& operator=(const Mesh&); /** \name static methods used while mesh traversal * \{ */ /** \brief * Used while dof compress */ static int newDOFFct1(ElInfo* e); /** \brief * Used while dof compress */ static int newDOFFct2(ElInfo* e); /** \} */ // ========================================================================== /** \name getting methods * \{ */ /** \brief * Returns geometric information about this mesh. With GeoIndex p it is * specifiedm which information is requested. */ inline int getGeo(GeoIndex p) const { return Global::getGeo(p, dim); }; /** \brief * Returns \ref name of the mesh */ inline const std::string& getName() const { return name; }; /** \brief * Returns \ref dim of the mesh */ inline int getDim() const { return dim; }; /** \brief * Returns \ref nDOFEl of the mesh */ inline const int getNumberOfAllDOFs() const { return nDOFEl; }; /** \brief * Returns \ref nNodeEl of the mesh */ inline const int getNumberOfNodes() const { return nNodeEl; }; /** \brief * Returns \ref nVertices of the mesh */ inline const int getNumberOfVertices() const { return nVertices; }; /** \brief * Returns \ref nEdges of the mesh */ inline const int getNumberOfEdges() const { return nEdges; }; /** \brief * Returns \ref nFaces of the mesh */ inline const int getNumberOfFaces() const { return nFaces; }; /** \brief * Returns \ref nLeaves of the mesh */ inline const int getNumberOfLeaves() const { return nLeaves; }; /** \brief * Returns \ref nElements of the mesh */ inline const int getNumberOfElements() const { return nElements; }; /** \brief * Returns \ref maxEdgeNeigh of the mesh */ inline const int getMaxEdgeNeigh() const { return maxEdgeNeigh; }; /** \brief * Returns \ref parametric of the mesh */ inline Parametric *getParametric() const { return parametric; }; /** \brief * Returns \ref diam of the mesh */ inline const WorldVector& getDiameter() const { return diam; }; /** \brief * Returns nDOF[i] of the mesh */ inline const int getNumberOfDOFs(int i) const { return nDOF[i]; }; /** \brief * Returns \ref elementPrototype of the mesh */ inline Element* getElementPrototype() { return elementPrototype; }; /** \brief * Returns \ref leafDataPrototype of the mesh */ inline ElementData* getElementDataPrototype() { return elementDataPrototype; }; /** \brief * Returns node[i] of the mesh */ inline int getNode(int i) const { return node[i]; }; /** \brief * Allocates the number of DOFs needed at position and registers the DOFs * at the DOFAdmins. The number of needed DOFs is the sum over the needed * DOFs of all DOFAdmin objects belonging to this mesh. * The return value is a pointer to the first allocated DOF. */ DegreeOfFreedom *getDOF(GeoIndex position); /** \brief * Returns *(\ref admin[i]) of the mesh */ inline const DOFAdmin& getDOFAdmin(int i) const { return *(admin[i]); }; /** \brief * Creates a DOFAdmin with name lname. nDOF specifies how many DOFs * are needed at the different positions (see \ref DOFAdmin::nrDOF). * A pointer to the created DOFAdmin is returned. */ const DOFAdmin* createDOFAdmin(const std::string& lname, DimVec nDOF); /** \brief * Returns the size of \ref admin which is the number of the DOFAdmins * belonging to this mesh */ const int getNumberOfDOFAdmin() const { return admin.size(); }; /** \brief * Returns the size of \ref macroElements which is the number of * of macro elements of this mesh */ const int getNumberOfMacros() const { return macroElements.size(); }; /** \brief * Returns a DOFAdmin which at least manages vertex DOFs */ const DOFAdmin* getVertexAdmin() const; /** \brief * Allocates a array of DOF pointers. The array holds one pointer for * each node. */ DegreeOfFreedom **createDOFPtrs(); /** \brief * Returns \ref preserveCoarseDOFs of the mesh */ inline bool queryCoarseDOFs() const { return preserveCoarseDOFs; }; /** \brief * Returns an iterator to the begin of \ref macroElements */ inline std::deque::iterator firstMacroElement() { return macroElements.begin(); }; /** \brief * Returns macroElements[i]. */ inline MacroElement *getMacroElement(int i) { return macroElements[i]; }; /** \brief * Returns an iterator to the end of \ref macroElements */ inline std::deque::iterator endOfMacroElements() { return macroElements.end(); }; /** \} */ // ========================================================================== /** \name setting methods * \{ */ /** \brief * Sets \ref name of the mesh */ inline void setName(const std::string& aName) { name = aName; }; /** \brief * Sets \ref nVertices of the mesh */ inline void setNumberOfVertices(int n) { nVertices = n; }; /** \brief * Sets \ref nFaces of the mesh */ inline void setNumberOfFaces(int n) { nFaces = n; }; /** \brief * Increments \ref nVertices by inc */ inline void incrementNumberOfVertices(int inc) { nVertices += inc; }; /** \brief * Sets \ref nEdges of the mesh */ inline void setNumberOfEdges(int n) { nEdges = n; }; /** \brief * Increments \ref nEdges by inc */ inline void incrementNumberOfEdges(int inc) { nEdges += inc; }; /** \brief * Increments \ref nFaces by inc */ inline void incrementNumberOfFaces(int inc) { nFaces += inc; }; /** \brief * Sets \ref nLeaves of the mesh */ inline void setNumberOfLeaves(int n) { nLeaves = n; }; /** \brief * Increments \ref nLeaves by inc */ inline void incrementNumberOfLeaves(int inc) { nLeaves += inc; }; /** \brief * Sets \ref nElements of the mesh */ inline void setNumberOfElements(int n) { nElements = n; }; /** \brief * Increments \ref nElements by inc */ inline void incrementNumberOfElements(int inc) { nElements += inc; }; /** \brief * Sets *\ref diam to w */ void setDiameter(const WorldVector& w); /** \brief * Sets (*\ref diam)[i] to d */ void setDiameter(int i, double d); /** \brief * Sets \ref preserveCoarseDOFs = true */ inline void retainCoarseDOFs() { preserveCoarseDOFs = true; }; /** \brief * Sets \ref preserveCoarseDOFs = b */ inline void setPreserveCoarseDOFs(bool b) { preserveCoarseDOFs = b; }; /** \brief * Sets \ref preserveCoarseDOFs = false */ inline void noCoarseDOFs() { preserveCoarseDOFs = false; }; /** \brief * Sets \ref elementPrototype of the mesh */ inline void setElementPrototype(Element* prototype) { elementPrototype = prototype; }; /** \brief * Sets \ref elementDataPrototype of the mesh */ inline void setElementDataPrototype(ElementData* prototype) { elementDataPrototype = prototype; }; inline void setParametric(Parametric *param) { parametric = param; }; inline void setMaxEdgeNeigh(int m) { maxEdgeNeigh = m; }; /** \} */ // ========================================================================== /** \brief * Creates a new Element by cloning \ref elementPrototype */ Element* createNewElement(Element *parent = NULL); /** \brief * Creates a new ElInfo dependent of \ref dim of the mesh */ ElInfo* createNewElInfo(); /** \brief * Frees DOFs at the given position pointed by dof */ void freeDOF(DegreeOfFreedom* dof, GeoIndex position); /** \brief * Frees memory for the given element el */ void freeElement(Element* el); /** \brief * Performs DOF compression for all DOFAdmins (see \ref DOFAdmin::compress) */ void dofCompress(); /** \brief * Adds a DOFAdmin to the mesh */ virtual void addDOFAdmin(DOFAdmin *admin_); /** \brief * Traverses the mesh. The argument level specifies the element level if * CALL_EL_LEVEL or CALL_LEAF_EL_LEVEL, or the multigrid level if * CALL_MG_LEVEL is set. Otherwise this variable is ignored. By the argument * fillFlag the elements to be traversed and data to be filled into ElInfo is * selected, using bitwise or of one CALL_... flag and several FILL_... * flags. The argument elFct is a pointer to a function which is called on * every element selected by the CALL_... part of fillFlag. * It is possible to use the recursive mesh traversal recursively, by calling * traverse() from elFct. */ int traverse(int level, const Flag fillFlag, int (*elFct)(ElInfo*)); /** \brief * Clears \ref macroElements */ inline void clearMacroElements() { macroElements.clear(); }; /** \brief * Adds a macro element to the mesh */ void addMacroElement(MacroElement* me); /** \brief * Frees the array of DOF pointers (see \ref createDOFPtrs) */ void freeDOFPtrs(DegreeOfFreedom **ptrs); /** \brief * Used by \ref findElementAtPoint. */ bool findElInfoAtPoint(const WorldVector& xy, ElInfo *el_info, DimVec& bary, const MacroElement *start_mel, const WorldVector *xy0, double *sp); /** \brief * Access to an element at world coordinates xy. Some applications need the * access to elements at a special location in world coordinates. Examples * are characteristic methods for convection problems, or the implementation * of a special right hand side like point evaluations or curve integrals. * For such purposes, a routine is available which returns an element pointer * and corresponding barycentric coordinates. * * \param xy world coordinates of point * \param elp return address for a pointer to the element at xy * \param pary returns barycentric coordinates of xy * \param start_mel initial guess for the macro element containing xy or NULL * \param xy0 start point from a characteristic method, see below, or NULL * \param sp return address for relative distance to domain boundary in a * characteristic method, see below, or NULL * \return true is xy is inside the domain , false otherwise * * For a characteristic method, where \f$ xy = xy_0 - V\tau \f$, it may be * convenient to know the point on the domain's boundary which lies on the * line segment between the old point xy0 and the new point xy, in case that * xy is outside the domain. Such information is returned when xy0 and a * pointer sp!=NULL are supplied: *sp is set to the value s such that * \f$ xy_0 +s (xy -xy_0) \in \partial Domain \f$, and the element and local * coordinates corresponding to that boundary point will be returned via elp * and bary. * * The implementation of findElementAtPoint() is based on the transformation * from world to local coordinates, available via the routine worldToCoord(), * At the moment, findElementAtPoint() works correctly only for domains with * non-curved boundary. This is due to the fact that the implementation first * looks for the macro-element containing xy and then finds its path through * the corresponding element tree based on the macro barycentric coordinates. * For non-convex domains, it is possible that in some cases a point inside * the domain is considered as external. */ bool findElementAtPoint(const WorldVector& xy, Element **elp, DimVec& bary, const MacroElement *start_mel, const WorldVector *xy0, double *sp); /** \brief * Returns FILL_ANY_?D */ inline static const Flag& getFillAnyFlag(int dim) { switch (dim) { case 1: return FILL_ANY_1D; break; case 2: return FILL_ANY_2D; break; case 3: return FILL_ANY_3D; break; default: ERROR_EXIT("invalid dim\n"); return FILL_ANY_1D; } }; // ===== Serializable implementation ===== void serialize(std::ostream &out); void deserialize(std::istream &in); /** \brief * Returns \ref elementIndex and increments it by 1. */ inline int getNextElementIndex() { return elementIndex++; }; /** \brief * Returns \ref initialized. */ inline bool isInitialized() { return initialized; }; inline std::map& getPeriodicAssociations() { return periodicAssociations; }; bool associated(DegreeOfFreedom dof1, DegreeOfFreedom dof2); bool indirectlyAssociated(DegreeOfFreedom dof1, DegreeOfFreedom dof2); inline MacroInfo* getMacroFileInfo() { return macroFileInfo_; }; void clearMacroFileInfo(); public: /** \brief * */ static const Flag FILL_NOTHING; /** \brief * */ static const Flag FILL_COORDS; /** \brief * */ static const Flag FILL_BOUND; /** \brief * */ static const Flag FILL_NEIGH; /** \brief * */ static const Flag FILL_OPP_COORDS; /** \brief * */ static const Flag FILL_ORIENTATION; /** \brief * */ static const Flag FILL_ADD_ALL; /** \brief * */ static const Flag FILL_ANY_1D; /** \brief * */ static const Flag FILL_ANY_2D; /** \brief * */ static const Flag FILL_ANY_3D; /** \brief * */ static const Flag FILL_DET; /** \brief * */ static const Flag FILL_GRD_LAMBDA; //************************************************************************** // flags for Mesh traversal //************************************************************************** /** \brief * */ static const Flag CALL_EVERY_EL_PREORDER; /** \brief * */ static const Flag CALL_EVERY_EL_INORDER; /** \brief * */ static const Flag CALL_EVERY_EL_POSTORDER; /** \brief * */ static const Flag CALL_LEAF_EL; /** \brief * */ static const Flag CALL_LEAF_EL_LEVEL; /** \brief * */ static const Flag CALL_EL_LEVEL; /** \brief * */ static const Flag CALL_MG_LEVEL; protected: bool findElementAtPointRecursive(ElInfo *elinfo, const DimVec& lambda, int outside, ElInfo *final_el_info); protected: /** \brief * maximal number of DOFs at one position */ static const int MAX_DOF; /** \brief * Name of this Mesh */ std::string name; /** \brief * Dimension of this Mesh. Doesn't have to be equal to dimension of world. */ int dim; /** \brief * Number of vertices in this Mesh */ int nVertices; /** \brief * Number of Edges in this Mesh */ int nEdges; /** \brief * Number of leaf elements in this Mesh */ int nLeaves; /** \brief * Total number of elements in this Mesh */ int nElements; /** \brief * Number of faces in this Mesh */ int nFaces; /** \brief * Maximal number of elements that share one edge; used to allocate memory * to store pointers to the neighbour at the refinement/coarsening edge * (only 3d); */ int maxEdgeNeigh; /** \brief * Diameter of the mesh in the DIM_OF_WORLD directions */ WorldVector diam; /** \brief * Is pointer to NULL if mesh contains no parametric elements else pointer * to a Parametric object containing coefficients of the parameterization * and related information */ Parametric *parametric; /** \brief * If the value is non zero then preserve all DOFs on all levels (can * be used for multigrid, e.g.); otherwise all DOFs on the parent that are * not handed over to a child are removed during refinement and added again * on the parent during coarsening. */ bool preserveCoarseDOFs; /** \brief * Number of all DOFs on a single element */ int nDOFEl; /** \brief * Number of DOFs at the different positions VERTEX, EDGE, (FACE,) CENTER on * an element: * * - nDOF[VERTEX]: number of DOFs at a vertex (>= 1) * * - nDOF[EDGE]: number of DOFs at an edge; if no DOFs are associated to * edges, then this value is 0 * * - nDOF[FACE]: number of DOFs at a face; if no DOFs are associated to * faces, then this value is 0 (only 3d) * * - nDOF[CENTER]: number of DOFs at the barycenter; if no DOFs are * associated to the barycenter, then this value is 0 */ DimVec nDOF; /** \brief * Number of nodes on a single element where DOFs are located; needed for * the (de-) allocation of the dof-vector on the element (\ref Element::dof); */ int nNodeEl; /** \brief * Gives the index of the first node at vertex, edge, face (only 3d), and * barycenter: * * - node[VERTEX]: has always value 0; dof[0],...,dof[N_VERTICES-1] are * always DOFs at the vertices; * * - node[EDGE]: dof[node[EDGE]],..., dof[node[EDGE]+N_EDGES-1] are the DOFs * at the N_EDGES edges, if DOFs are located at edges; * * - node[FACE]: dof[node[FACE]],..., dof[node[FACE]+N_FACES-1] are the DOFs * at the N_FACES faces, if DOFs are located at faces (only 3d); * * - node[CENTER]: dof[node[CENTER]] are the DOFs at the barycenter, if DOFs * are located at the barycenter; */ DimVec node; /** \brief * list of all DOFAdmins */ std::vector admin; /** \brief * List of all MacroElements of this Mesh */ std::deque macroElements; /** \brief * Needed during DOF compression (\ref DOFAdmin::compress). */ std::vector newDOF; /** \brief * Needed during DOF compression (\ref DOFAdmin::compress). */ static DOFAdmin *compressAdmin; /** \brief * Used for recursive mesh traversal. Static pointer to the mesh * that should be traversed. This allows access to the mesh even * from the static traverse routines */ static Mesh* traversePtr; /** \brief * Used by compress- and check functions. Number of the current DOFAdmin */ static int iadmin; /** \brief * Used by check functions */ static std::vector dof_used; /** \brief * */ static std::map serializedDOFs; /** \brief * Used while mesh refinement. To create new elements * elementPrototype->clone() is called, which returns a Element of the * same type as elementPrototype. So e.g. Elements of the different * dimensions can be created in a uniform way. */ Element* elementPrototype; /** \brief * Prototype for leaf data. Used for creation of new leaf data while * refinement. */ ElementData* elementDataPrototype; /** \brief * Used for enumeration of all mesh elements */ int elementIndex; /** \brief * True if the mesh is already initialized, false otherwise. */ bool initialized; /** \brief * Map of managed periodic vertex associations. */ std::map periodicAssociations; /** \brief * If the mesh has been created by reading a macro file, here * the information are stored about the content of the file. */ MacroInfo *macroFileInfo_; protected: /** \brief * for findElement-Fcts */ DimVec final_lambda; /** \brief * */ const WorldVector *g_xy0, *g_xy; /** \brief * */ double *g_sp; friend class MacroInfo; friend class MacroReader; friend class MacroWriter; friend class MacroElement; friend class Element; friend void Element::newDOFFct1(const DOFAdmin*); friend void Element::newDOFFct2(const DOFAdmin*); }; } #endif // AMDIS_MESH_H