Element.h 17 KB
Newer Older
1
2
3
4
5
6
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
7
// ==  TU Dresden                                                            ==
8
// ==                                                                        ==
9
10
11
// ==  Institut fr Wissenschaftliches Rechnen                               ==
// ==  Zellescher Weg 12-14                                                  ==
// ==  01069 Dresden                                                         ==
12
13
14
15
// ==  germany                                                               ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
16
// ==  https://gforge.zih.tu-dresden.de/projects/amdis/                      ==
17
18
19
20
21
22
23
24
25
26
27
28
29
// ==                                                                        ==
// ============================================================================

/** \file Element.h */

#ifndef AMDIS_ELEMENT_H
#define AMDIS_ELEMENT_H

#include "Global.h"
#include "RefinementManager.h"
#include "Serializable.h"
#include "ElementData.h"
#include "LeafData.h"
30
#include "AMDiS_fwd.h"
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

namespace AMDiS {

  template<typename T, GeoIndex d> class FixVec;

#define AMDIS_UNDEFINED  5

  /** \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:
68
    /// private standard constructor because an Element must know his Mesh
69
    Element() {}
70

71
  public:
72
    /// constructs an Element which belongs to Mesh
73
74
    Element(Mesh *);

75
    /// copy constructor
76
77
    Element(const Element& old);

78
    /// destructor
79
80
    virtual ~Element();

81
    ///
82
83
    void deleteElementDOFs();

84
85
86
87
88
89
    /** \brief
     * Clone this Element and return a reference to it. Because also the DOFs
     * are cloned, \ref Mesh::serializedDOfs must be used.
     */
    Element* cloneWithDOFs();

90
91
92
93
    /** \name getting methods
     * \{
     */

94
    /// Returns \ref child[0]
Thomas Witkowski's avatar
Thomas Witkowski committed
95
96
    inline Element* getFirstChild() const 
    {
97
      return child[0];
98
    }
99

100
    /// Returns \ref child[1]
Thomas Witkowski's avatar
Thomas Witkowski committed
101
102
    inline Element* getSecondChild() const 
    {
103
      return child[1];
104
    }
105

106
    /// Returns \ref child[i], i=0,1
Thomas Witkowski's avatar
Thomas Witkowski committed
107
108
    inline Element* getChild(int i) const 
    {
109
      TEST_EXIT_DBG(i==0 || i==1)("i must be 0 or 1\n");
110
      return child[i];
111
    }
112
113
114
115
116

    /** \brief
     * Returns true if Element is a leaf element (\ref child[0] == NULL), returns
     * false otherwise.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
117
118
    inline const bool isLeaf() const 
    { 
119
      return (child[0] == NULL); 
120
    }
121

122
    /// Returns \ref dof[i][j] which is the j-th DOF of the i-th node of Element.
Thomas Witkowski's avatar
Thomas Witkowski committed
123
124
    const DegreeOfFreedom getDOF(int i, int j) const 
    { 
125
      return dof[i][j];
126
    }
127

128
    /// Returns \ref dof[i] which is a pointer to the DOFs of the i-th node.
Thomas Witkowski's avatar
Thomas Witkowski committed
129
130
    const DegreeOfFreedom* getDOF(int i) const 
    {
131
      return dof[i];
132
    }
133

134
    /// Returns a pointer to the DOFs of this Element
Thomas Witkowski's avatar
Thomas Witkowski committed
135
136
    const DegreeOfFreedom** getDOF() const 
    {
137
      return const_cast<const DegreeOfFreedom**>(dof);
138
    }
139

140
    /// Returns \ref mesh of Element
Thomas Witkowski's avatar
Thomas Witkowski committed
141
142
    inline Mesh* getMesh() const 
    { 
143
      return mesh; 
144
    }
145
146
147
148
149
150
151

    /** \brief
     * Returns \ref elementData's error estimation, if Element is a leaf element
     * and has leaf data. 
     */
    inline double getEstimation(int row) const
    {
152
      if (isLeaf()) {
153
	TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
154
	ElementData *ld = elementData->getElementData(ESTIMATABLE);
155
	TEST_EXIT_DBG(ld)("leaf data not estimatable!\n");
156

157
158
159
160
	return dynamic_cast<LeafDataEstimatableInterface*>(ld)->getErrorEstimate(row);
      }	
      
      return 0.0;
161
    }
162
163
164
165
166

