ElementObjectDatabase.h 19.2 KB
Newer Older
Thomas Witkowski's avatar
Thomas Witkowski committed
1
2
3
4
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
5
// ==  http://www.amdis-fem.org                                              ==
Thomas Witkowski's avatar
Thomas Witkowski committed
6
7
// ==                                                                        ==
// ============================================================================
8
9
10
11
12
13
14
15
16
17
18
19
//
// Software License for AMDiS
//
// Copyright (c) 2010 Dresden University of Technology 
// All rights reserved.
// Authors: Simon Vey, Thomas Witkowski et al.
//
// This file is part of AMDiS
//
// See also license.opensource.txt in the distribution.


Thomas Witkowski's avatar
Thomas Witkowski committed
20

21
/** \file ElementObjectDatabase.h */
Thomas Witkowski's avatar
Thomas Witkowski committed
22

23
24
#ifndef AMDIS_ELEMENT_OBJECT_DATABASE_H
#define AMDIS_ELEMENT_OBJECT_DATABASE_H
Thomas Witkowski's avatar
Thomas Witkowski committed
25
26
27
28
29

#include <map>
#include <vector>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
30
#include <boost/container/flat_map.hpp>
Thomas Witkowski's avatar
Thomas Witkowski committed
31

32
#include "AMDiS_fwd.h"
33
#include "Containers.h"
Thomas Witkowski's avatar
Thomas Witkowski committed
34
35
#include "Global.h"
#include "Boundary.h"
36
#include "Serializer.h"
37
#include "FiniteElemSpace.h"
Thomas Witkowski's avatar
Thomas Witkowski committed
38
39
40

namespace AMDiS {

41
42
  using namespace std;

43
44
  using boost::container::flat_map;

45
  /// Just to templatize the typedef.
46
  template<typename T>
47
  struct PerBoundMap {
48
49
50
51
    typedef map<pair<T, T>, BoundaryType> type;
    typedef typename type::iterator iterator;
  };

52

53
54
#pragma pack(push)
#pragma pack(1)
55
  /// Defines one element object. This may be either a vertex, edge or face.
Thomas Witkowski's avatar
Thomas Witkowski committed
56
  struct ElementObjectData {
57
    ElementObjectData(int a = -1, int b = 0)
Thomas Witkowski's avatar
Thomas Witkowski committed
58
      : elIndex(a),
59
	ithObject(b)
Thomas Witkowski's avatar
Thomas Witkowski committed
60
    {}
61
62

    /// Index of the element this object is part of.
Thomas Witkowski's avatar
Thomas Witkowski committed
63
64
    int elIndex;
    
65
    /// Index of the object within the element.
66
    char ithObject;
Thomas Witkowski's avatar
Thomas Witkowski committed
67

68
    /// Write this element object to disk.
69
    void serialize(ostream &out) const
70
71
72
73
74
    {
      SerUtil::serialize(out, elIndex);
      SerUtil::serialize(out, ithObject);
    }

75
    /// Read this element object from disk.
76
    void deserialize(istream &in)
77
78
79
80
81
    {
      SerUtil::deserialize(in, elIndex);
      SerUtil::deserialize(in, ithObject);
    }

82
    /// Compare this element object with another one.
83
84
    bool operator==(ElementObjectData& cmp) const
    {
85
      return (elIndex == cmp.elIndex && ithObject == cmp.ithObject);
86
87
    }

88
    /// Define a strict order on element objects.
89
90
    bool operator<(const ElementObjectData& rhs) const
    {
91
92
      return (elIndex < rhs.elIndex || 
	      (elIndex == rhs.elIndex && ithObject < rhs.ithObject));
93
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
94
  };
95
#pragma pack(pop)
Thomas Witkowski's avatar
Thomas Witkowski committed
96
97


98
99
  /** \brief
   * This class is a database of element objects. An element object is either a
100
101
102
103
104
105
106
   * vertex, edge or the face of a specific element. This database is used to
   * store all objects of all elements of a mesh. The information is stored in a
   * way that makes it possible to identify all elements, which have a given
   * vertex, edge or face in common. If is is known which element is owned by 
   * which rank in parallel computations, it is thus possible to get all interior
   * boundaries on object level. This is required, because two elements may share
   * a common vertex without beging neighbours in the definition of AMDiS.
107
   */
108
  class ElementObjectDatabase {
Thomas Witkowski's avatar
Thomas Witkowski committed
109
  public:
110
    ElementObjectDatabase()
111
112
      : feSpace(NULL),
	mesh(NULL),
113
114
	iterGeoPos(CENTER),
	macroElementRankMap(NULL),
115
116
	levelData(NULL)
    {}
Thomas Witkowski's avatar
Thomas Witkowski committed
117

118
    void setFeSpace(const FiniteElemSpace *fe)
Thomas Witkowski's avatar
Thomas Witkowski committed
119
    {
120
121
122
123
124
125
126
      feSpace = fe;
      mesh = feSpace->getMesh();
    }
  
