-
Thomas Witkowski authoredThomas Witkowski authored
Element.h 17.48 KiB
// ============================================================================
// == ==
// == AMDiS - Adaptive multidimensional simulations ==
// == ==
// ============================================================================
// == ==
// == crystal growth group ==
// == ==
// == Stiftung caesar ==
// == Ludwig-Erhard-Allee 2 ==
// == 53175 Bonn ==
// == germany ==
// == ==
// ============================================================================
// == ==
// == http://www.caesar.de/cg/AMDiS ==
// == ==
// ============================================================================
/** \file Element.h */
#ifndef AMDIS_ELEMENT_H
#define AMDIS_ELEMENT_H
// ============================================================================
// ===== includes =============================================================
// ============================================================================
#include "Global.h"
#include "RefinementManager.h"
#include "Serializable.h"
#include "ElementData.h"
#include "LeafData.h"
namespace AMDiS {
// ============================================================================
// ===== forward declarations =================================================
// ============================================================================
class Mesh;
class DOFAdmin;
template<typename T> class WorldVector;
class CoarseningManager;
template<typename T, GeoIndex d> class FixVec;
#define AMDIS_UNDEFINED 5
// ============================================================================
// ===== class Element ========================================================
// ============================================================================
/** \ingroup Triangulation
* \brief
* Base class for Line, Triangle, Tetrahedron
*
* Elements in AMDiS are always simplices (a simplex is a Line in 1d, a
* Triangle in 2d and a Tetrahedron in 3d).
* We restrict ourselves here to simplicial meshes, for several reasons:
* -# A simplex is one of the most simple geometric types and complex domains
* may be approximated by a set of simplices quite easily.
* -# Simplicial meshes allow local refinement without the need of
* nonconforming meshes (hanging nodes), parametric elements, or mixture of
* element types (which is the case for quadrilateral meshes).
* -# Polynomials of any degree are easily represented on a simplex using
* local (barycentric) coordinates.
*
* A Line element and its refinement:
*
* <img src="line.png">
*
* A Triangle element and its refinement:
*
* <img src="triangle.png">
*
* A Tetrahedron element and its refinements:
*
* <img src="tetrahedron.png">
*/
class Element : public Serializable
{
private:
/** \brief
* private standard constructor because an Element must know his Mesh
*/
Element() {};
public:
/** \brief
* constructs an Element which belongs to Mesh
*/
Element(Mesh *);
/** \brief
* copy constructor
*/
Element(const Element& old);
/** \brief
* destructor
*/
virtual ~Element();
/** \brief
* Clone this Element and return a reference to it. Because also the DOFs
* are cloned, \ref Mesh::serializedDOfs must be used.
*/
Element* cloneWithDOFs();
// ===== getting methods ======================================================
/** \name getting methods
* \{
*/
/** \brief
* Returns \ref child[0]
*/
inline Element* getFirstChild() const {
return child[0];
}
/** \brief
* Returns \ref child[1]
*/
inline Element* getSecondChild() const {
return child[1];
}
/** \brief
* Returns \ref child[i], i=0,1
*/
inline Element* getChild(int i) const {
TEST_EXIT_DBG(i==0 || i==1)("i must be 0 or 1\n");
return child[i];
}
/** \brief
* Returns true if Element is a leaf element (\ref child[0] == NULL), returns
* false otherwise.
*/
inline const bool isLeaf() const {
return (child[0] == NULL);
}
/** \brief
* Returns \ref dof[i][j] which is the j-th DOF of the i-th node of Element.
*/
const DegreeOfFreedom getDOF(int i, int j) const {
return dof[i][j];
}
/** \brief
* Returns \ref dof[i] which is a pointer to the DOFs of the i-th node.
*/
const DegreeOfFreedom* getDOF(int i) const {
return dof[i];
}
/** \brief
* Returns a pointer to the DOFs of this Element
*/
const DegreeOfFreedom** getDOF() const {
return const_cast<const DegreeOfFreedom**>(dof);
}
/** \brief
* Returns \ref mesh of Element
*/
inline Mesh* getMesh() const {
return mesh;
}
/** \brief
* Returns \ref elementData's error estimation, if Element is a leaf element
* and has leaf data.
*/
inline double getEstimation(int row) const
{
if (isLeaf()) {
TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
ElementData *ld = elementData->getElementData(ESTIMATABLE);
TEST_EXIT_DBG(ld)("leaf data not estimatable!\n");
return dynamic_cast<LeafDataEstimatableInterface*>(ld)->getErrorEstimate(row);
}
return 0.0;
}
/** \brief
* Returns Element's coarsening error estimation, if Element is a leaf
* element and if it has leaf data and if this leaf data are coarsenable.
*/
inline double getCoarseningEstimation(int row) {
if (isLeaf()) {
TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
ElementData *ld = elementData->getElementData(COARSENABLE);
TEST_EXIT_DBG(ld)("element data not coarsenable!\n");
return dynamic_cast<LeafDataCoarsenableInterface*>(ld)->getCoarseningErrorEstimate(row);
}
return 0.0;
}
/** \brief
* Returns region of element if defined, -1 else.
*/
int getRegion() const;
/** \brief
* Returns local vertex number of the j-th vertex of the i-th edge
*/
virtual int getVertexOfEdge(int i, int j) const = 0;
/** \brief
* Returns local vertex number of the vertexIndex-th vertex of the
* positionIndex-th part of type position (vertex, edge, face)
*/
virtual int getVertexOfPosition(GeoIndex position,
int positionIndex,
int vertexIndex) const = 0;
/** \brief
*
*/
virtual int getPositionOfVertex(int side, int vertex) const = 0;
/** \brief
*
*/
virtual int getEdgeOfFace(int face, int edge) const = 0;
/** \brief
* Returns the number of parts of type i in this element
*/
virtual int getGeo(GeoIndex i) const = 0;
/** \brief
* Returns Element's \ref mark
*/
inline const signed char getMark() const {
return mark;
}
/** \brief
* Returns \ref newCoord[i]
*/
double getNewCoord(int j) const;
/** \brief
* Returns Element's \ref index
*/
inline int getIndex() const {
return index;
}
/** \brief
* Returns \ref newCoord
*/
inline WorldVector<double>* getNewCoord() const {
return newCoord;
}
/** \} */
// ===== setting methods ======================================================
/** \name setting methods
* \{
*/
/** \brief
* Sets \ref child[0]
*/
virtual void setFirstChild(Element *aChild) {
child[0] = aChild;
}
/** \brief
* Sets \ref child[1]
*/
virtual void setSecondChild(Element *aChild) {
child[1] = aChild;
}
/** \brief
* Sets \ref elementData of Element
*/
void setElementData(ElementData* ed) {
elementData = ed;
}
/** \brief
* Sets \ref newCoord of Element. Needed by refinement, if Element has a
* boundary edge on a curved boundary.
*/
inline void setNewCoord(WorldVector<double>* coord) {
newCoord = coord;
}
/** \brief
* Sets \ref mesh.
*/
inline void setMesh(Mesh *m) {
mesh = m;
}
/** \brief
* Sets the pointer to the DOFs of the i-th node of Element
*/
DegreeOfFreedom* setDOF(int pos, DegreeOfFreedom* p) {
dof[pos] = p;
return dof[pos];
}
/** \brief
* Checks whether Element is a leaf element and whether it has leaf data.
* If the checks don't fail, leaf data's error estimation is set to est.
*/
inline void setEstimation(double est, int row)
{
if (isLeaf()) {
TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
ElementData *ld = elementData->getElementData(ESTIMATABLE);
TEST_EXIT_DBG(ld)("leaf data not estimatable\n");
dynamic_cast<LeafDataEstimatableInterface*>(ld)->
setErrorEstimate(row, est);
} else {
ERROR_EXIT("setEstimation only for leaf elements!\n");
}
}
/** \brief
* Sets Element's coarsening error estimation, if Element is a leaf element
* and if it has leaf data and if this leaf data are coarsenable.
*/
inline void setCoarseningEstimation(double est, int row)
{
if (isLeaf()) {
TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
ElementData *ld = elementData->getElementData(COARSENABLE);
TEST_EXIT_DBG(ld)("leaf data not coarsenable\n");
dynamic_cast<LeafDataCoarsenableInterface*>(ld)->
setCoarseningErrorEstimate(row, est);
} else {
ERROR_EXIT("setEstimation only for leaf elements!\n");
}
}
/** \brief
* Sets Elements \ref mark = mark + 1;
*/
inline void incrementMark() {
mark++;
}
/** \brief
* Sets Elements \ref mark = mark - 1;
*/
inline void decrementMark() {
if (0 < mark)
mark--;
}
/** \brief
* Sets Element's \ref mark
*/
inline void setMark(signed char m) {
mark = m;
}
/** \} */
// ===== pure virtual methods =================================================
/** \name pure virtual methods
* \{
*/
/** \brief
* orient the vertices of edges/faces.
* Used by Estimator for the jumps => same quadrature nodes from both sides!
*/
virtual const FixVec<int,WORLD>&
sortFaceIndices(int face, FixVec<int,WORLD> *vec) const = 0;
/** \brief
* Returns a copy of itself. Needed by Mesh to create Elements by a
* prototype.
*/
virtual Element *clone() = 0;
/** \brief
* Returns which side of child[childnr] corresponds to side sidenr of
* this Element. If the child has no corresponding
* side, the return value is negative. *isBisected is true after the
* function call, if the side of the child is only a part of element's
* side, false otherwise.
*/
virtual int getSideOfChild(int childnr, int sidenr, int elType = 0) const = 0;
/** \brief
* Returns which vertex of elements parent corresponds to the vertexnr of
* the element, if the element is the childnr-th child of the parent.
* If the vertex is the ner vertex at the refinement edge, -1 is returned.
*/
virtual int getVertexOfParent(int childnr, int vertexnr, int elType = 0) const = 0;
/** \brief
* Returns whether Element is a Line
*/
virtual bool isLine() const = 0;
/** \brief
* Returns whether Element is a Triangle
*/
virtual bool isTriangle() const = 0;
/** \brief
* Returns whether Element is a Tetrahedron
*/
virtual bool isTetrahedron() const = 0;
/** \brief
* Returns whether Element has sideElem as one of its sides.
*/
virtual bool hasSide(Element *sideElem) const = 0;
/** \} */
// ===== other public methods =================================================
/** \brief
* assignment operator
*/
Element& operator=(const Element& el);
/** \brief
* Checks whether the face with vertices dof[0],..,dof[DIM-1] is
* part of mel's boundary. returns the opposite vertex if true, -1 else
*/
int oppVertex(FixVec<DegreeOfFreedom*, DIMEN> pdof) const;
/** \brief
* Refines Element's leaf data
*/
inline void refineElementData(Element* child1, Element* child2, int elType = 0) {
if (elementData) {
bool remove = elementData->refineElementData(this, child1, child2, elType);
if (remove) {
ElementData *tmp = elementData->getDecorated();
DELETE elementData;
elementData = tmp;
}
}
}
/** \brief
* Coarsens Element's leaf data
*/
inline void coarsenElementData(Element* child1, Element* child2, int elType=0) {
ElementData *childData;
childData = child1->getElementData();
if (childData) {
childData->coarsenElementData(this, child1, child2, elType);
DELETE childData;
child1->setElementData(NULL);
}
childData = child2->getElementData();
if (childData) {
childData->coarsenElementData(this, child2, child1, elType);
DELETE childData;
child2->setElementData(NULL);
}
}
/** \brief
* Returns pointer to \ref elementData
*/
inline ElementData* getElementData() const {
return elementData;
}
/** \brief
*
*/
inline ElementData* getElementData(int typeID) const {
if (elementData) {
return elementData->getElementData(typeID);
}
return NULL;
}
/** \brief
* kills \ref elementData
*/
bool deleteElementData(int typeID) {
FUNCNAME("Element::deleteElementData()");
if (elementData) {
if (elementData->isOfType(typeID)) {
ElementData *tmp = elementData;
elementData = elementData->getDecorated();
DELETE tmp;
return true;
} else {
return elementData->deleteDecorated(typeID);
}
}
return false;
}
/** \brief
* Returns whether element is refined at side side
* el1, el2 are the corresponding children.
* (not neccessarly the direct children!)
* elementTyp is the type of this element (comes from ElInfo)
*/
bool isRefinedAtSide(int side, Element *el1, Element *el2,
unsigned char elementTyp = 255);
/** \brief
* Returns whether Element's \ref newCoord is set
*/
inline bool isNewCoordSet() const {
return (newCoord != NULL);
}
/** \brief
* Frees memory for \ref newCoord
*/
void eraseNewCoord();
// ===== Serializable implementation =====
void serialize(std::ostream &out);
void deserialize(std::istream &in);
int calcMemoryUsage();
// ===== protected methods ====================================================
protected:
/** \brief
* Sets Element's \ref dof pointer. Used by friend class Mesh.
*/
void setDOFPtrs();
/** \brief
* Sets Element's \ref index. Used by friend class Mesh.
*/
inline void setIndex(int i) {
index = i;
}
/** \brief
* Used by friend class Mesh while dofCompress
*/
void newDOFFct1(const DOFAdmin*);
/** \brief
* Used by friend class Mesh while dofCompress
*/
void newDOFFct2(const DOFAdmin*);
protected:
/** \brief
* Pointers to the two children of interior elements of the tree. Pointers
* to NULL for leaf elements.
*/
Element *child[2];
/** \brief
* Vector of pointers to DOFs. These pointers must be available for elements
* vertices (for the geometric description of the mesh). There my be pointers
* for the edges, for faces and for the center of an element. They are
* ordered the following way: The first N_VERTICES entries correspond to the
* DOFs at the vertices of the element. The next ones are those at the edges,
* if present, then those at the faces, if present, and then those at the
* barycenter, if present.
*/
DegreeOfFreedom **dof;
/** \brief
* Unique global index of the element. these indices are not strictly ordered
* and may be larger than the number of elements in the binary tree (the list
* of indices may have holes after coarsening).
*/
int index;
/** \brief
* Marker for refinement and coarsening. if mark is positive for a leaf
* element, this element is refined mark times. if mark is negative for
* a leaf element, this element is coarsened -mark times.
*/
signed char mark;
/** \brief
* If the element has a boundary edge on a curved boundary, this is a pointer
* to the coordinates of the new vertex that is created due to the refinement
* of the element, otherwise it is a NULL pointer. Thus coordinate
* information can be also produced by the traversal routines in the case of
* curved boundary.
*/
WorldVector<double> *newCoord;
/** \brief
* Pointer to the Mesh this element belongs to
*/
Mesh* mesh;
/** \brief
* Pointer to Element's leaf data
*/
ElementData* elementData;
friend class Mesh;
};
}
#endif // AMDIS_ELEMENT_H