ElementObjectDatabase.h 18.5 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
30

#include <map>
#include <vector>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>

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

namespace AMDiS {

40
41
  using namespace std;

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

49
50

  /// Defines one element object. This may be either a vertex, edge or face.
Thomas Witkowski's avatar
Thomas Witkowski committed
51
  struct ElementObjectData {
52
    ElementObjectData(int a = -1, int b = 0)
Thomas Witkowski's avatar
Thomas Witkowski committed
53
      : elIndex(a),
54
	ithObject(b)
Thomas Witkowski's avatar
Thomas Witkowski committed
55
    {}
56
57

    /// Index of the element this object is part of.
Thomas Witkowski's avatar
Thomas Witkowski committed
58
59
    int elIndex;
    
60
    /// Index of the object within the element.
Thomas Witkowski's avatar
Thomas Witkowski committed
61
62
    int ithObject;
    
63
    /// Write this element object to disk.
64
    void serialize(ostream &out) const
65
66
67
68
69
    {
      SerUtil::serialize(out, elIndex);
      SerUtil::serialize(out, ithObject);
    }

70
    /// Read this element object from disk.
71
    void deserialize(istream &in)
72
73
74
75
76
    {
      SerUtil::deserialize(in, elIndex);
      SerUtil::deserialize(in, ithObject);
    }

77
    /// Compare this element object with another one.
78
79
    bool operator==(ElementObjectData& cmp) const
    {
80
      return (elIndex == cmp.elIndex && ithObject == cmp.ithObject);
81
82
    }

83
    /// Define a strict order on element objects.
84
85
    bool operator<(const ElementObjectData& rhs) const
    {
86
87
      return (elIndex < rhs.elIndex || 
	      (elIndex == rhs.elIndex && ithObject < rhs.ithObject));
88
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
89
90
91
92
  };



93
94
  /** \brief
   * This class is a database of element objects. An element object is either a
95
96
97
98
99
100
101
   * 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.
102
   */
103
  class ElementObjectDatabase {
Thomas Witkowski's avatar
Thomas Witkowski committed
104
  public:
105
    ElementObjectDatabase()
106
107
      : feSpace(NULL),
	mesh(NULL),
108
	iterGeoPos(CENTER)
Thomas Witkowski's avatar
Thomas Witkowski committed
109
110
    {}

111
    void setFeSpace(const FiniteElemSpace *fe)
Thomas Witkowski's avatar
Thomas Witkowski committed
112
    {
113
114
115
116
117
118
119
      feSpace = fe;
      mesh = feSpace->getMesh();
    }
  
    Mesh* getMesh()
    {
      return mesh;
120
121
    }

122
    void create();
123

124
    void createMacroElementInfo(vector<MacroElement*> &mel);
125
126

