// ============================================================================
// == ==
// == 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();
int calcMemoryUsage();
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