    /** \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.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
167
168
    inline double getCoarseningEstimation(int row) 
    {
169
      if (isLeaf()) {
170
	TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
171
	ElementData *ld = elementData->getElementData(COARSENABLE);
172
	TEST_EXIT_DBG(ld)("element data not coarsenable!\n");
173

174
	return dynamic_cast<LeafDataCoarsenableInterface*>(ld)->getCoarseningErrorEstimate(row);
175
      }
176
177
      
      return 0.0;
178
    }
179

180
    /// Returns region of element if defined, -1 else.
181
182
    int getRegion() const;

183
    /// Returns local vertex number of the j-th vertex of the i-th edge
184
185
186
187
188
189
190
    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,
191
192
				    int positionIndex,
				    int vertexIndex) const = 0;
193

194
    ///
195
196
    virtual int getPositionOfVertex(int side, int vertex) const = 0;

197
    ///
198
199
    virtual int getEdgeOfFace(int face, int edge) const = 0;

200
    /// Returns the number of parts of type i in this element
201
202
    virtual int getGeo(GeoIndex i) const = 0;

203
    /// Returns Element's \ref mark
Thomas Witkowski's avatar
Thomas Witkowski committed
204
205
    inline const signed char getMark() const 
    { 
206
      return mark;
207
    }
208

209
    /// Returns \ref newCoord[i]
Thomas Witkowski's avatar
Thomas Witkowski committed
210
211
    inline double getNewCoord(int i) const 
    {
212
213
214
	TEST_EXIT_DBG(newCoord)("newCoord = NULL\n");
	return (*newCoord)[i];
    }
215

216
    /// Returns Element's \ref index
Thomas Witkowski's avatar
Thomas Witkowski committed
217
218
    inline int getIndex() const 
    { 
219
      return index; 
220
    }
221

222
    /// Returns \ref newCoord
Thomas Witkowski's avatar
Thomas Witkowski committed
223
224
    inline WorldVector<double>* getNewCoord() const 
    { 
225
      return newCoord; 
226
    }
227
228
229
230
231
232
233

    /** \} */

    /** \name setting methods
     * \{
     */

234
    /// Sets \ref child[0]
Thomas Witkowski's avatar
Thomas Witkowski committed
235
236
    virtual void setFirstChild(Element *aChild) 
    {
237
      child[0] = aChild;
238
    }
239

240
    /// Sets \ref child[1]
Thomas Witkowski's avatar
Thomas Witkowski committed
241
242
    virtual void setSecondChild(Element *aChild) 
    {
243
      child[1] = aChild;
244
    }
245

246
    /// Sets \ref elementData of Element
Thomas Witkowski's avatar
Thomas Witkowski committed
247
248
    void setElementData(ElementData* ed) 
    {
249
      elementData = ed;
250
    }
251
252
253
254
255