    /** \brief
127
128
129
     * 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.
130
     *
131
132
     * \param[in]  macroElementRankMap   Maps to each macro element of the mesh
     *                                   the rank that owns this macro element.
133
     */
134
135
    void createRankData(map<int, int>& macroElementRankMap,
			MeshLevelData& levelData);
Thomas Witkowski's avatar
Thomas Witkowski committed
136

137

138
    /** \brief
139
140
141
     * 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.
142
     *
143
144
     * \param[in]  pos   Must be either VERTEX, EDGE or FACE and defines the
     *                   elements that should be traversed.
145
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
146
147
    bool iterate(GeoIndex pos)
    {
148
149
150
      // 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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
      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;
    }


209
    /// Returns the data of the current iterator position.
210
    map<int, ElementObjectData>& getIterateData()
Thomas Witkowski's avatar
Thomas Witkowski committed
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
    {
      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;
      }
    }


231
    /// Returns the rank owner of the current iterator position.
232
    int getIterateOwner()
Thomas Witkowski's avatar
Thomas Witkowski committed
233
234
235
    {
      switch (iterGeoPos) {
      case VERTEX:
236
	return vertexOwner[vertexIter->first];
Thomas Witkowski's avatar
Thomas Witkowski committed
237
238
	break;
      case EDGE:
239
	return edgeOwner[edgeIter->first];
Thomas Witkowski's avatar
Thomas Witkowski committed
240
241
	break;
      case FACE:
242
	return faceOwner[faceIter->first];
Thomas Witkowski's avatar
Thomas Witkowski committed
243
244
245
246
247
248
249
250
251
	break;
      default:
	ERROR_EXIT("Should not happen!\n");

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

252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    /// Returns the rank owner of the current iterator position.
    int getIterateMaxLevel()
    {
      switch (iterGeoPos) {
      case VERTEX:
	return vertexMaxLevel[vertexIter->first];
	break;
      case EDGE:
	return edgeMaxLevel[edgeIter->first];
	break;
      case FACE:
	return faceMaxLevel[faceIter->first];
	break;
      default:
	ERROR_EXIT("Should not happen!\n");

	// Will never be reached, just to avoid compiler warnings.
	return -1;
      }
    }
272

273
    /// Returns the rank owner of a vertex DOF.
274
    int getOwner(DegreeOfFreedom vertex)
Thomas Witkowski's avatar
Thomas Witkowski committed
275
    {
276
      return vertexOwner[vertex];
Thomas Witkowski's avatar
Thomas Witkowski committed
277
278
    }

279
    /// Returns the rank owner of an edge.
280
    int getOwner(DofEdge edge)
Thomas Witkowski's avatar
Thomas Witkowski committed
281
    {
282
      return edgeOwner[edge];
Thomas Witkowski's avatar
Thomas Witkowski committed
283
284
    }

285
    /// Returns the rank owner of an face.
286
    int getOwner(DofFace face, int level)
Thomas Witkowski's avatar
Thomas Witkowski committed
287
    {
288
      return faceOwner[face];
Thomas Witkowski's avatar
Thomas Witkowski committed
289
290
    }

291

292
    /// Checks if a given vertex DOF is in a given rank.
293
294
295
296
297
    int isInRank(DegreeOfFreedom vertex, int rank)
    {
      return (vertexInRank[vertex].count(rank));
    }

298
    /// Checks if a given edge is in a given rank.
299
300
301
302
303
    int isInRank(DofEdge edge, int rank)
    {
      return (edgeInRank[edge].count(rank));
    }

304
    /// Checks if a given face is in a given rank.
305
306
307
308
309
310
    int isInRank(DofFace face, int rank)
    {
      return (faceInRank[face].count(rank));
    }


311
312
    /// Returns a vector with all macro elements that have a given vertex DOF 
    /// in common.
313
    vector<ElementObjectData>& getElements(DegreeOfFreedom vertex)
Thomas Witkowski's avatar
Thomas Witkowski committed
314
315
316
317
    {
      return vertexElements[vertex];
    }

318
    /// Returns a vector with all macro elements that have a given edge in common.
319
    vector<ElementObjectData>& getElements(DofEdge edge)
Thomas Witkowski's avatar
Thomas Witkowski committed
320
321
322
323
    {
      return edgeElements[edge];
    }

324
    /// Returns a vector with all macro elements that have a given face in common.
325
    vector<ElementObjectData>& getElements(DofFace face)
Thomas Witkowski's avatar
Thomas Witkowski committed
326
327
328
329
    {
      return faceElements[face];
    }

330

331
332
    /// Returns a vector with all macro elements that have a given vertex DOF 
    /// in common.
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    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];
    }


357
358
359
    
    /// Returns a map that maps to each rank all macro elements in this rank that
    /// have a given vertex DOF in common.
360
    map<int, ElementObjectData>& getElementsInRank(DegreeOfFreedom vertex)
361
362
363
364
    {
      return vertexInRank[vertex];
    }

365
366
    /// Returns a map that maps to each rank all macro elements in this rank that
    /// have a given edge in common.
367
    map<int, ElementObjectData>& getElementsInRank(DofEdge edge)
368
369
370
371
    {
      return edgeInRank[edge];
    }

372
373
    /// Returns a map that maps to each rank all macro elements in this rank that
    /// have a given face in common.
374
    map<int, ElementObjectData>& getElementsInRank(DofFace face)
375
376
377
378
    {
      return faceInRank[face];
    }

379
    /// Returns to an element object data the appropriate vertex DOF.
380
381
    DegreeOfFreedom getVertexLocalMap(ElementObjectData &data)
    {
382
383
      TEST_EXIT_DBG(vertexLocalMap.count(data))("Should not happen!\n");

384
385
386
      return vertexLocalMap[data];
    }

387
    /// Returns to an element object data the appropriate edge.
388
389
    DofEdge getEdgeLocalMap(ElementObjectData &data)
    {
390
391
      TEST_EXIT_DBG(edgeLocalMap.count(data))("Should not happen!\n");

392
393
394
      return edgeLocalMap[data];
    }

395
    /// Returns to an element object data the appropriate face.
396
397
    DofFace getFaceLocalMap(ElementObjectData &data)
    {
398
399
      TEST_EXIT_DBG(faceLocalMap.count(data))("Should not happen!\n");

400
401
402
      return faceLocalMap[data];
    }

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
    PerBoundMap<DegreeOfFreedom>::type& getPeriodicVertices()
    {
      return periodicVertices;
    }

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

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

418
419
    inline bool getEdgeReverseMode(ElementObjectData &obj0, 
				   ElementObjectData &obj1)
420
    {
421
422
423
      if (mesh->getDim() == 2)
	return true;

424
425
426
427
428
429
      TEST_EXIT_DBG(edgeReverseMode.count(make_pair(obj0, obj1)))
	("Should not happen!\n");

      return edgeReverseMode[make_pair(obj0, obj1)];
    }

430
431
    inline bool getFaceReverseMode(ElementObjectData &obj0, 
				   ElementObjectData &obj1)
432
433
434
435
436
437
438
    {
      TEST_EXIT_DBG(faceReverseMode.count(make_pair(obj0, obj1)))
	("Should not happen!\n");

      return faceReverseMode[make_pair(obj0, obj1)];
    }

439
440
441
442
443
444
    /// Returns true if there is periodic data.
    bool hasPeriodicData()
    {
      return (periodicVertices.size() != 0);
    }

445
446
447
448
449
450
451
452
    /// 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);
    }

453
454
455
456
457
458
459
460
461
462
    inline Element* getElementPtr(int index)
    {
      return macroElIndexMap[index];
    }

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

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
  protected:
470
471
472
473
474
475
476
477
478
    /** \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);

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
    /// Adds the i-th DOF vertex of an element to the object database.
    void addVertex(Element *el, int ith)
    {
      DegreeOfFreedom vertex = el->getDof(ith, 0);
      int elIndex = el->getIndex();
      ElementObjectData elObj(elIndex, ith);

      vertexElements[vertex].push_back(elObj);
      vertexLocalMap[elObj] = vertex;
    }

    /// Adds the i-th edge of an element to the object database.
    void addEdge(Element *el, int ith)
    {
      DofEdge edge = el->getEdge(ith);
      int elIndex = el->getIndex();
      ElementObjectData elObj(elIndex, ith);

      edgeElements[edge].push_back(elObj);
      edgeLocalMap[elObj] = edge;
    }

    /// Adds the i-th face of an element to the object database.
    void addFace(Element *el, int ith)
    {
      DofFace face = el->getFace(ith);
      int elIndex = el->getIndex();
      ElementObjectData elObj(elIndex, ith);

      faceElements[face].push_back(elObj);
      faceLocalMap[elObj] = face;
    }

512
513
514
515
516
517
518
519
520
521
522
    /** \brief
     * 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.
     */
    void createPeriodicData();

523

524
525
526
527
528
529
    /// Creates on all boundaries the reverse mode flag.
    void createReverseModeData();