    Mesh* getMesh()
    {
      return mesh;
127
128
    }

129
130
131
132
133
134
    /*
     * \param[in]  macroElementRankMap   Maps to each macro element of the mesh
     *                                   the rank that owns this macro element.
     */
    void create(map<int, int>& macroElementRankMap,
		MeshLevelData& levelData);
135

136
    void createMacroElementInfo(vector<MacroElement*> &mel);
137

138
139
140
    /// Create for a filled object database the membership information for all
    /// element objects. An object is owned by a rank, if the rank has the
    /// heighest rank number of all ranks where the object is part of.
141
    void updateRankData();
142

Thomas Witkowski's avatar
bla  
Thomas Witkowski committed
143
144
145
    /// All data from the database is dropped. 
    void clear();

146
147
148
149
150
151
    /// Resets iteration;
    bool resetIterator()
    {
      iterGeoPos = CENTER;
    }

152
    /** \brief
153
154
155
     * Iterates over all elements for one geometrical index, i.e., over all
     * vertices, edges or faces in the mesh. The function returns true, if the
     * result is valid. Otherwise the iterator is at the end position.
156
     *
157
158
     * \param[in]  pos   Must be either VERTEX, EDGE or FACE and defines the
     *                   elements that should be traversed.
159
     */
160
    inline bool iterate(GeoIndex pos)
Thomas Witkowski's avatar
Thomas Witkowski committed
161
    {
162
163
164
      // CENTER marks the variable "iterGeoPos" to be in an undefined state. I.e.,
      // there is no iteration that is actually running.

Thomas Witkowski's avatar
Thomas Witkowski committed
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
      if (iterGeoPos == CENTER) {
	iterGeoPos = pos;
	switch (iterGeoPos) {
	case VERTEX:
	  vertexIter = vertexInRank.begin();
	  break;
	case EDGE:
	  edgeIter = edgeInRank.begin();
	  break;
	case FACE:
	  faceIter = faceInRank.begin();
	  break;
	default:
	  ERROR_EXIT("Not GeoIndex %d!\n", iterGeoPos);
	}
      } else {
	switch (iterGeoPos) {
	case VERTEX:
	  ++vertexIter;
	  break;
	case EDGE:
	  ++edgeIter;
	  break;
	case FACE:
	  ++faceIter;
	  break;
	default:
	  ERROR_EXIT("Not GeoIndex %d!\n", iterGeoPos);
	}
      }

      switch (iterGeoPos) {
      case VERTEX:
	if (vertexIter == vertexInRank.end()) {
	  iterGeoPos = CENTER;
	  return false;
	}
	break;
      case EDGE:
	if (edgeIter == edgeInRank.end()) {
	  iterGeoPos = CENTER;
	  return false;
	}
	break;
      case FACE:
	if (faceIter == faceInRank.end()) {
	  iterGeoPos = CENTER;
	  return false;
	}
	break;
      default:
	ERROR_EXIT("Should not happen!\n");	
      }

      return true;
    }


223
    /// Returns the data of the current iterator position.
224
    flat_map<int, ElementObjectData>& getIterateData()
Thomas Witkowski's avatar
Thomas Witkowski committed
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    {
      switch (iterGeoPos) {
      case VERTEX:
	return vertexIter->second;
	break;
      case EDGE:
	return edgeIter->second;
	break;
      case FACE:
	return faceIter->second;
	break;
      default:
	ERROR_EXIT("Should not happen!\n");

	// Will never be reached, just to avoid compiler warnings.
	return faceIter->second;
      }
    }

244
    /// Returns the rank owner of the current iterator position.
245
    int getIterateOwner(int level);
Thomas Witkowski's avatar
Thomas Witkowski committed
246

247
248
249
250
251
252
253
254
255
    /// Returns the owner of a macro element vertex.
    int getOwner(DegreeOfFreedom vertex, int level);