    /** \brief
     * Sets \ref newCoord of Element. Needed by refinement, if Element has a
     * boundary edge on a curved boundary.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
256
257
    inline void setNewCoord(WorldVector<double>* coord) 
    {
258
      newCoord = coord;
259
    }
260

261
    /// Sets \ref mesh.
Thomas Witkowski's avatar
Thomas Witkowski committed
262
263
    inline void setMesh(Mesh *m) 
    {
264
      mesh = m;
265
    }
266

267
    /// Sets the pointer to the DOFs of the i-th node of Element
Thomas Witkowski's avatar
Thomas Witkowski committed
268
269
    DegreeOfFreedom* setDOF(int pos, DegreeOfFreedom* p) 
    {
270
271
      dof[pos] = p;
      return dof[pos];
272
    }
273
274
275
276
277
278
279

    /** \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)
    {
280
      if (isLeaf()) {
281
	TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
282
	ElementData *ld = elementData->getElementData(ESTIMATABLE);
283
	TEST_EXIT_DBG(ld)("leaf data not estimatable\n");
284
285
286

	dynamic_cast<LeafDataEstimatableInterface*>(ld)->
	  setErrorEstimate(row, est);
287
      } else {
288
289
	ERROR_EXIT("setEstimation only for leaf elements!\n");
      }
290
    }
291
292
293
294
295
296
297

    /** \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)
    {
298
      if (isLeaf()) {
299
	TEST_EXIT_DBG(elementData)("leaf element without leaf data\n");
300
	ElementData *ld = elementData->getElementData(COARSENABLE);
301
	TEST_EXIT_DBG(ld)("leaf data not coarsenable\n");
302
303
304

	dynamic_cast<LeafDataCoarsenableInterface*>(ld)->
	  setCoarseningErrorEstimate(row, est);
305
      } else {
306
307
	ERROR_EXIT("setEstimation only for leaf elements!\n");
      }
308
    }
309

310
    /// Sets Elements \ref mark = mark + 1;
Thomas Witkowski's avatar
Thomas Witkowski committed
311
312
    inline void incrementMark() 
    {
313
314
      mark++;
    }
315

316
    /// Sets Elements \ref mark = mark - 1;
Thomas Witkowski's avatar
Thomas Witkowski committed
317
318
    inline void decrementMark() 
    {
319
320
      if (0 < mark) 
	mark--;
321
    }
322

323
    /// Sets Element's \ref mark
Thomas Witkowski's avatar
Thomas Witkowski committed
324
325
    inline void setMark(signed char m) 
    {
326
      mark = m;
327
    }
328
329
330
331
332
333
334
335
336
337
338
339
340

    /** \} */


    /** \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>& 
341
      sortFaceIndices(int face, FixVec<int, WORLD> *vec) const = 0;
342

343
    /// Returns a copy of itself. Needed by Mesh to create Elements by a prototype. 
344
345
346
    virtual Element *clone() = 0;

    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
347
348
349
350
     * 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. 
351
352
353
354
355
356
357
358
359
360
     */
    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;

361
    /// Returns whether Element is a Line
362
363
    virtual bool isLine() const = 0;

364
    /// Returns whether Element is a Triangle
365
366
    virtual bool isTriangle() const = 0;

367
    /// Returns whether Element is a Tetrahedron
368
369
    virtual bool isTetrahedron() const = 0;

370
    /// Returns whether Element has sideElem as one of its sides.
371
372
    virtual bool hasSide(Element *sideElem) const = 0;

373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
    /** \brief
     * Traverses an edge of a given element (this includes also all children of the
     * element having the same edge). All vertex dofs alonge this edge are assembled 
     * and put together to a list.
     *
     * \param[in]  feSpace         FE space which is used to get the dofs.
     * \param[in]  ithEdge         Defines the edge on which all the vertex dofs
     *                             are assembled.
     * \param[out] dofs            List of dofs, where the result is stored.
     * \param[in]  parentVertices  If true, also the two vertices of the parent
     *                             element are put into the result list.
     */
    virtual void getVertexDofs(FiniteElemSpace* feSpace, int ithEdge, 
			       DofContainer& dofs, bool parentVertices = 0) const = 0;

    /** \brief
     * Traverses an edge of a given element (this includes also all children of the
     * element having the same edge). All non vertex dofs alonge this edge are 
     * assembled and put together to a list.
     *
     * \param[in]  feSpace         FE space which is used to get the dofs.
     * \param[in]  ithEdge         Defines the edge on which all the non vertex
     *                             dofs are assembled.
     * \param[out] dofs            All dofs are put to this dof list.
     */
    virtual void getNonVertexDofs(FiniteElemSpace* feSpace, int ithEdge, 
				  DofContainer& dofs) const = 0;


402
403
404
405
    /** \} */

    // ===== other public methods =================================================

406
    /// assignment operator
407
    Element& operator=(const Element& el);
408
409
410
411
412
413
414