    BoundaryType getNewBoundaryType();

    BoundaryType provideConnectedPeriodicBoundary(BoundaryType b0, 
530
						  BoundaryType b1);
531
532

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

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

538
    /// Some auxiliary function to write the element object database to disk.
539
    void serialize(ostream &out, map<int, ElementObjectData>& data);
540

541
    /// Some auxiliary function to read the element object database from disk.
542
    void deserialize(istream &in, map<int, ElementObjectData>& data);
543

Thomas Witkowski's avatar
Thomas Witkowski committed
544
  private:
545
546
    const FiniteElemSpace* feSpace;

547
548
    /// The mesh that is used to store all its element information in 
    /// the database.
549
    Mesh *mesh;
550
    
551
    /// Maps to each vertex DOF all element objects that represent this vertex.
552
    map<DegreeOfFreedom, vector<ElementObjectData> > vertexElements;
553
554

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

557
558
    /// Maps to each face all element objects that represent this edge.
    map<DofFace, vector<ElementObjectData> > faceElements;
559

560
561
    
    /// Maps to an element object the corresponding vertex DOF.
562
    map<ElementObjectData, DegreeOfFreedom> vertexLocalMap;
563
564

    /// Maps to an element object the corresponding edge.
565
    map<ElementObjectData, DofEdge> edgeLocalMap;
566
567