    /// Returns the owner of a macro element edge.
    int getOwner(DofEdge edge, int level);
	
    /// Returns the owner of a macro element face.
    int getOwner(DofFace face, int level);

256
    /// Returns the rank owner of the current iterator position.
257
    int getIterateMaxLevel();
258

259
    /// Checks if a given vertex DOF is in a given rank.
260
261
262
263
264
    int isInRank(DegreeOfFreedom vertex, int rank)
    {
      return (vertexInRank[vertex].count(rank));
    }

265
    /// Checks if a given edge is in a given rank.
266
267
268
269
270
    int isInRank(DofEdge edge, int rank)
    {
      return (edgeInRank[edge].count(rank));
    }

271
    /// Checks if a given face is in a given rank.
272
273
274
275
276
277
    int isInRank(DofFace face, int rank)
    {
      return (faceInRank[face].count(rank));
    }


278
279
    /// Returns a vector with all macro elements that have a given vertex DOF 
    /// in common.
280
    vector<ElementObjectData>& getElements(DegreeOfFreedom vertex)
Thomas Witkowski's avatar
Thomas Witkowski committed
281
282
283
284
    {
      return vertexElements[vertex];
    }

285
    /// Returns a vector with all macro elements that have a given edge in common.
286
    vector<ElementObjectData>& getElements(DofEdge edge)
Thomas Witkowski's avatar
Thomas Witkowski committed
287
288
289
290
    {
      return edgeElements[edge];
    }

291
    /// Returns a vector with all macro elements that have a given face in common.
292
    vector<ElementObjectData>& getElements(DofFace face)
Thomas Witkowski's avatar
Thomas Witkowski committed
293
294
295
296
    {
      return faceElements[face];
    }

297

298
299
    /// Returns a vector with all macro elements that have a given vertex DOF 
    /// in common.
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
    vector<ElementObjectData>& getElementsVertex(int elIndex, int ithVertex)
    {
      ElementObjectData elObj(elIndex, ithVertex);
      DegreeOfFreedom vertex = vertexLocalMap[elObj];
      return vertexElements[vertex];
    }
    
    /// Returns a vector with all macro elements that have a given edge in common.
    vector<ElementObjectData>& getElementsEdge(int elIndex, int ithEdge)
    {
      ElementObjectData elObj(elIndex, ithEdge);
      DofEdge edge = edgeLocalMap[elObj];
      return edgeElements[edge];
    }