    /** \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;

415
    /// Refines Element's leaf data
Thomas Witkowski's avatar
Thomas Witkowski committed
416
417
    inline void refineElementData(Element* child1, Element* child2, int elType = 0) 
    {
418
419
420
      if (elementData) {
	bool remove = elementData->refineElementData(this, child1, child2, elType);
	if (remove) {
421
	  ElementData *tmp = elementData->getDecorated();
Thomas Witkowski's avatar
Thomas Witkowski committed
422
	  delete elementData;
423
424
425
	  elementData = tmp;
	}
      }
426
    }
427

428
    /// Coarsens Element's leaf data
Thomas Witkowski's avatar
Thomas Witkowski committed
429
430
    inline void coarsenElementData(Element* child1, Element* child2, int elType = 0) 
    {
431
432
      ElementData *childData;
      childData = child1->getElementData();
433
      if (childData) {
434
	childData->coarsenElementData(this, child1, child2, elType);
Thomas Witkowski's avatar
Thomas Witkowski committed
435
	delete childData;
436
437
438
	child1->setElementData(NULL);
      }
      childData = child2->getElementData();
439
      if (childData) {
440
	childData->coarsenElementData(this, child2, child1, elType);
Thomas Witkowski's avatar
Thomas Witkowski committed
441
	delete childData;
442
443
	child2->setElementData(NULL);
      }
444
    }
445

446
    /// Returns pointer to \ref elementData
Thomas Witkowski's avatar
Thomas Witkowski committed
447
448
    inline ElementData* getElementData() const 
    {
449
      return elementData;
450
    }
451

452
    ///
Thomas Witkowski's avatar
Thomas Witkowski committed
453
454
455
    inline ElementData* getElementData(int typeID) const 
    {
      if (elementData)
456
	return elementData->getElementData(typeID);
Thomas Witkowski's avatar
Thomas Witkowski committed
457

458
      return NULL;
459
    }
460

461
    /// Deletes the \ref elementData with a specific typeID.
462
    bool deleteElementData(int typeID);
463
464
465
466
467
468
469
470

    /** \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, 
471
			 unsigned char elementTyp = 255);
472

473
    /// Returns whether Element's \ref newCoord is set
Thomas Witkowski's avatar
Thomas Witkowski committed
474
475
    inline bool isNewCoordSet() const 
    { 
476
      return (newCoord != NULL);
477
    }
478

479
    /// Frees memory for \ref newCoord
480
    void eraseNewCoord();
481
482
 
    /// Serialize the element to a file.
483
    void serialize(std::ostream &out);
484

485
    /// Deserialize an element from a file.
486
    void deserialize(std::istream &in);
487

488
    ///
489
490
    int calcMemoryUsage();

491
  protected:
492
    /// Sets Element's \ref dof pointer. Used by friend class Mesh.
493
494
    void setDOFPtrs();
  
495
    /// Sets Element's \ref index. Used by friend class Mesh.
Thomas Witkowski's avatar
Thomas Witkowski committed
496
497
    inline void setIndex(int i) 
    {
498
      index = i;
499
    }
500

501
    /// Used by friend class Mesh while dofCompress
502
503
    void newDOFFct1(const DOFAdmin*);

504
    /// Used by friend class Mesh while dofCompress
505
506
507
508
509
510
511
    void newDOFFct2(const DOFAdmin*);

  protected:
    /** \brief
     * Pointers to the two children of interior elements of the tree. Pointers
     * to NULL for leaf elements.
     */
512
    Element *child[2];
513
514
515
516
517

    /** \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 
518
519
520
     * 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 
521
522
     * barycenter, if present.
     */
523
    DegreeOfFreedom **dof;
524
525
526
527
528
529

    /** \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).
     */
530
    int index;
531
532
533
534
535
536

    /** \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.
     */
537
    signed char mark;
538
539
540
541
542
 
    /** \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 
543
544
     * information can be also produced by the traversal routines in the case of 
     * curved boundary.
545
546
547
     */
    WorldVector<double> *newCoord;

548
    /// Pointer to the Mesh this element belongs to
549
    Mesh* mesh;
550

551
    /// Pointer to Element's leaf data
552
    ElementData* elementData;
553

554
555
556
557
558
559
    /** \brief
     * This map is used for deletion of all DOFs of all elements of a mesh. Once
     * a DOF-vector (all DOFS at a node, edge, etc.) is deleted, its address is
     * added to this map to note not to delete it a second time.
     */
    static std::map<DegreeOfFreedom*, bool> deletedDOFs;
560
561
562
563
564
565
566
567

    friend class Mesh;
  };

}

#endif  // AMDIS_ELEMENT_H