    /// Maps to an element object the corresponding face.
568
    map<ElementObjectData, DofFace> faceLocalMap;
569

570
    /// Defines for all vertex DOFs the rank that ownes this vertex DOF.
571
    map<DegreeOfFreedom, int> vertexOwner;
572
573

    /// Defines for all edges the rank that ownes this edge.
574
    map<DofEdge, int> edgeOwner;
575
576

    /// Defines for all faces the rank that ownes this face.
577
    map<DofFace, int> faceOwner;
Thomas Witkowski's avatar
Thomas Witkowski committed
578

579
580
581
582
583
584
585
    
    map<DegreeOfFreedom, int> vertexMaxLevel;

    map<DofEdge, int> edgeMaxLevel;

    map<DofFace, int> faceMaxLevel;

586

587
588
    /// Defines to each vertex DOF a map that maps to each rank number the element
    /// objects that have this vertex DOF in common.
589
    map<DegreeOfFreedom, map<int, ElementObjectData> > vertexInRank;
590

591
592
    /// Defines to each edge a map that maps to each rank number the element 
    /// objects that have this edge in common.
593
    map<DofEdge, map<int, ElementObjectData> > edgeInRank;
594

595
596
    /// Defines to each face a map that maps to each rank number the element 
    /// objects that have this face in common.
597
    map<DofFace, map<int, ElementObjectData> > faceInRank;
Thomas Witkowski's avatar
Thomas Witkowski committed
598

599
600

    /// Vertex iterator to iterate over \ref vertexInRank
601
    map<DegreeOfFreedom, map<int, ElementObjectData> >::iterator vertexIter;
602
603

    /// Edge iterator to iterate over \ref edgeInRank
604
    map<DofEdge, map<int, ElementObjectData> >::iterator edgeIter;
605
606

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

609
610
611
612
613

    /// 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
614
    GeoIndex iterGeoPos;
615

616
    map<pair<BoundaryType, BoundaryType>, BoundaryType> bConnMap;
617

618
    /// The following three data structures store periodic DOFs, edges and faces.
619
620
621
    PerBoundMap<DegreeOfFreedom>::type periodicVertices;
    PerBoundMap<DofEdge>::type periodicEdges;
    PerBoundMap<DofFace>::type periodicFaces;
622

623
624
625
626
627
628
629
    /// 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.
630
    map<DegreeOfFreedom, std::set<BoundaryType> > periodicDofAssoc;
631

632
    /// Stores to each edge all its periodic associations.
633
634
635
636
637
    map<DofEdge, std::set<DofEdge> > periodicEdgeAssoc;

    map<pair<ElementObjectData, ElementObjectData>, bool> edgeReverseMode;

    map<pair<ElementObjectData, ElementObjectData>, bool> faceReverseMode;
638
639
640
641
642
643

    /// Maps to each macro element index a pointer to the corresponding element.
    map<int, Element*> macroElIndexMap;
    
    /// Maps to each macro element index the type of this element.
    map<int, int> macroElIndexTypeMap;
Thomas Witkowski's avatar
Thomas Witkowski committed
644
645
646
647
648
  };

}

#endif