    /// Returns a vector with all macro elements that have a given face in common.
    vector<ElementObjectData>& getElementsFace(int elIndex, int ithFace)
    {
      ElementObjectData elObj(elIndex, ithFace);
      DofFace face = faceLocalMap[elObj];
      return faceElements[face];
    }

323
324
325
326
327
328
    /// Returns, for a given vertex, a map that maps from rank numbers to 
    /// element data objects, which identify on the rank the element which 
    /// contains this vertex. If more than one element in one subdomain contains
    /// the vertex, the element with the highest element index is given. If the
    /// vertex is not contained in a rank's subdomain, it will not be considered
    /// in this mapping.
329
    flat_map<int, ElementObjectData>& getElementsInRank(DegreeOfFreedom vertex)
330
331
332
333
    {
      return vertexInRank[vertex];
    }

334
335
336
337
338
339
    /// Returns, for a given edge, a map that maps from rank numbers to 
    /// element data objects, which identify on the rank the element which 
    /// contains this edge. If more than one element in one subdomain contains
    /// the edge, the element with the highest element index is given. If the
    /// edge is not contained in a rank's subdomain, it will not be considered
    /// in this mapping.
340
    flat_map<int, ElementObjectData>& getElementsInRank(DofEdge edge)
341
342
343
344
    {
      return edgeInRank[edge];
    }

345
346
347
348
    /// Returns, for a given face, a map that maps from rank numbers to 
    /// element data objects, which identify on the rank the element which 
    /// contains this face. If the face is not contained in a rank's subdomain, 
    /// it will not be considered in this mapping.
349
    flat_map<int, ElementObjectData>& getElementsInRank(DofFace face)
350
351
352
353
    {
      return faceInRank[face];
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
    /// Get degree of a DOF, thus the number of ranks which contain it.
    inline int getDegree(DegreeOfFreedom dof)
    {
      return vertexInRank[dof].size();
    }

    /// Get degree of an edge, thus the number of ranks which contain it.
    inline int getDegree(DofEdge edge)
    {
      return edgeInRank[edge].size();
    }

    /// Get degree of a face, thus the number of ranks which contain it.
    inline int getDegree(DofFace face)
    {
      return faceInRank[face].size();
    }

372
    /// Returns to an element object data the appropriate vertex DOF.
373
374
    DegreeOfFreedom getVertexLocalMap(ElementObjectData &data)
    {
375
376
      TEST_EXIT_DBG(vertexLocalMap.count(data))("Should not happen!\n");

377
378
379
      return vertexLocalMap[data];
    }

380
    /// Returns to an element object data the appropriate edge.
381
382
    DofEdge getEdgeLocalMap(ElementObjectData &data)
    {
383
384
      TEST_EXIT_DBG(edgeLocalMap.count(data))("Should not happen!\n");

385
386
387
      return edgeLocalMap[data];
    }

388
    /// Returns to an element object data the appropriate face.
389
390
    DofFace getFaceLocalMap(ElementObjectData &data)
    {
391
392
      TEST_EXIT_DBG(faceLocalMap.count(data))("Should not happen!\n");

393
394
395
      return faceLocalMap[data];
    }

396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
    PerBoundMap<DegreeOfFreedom>::type& getPeriodicVertices()
    {
      return periodicVertices;
    }

    PerBoundMap<DofEdge>::type& getPeriodicEdges()
    {
      return periodicEdges;
    }

    PerBoundMap<DofFace>::type& getPeriodicFaces()
    {
      return periodicFaces;
    }

411
412
    inline bool getEdgeReverseMode(ElementObjectData &obj0, 
				   ElementObjectData &obj1)
413
    {
414
415
416
      if (mesh->getDim() == 2)
	return true;

417
418
      if (edgeReverseMode.empty())
	return false;
419

420
      return static_cast<bool>(edgeReverseMode.count(make_pair(obj0, obj1)));
421
422
    }

423
424
    inline bool getFaceReverseMode(ElementObjectData &obj0, 
				   ElementObjectData &obj1)
425
    {
426
427
      if (faceReverseMode.empty())
	return false;
428

429
      return static_cast<bool>(faceReverseMode.count(make_pair(obj0, obj1)));
430
431
    }

432
433
434
435
436
437
    /// Returns true if there is periodic data.
    bool hasPeriodicData()
    {
      return (periodicVertices.size() != 0);
    }

438
439
440
441
442
443
444
445
    /// Returns true if the given boundary type is larger or equal to the smallest
    /// periodic boundary ID in mesh. See \ref smallestPeriodicBcType for more
    /// information.
    bool isValidPeriodicType(BoundaryType t) const
    {
      return (t >= smallestPeriodicBcType);
    }

446
447
448
449
450
451
452
453
454
455
    inline Element* getElementPtr(int index)
    {
      return macroElIndexMap[index];
    }

    inline int getElementType(int index)
    {
      return macroElIndexTypeMap[index];
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
456
457
458
459
460
461
462
    void setData(map<int, int> &rankMap,
		MeshLevelData& ld)
    {
      macroElementRankMap = &rankMap;
      levelData = &ld;
    }

463
    /// Write the element database to disk.
464
    void serialize(ostream &out);
465
466
    
    /// Read the element database from disk.
467
    void deserialize(istream &in);
468

469
470
471
    /// Returns the estimated memory usage of an object of this class.
    unsigned long calculateMemoryUsage();

472
  protected:
473
474
475
476
477
478
479
480
481
    /** \brief
     * Adds an element to the object database. If the element is part of a
     * periodic boundary, all information about subobjects of the element on
     * this boundary are collected.
     *
     * \param[in]  elInfo    ElInfo object of the element. 
     */
    void addElement(ElInfo *elInfo);

482
    /// Adds the i-th DOF vertex of an element to the object database.
Thomas Witkowski's avatar
Thomas Witkowski committed
483
    void addVertex(Element *el, int ith);
484
485

    /// Adds the i-th edge of an element to the object database.
Thomas Witkowski's avatar
Thomas Witkowski committed
486
    void addEdge(Element *el, int ith);
487
488

    /// Adds the i-th face of an element to the object database.
Thomas Witkowski's avatar
Thomas Witkowski committed
489
    void addFace(Element *el, int ith);
490

491
492
493
494
495
496
497
    /// Creates final data of the periodic boundaries. Must be called after all
    /// elements of the mesh are added to the object database. Then this
    /// functions search for indirectly connected vertices in periodic 
    /// boundaries. This is only the case, if there are more than one boundary
    /// conditions. Then, e.g., in 2D, all edges of a square are iterectly
    /// connected. In 3D, if the macro mesh is a box, all eight vertex nodes and
    /// always four of the 12 edges are indirectly connected.
498
    void createPeriodicData();
Thomas Witkowski's avatar
Thomas Witkowski committed
499
    
500
501
502
503
504
505
    /// Creates on all boundaries the reverse mode flag.
    void createReverseModeData();

    BoundaryType getNewBoundaryType();

    BoundaryType provideConnectedPeriodicBoundary(BoundaryType b0, 
506
						  BoundaryType b1);
507
508

    /// Some auxiliary function to write the element object database to disk.
509
    void serialize(ostream &out, vector<ElementObjectData>& elVec);
510

511
    /// Some auxiliary function to read the element object database from disk.
512
    void deserialize(istream &in, vector<ElementObjectData>& elVec);
513

514
    /// Some auxiliary function to write the element object database to disk.
515
    void serialize(ostream &out, flat_map<int, ElementObjectData>& data);
516

517
    /// Some auxiliary function to read the element object database from disk.
518
    void deserialize(istream &in, flat_map<int, ElementObjectData>& data);
519

520
    int getOwner(vector<ElementObjectData>& objData, int level);
Thomas Witkowski's avatar
Thomas Witkowski committed
521
  private:
522
523
    const FiniteElemSpace* feSpace;

524
525
    /// The mesh that is used to store all its element information in 
    /// the database.
526
    Mesh *mesh;
527

528
    
529
    /// Maps to each vertex DOF all element objects that represent this vertex.
530
    flat_map<DegreeOfFreedom, vector<ElementObjectData> > vertexElements;
531
532

    /// Maps to each edge all element objects that represent this edge.
533
    flat_map<DofEdge, vector<ElementObjectData> > edgeElements;
Thomas Witkowski's avatar
Thomas Witkowski committed
534

535
    /// Maps to each face all element objects that represent this edge.
536
537
538
539
540
541
542
543
544
545
546
547
    flat_map<DofFace, vector<ElementObjectData> > faceElements;

    
    /// Temporary object to speed up creation of \ref vertexElements
    map<DegreeOfFreedom, vector<ElementObjectData> > tmpVertexElements;

    /// Temporary object to speed up creation of \ref edgeElements
    map<DofEdge, vector<ElementObjectData> > tmpEdgeElements;

    /// Temporary object to speed up creation of \ref faceElements
    map<DofFace, vector<ElementObjectData> > tmpFaceElements;

548

549
550
    
    /// Maps to an element object the corresponding vertex DOF.
551
    flat_map<ElementObjectData, DegreeOfFreedom> vertexLocalMap;
552
553

    /// Maps to an element object the corresponding edge.
554
    flat_map<ElementObjectData, DofEdge> edgeLocalMap;
555
556

    /// Maps to an element object the corresponding face.
557
    flat_map<ElementObjectData, DofFace> faceLocalMap;
558

559
   
560
561
    /// Defines to each vertex DOF a map that maps to each rank number the element
    /// objects that have this vertex DOF in common.
562
    flat_map<DegreeOfFreedom, flat_map<int, ElementObjectData> > vertexInRank;
563

564
565
    /// Defines to each edge a map that maps to each rank number the element 
    /// objects that have this edge in common.
566
    flat_map<DofEdge, flat_map<int, ElementObjectData> > edgeInRank;
567

568
569
    /// Defines to each face a map that maps to each rank number the element 
    /// objects that have this face in common.
570
    flat_map<DofFace, flat_map<int, ElementObjectData> > faceInRank;
Thomas Witkowski's avatar
Thomas Witkowski committed
571

572
573

    /// Vertex iterator to iterate over \ref vertexInRank
574
    flat_map<DegreeOfFreedom, flat_map<int, ElementObjectData> >::iterator vertexIter;
575
576

    /// Edge iterator to iterate over \ref edgeInRank
577
    flat_map<DofEdge, flat_map<int, ElementObjectData> >::iterator edgeIter;
578
579

    /// Face iterator to iterate over \ref faceInRank
580
    flat_map<DofFace, flat_map<int, ElementObjectData> >::iterator faceIter;
Thomas Witkowski's avatar
Thomas Witkowski committed
581

582
583
584
585
586

    /// Defines the geometrical iteration index of the iterators. I.e., the value
    /// is either VERTEX, EDGE or FACE and the corresponding element objects are
    /// traversed. The value CENTER is used to define a not defined states of the
    /// iterators, i.e., if no iteration is running.
Thomas Witkowski's avatar
Thomas Witkowski committed
587
    GeoIndex iterGeoPos;
588

589
    map<pair<BoundaryType, BoundaryType>, BoundaryType> bConnMap;
590

591
    /// The following three data structures store periodic DOFs, edges and faces.
592
593
594
    PerBoundMap<DegreeOfFreedom>::type periodicVertices;
    PerBoundMap<DofEdge>::type periodicEdges;
    PerBoundMap<DofFace>::type periodicFaces;
595

596
597
598
599
600
601
602
    /// Defines the smallest boudary ID for periodic boundary conditions. This is
    /// required to distinguish between "real" periodic boundaries and periodic
    /// boundary IDs that are set by the parallel algorithm for indirectly 
    /// connected boundaries.
    BoundaryType smallestPeriodicBcType;

    /// Stores to each vertex all its periodic associations.
603
    map<DegreeOfFreedom, std::set<BoundaryType> > periodicDofAssoc;
604

605
    /// Stores to each edge all its periodic associations.
606
607
    map<DofEdge, std::set<DofEdge> > periodicEdgeAssoc;

608
609
    /// Stores all interior edge boundaries which have reverse mode enabled.
    std::set<pair<ElementObjectData, ElementObjectData> > edgeReverseMode;
610

611
612
    /// Stores all interior face boundaries which have reverse mode enabled.
    std::set<pair<ElementObjectData, ElementObjectData> > faceReverseMode;
613

614
615
    map<int, int> *macroElementRankMap;

616
    /// Maps to each macro element index a pointer to the corresponding element.
617
    flat_map<int, Element*> macroElIndexMap;
618
619
    
    /// Maps to each macro element index the type of this element.
620
    flat_map<int, int> macroElIndexTypeMap;
621
622

    MeshLevelData* levelData;
Thomas Witkowski's avatar
Thomas Witkowski committed
623
624
625
626
627
  };

}

#endif