MeshStructure.cc 8.52 KB
Newer Older
1
2
3
4
5
6
7
8
#include "MeshStructure.h"
#include "MeshStructure_ED.h"
#include "PartitionElementData.h"
#include "Mesh.h"
#include "Element.h"
#include "Traverse.h"
#include "ElInfo.h"
#include "RefinementManager.h"
Thomas Witkowski's avatar
Thomas Witkowski committed
9
#include "Debug.h"
10
11
12

namespace AMDiS {

13
  const int MeshStructure::unsignedLongSize = sizeof(unsigned long int) * 8;
14

15

16
17
  void MeshStructure::insertElement(bool isLeaf) 
  {
18
    // overflow? -> next index
19
20
21
22
    if (pos >= unsignedLongSize) {
      code.push_back(currentCode);
      pos = 0;
      currentCode = 0;
23
24
25
    }

    // insert element in binary code
26
    if (!isLeaf) {
27
      unsigned long int one = 1;
28
      currentCode += (one << pos);
29
30
    } 

31
32
    pos++;
    nElements++;
33
34
  }

35

36
37
  void MeshStructure::clear()
  {
38
39
40
41
42
    currentCode = 0;
    code.resize(0);
    pos = 0;
    nElements = 0;
    currentElement = 0;
43
44
  }

45

46
47
48
  void MeshStructure::init(Mesh *mesh) 
  {
    clear();
49

50
51
    TraverseStack stack;
    ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER);
52
    while (elInfo) {
53
54
55
56
57
58
59
      insertElement(elInfo->getElement()->isLeaf());
      elInfo = stack.traverseNext(elInfo);
    }
  
    commit();
  }

60
61
62
63
64
65
66

  void MeshStructure::init(BoundaryObject &bound)
  {
    FUNCNAME("MeshStructure::init()");

    Element *el = bound.el;

67
68
    TEST_EXIT_DBG(el)("No element!\n");

69
70
    clear();

71
72
    int s1 = el->getSubObjOfChild(0, bound.subObj, bound.ithObj, bound.elType);
    int s2 = el->getSubObjOfChild(1, bound.subObj, bound.ithObj, bound.elType);
73
74
    
    TEST_EXIT(s1 != -1 || s2 != -1)("This should not happen!\n");
75
76
77
78
79
80
81

    if (debugMode) {
      MSG("addAlondSide(%d, %d, %d, %d)\n",
	  bound.elIndex, bound.ithObj, bound.elType, bound.reverseMode);
      MSG("Element is leaf: %d\n", el->isLeaf());
      MSG("s1 = %d    s2 = %d\n", s1, s2);
    }
82
83
84
    
    if (!el->isLeaf()) {
      if (s1 == -1)
85
	addAlongSide(el->getSecondChild(), bound.subObj, s2, 
86
87
		     el->getChildType(bound.elType), bound.reverseMode);
      else if (s2 == -1)
88
	addAlongSide(el->getFirstChild(), bound.subObj, s1, 
89
90
		     el->getChildType(bound.elType), bound.reverseMode);
      else
91
	addAlongSide(el, bound.subObj, bound.ithObj, bound.elType, bound.reverseMode);
92
    }
93
94
95
96

    commit();    
  }

97
98
99

  void MeshStructure::addAlongSide(Element *el, GeoIndex subObj, int ithObj, 
				   int elType, bool reverseOrder)
100
  {
101
102
103
104
    FUNCNAME("MeshStructure::addAlongSide()");

    if (debugMode) {
      MSG("addAlondSide(%d, %d, %d, %d)\n",
105
	  el->getIndex(), ithObj, elType, reverseOrder);
106
107
108
      MSG("Element is leaf: %d\n", el->isLeaf());
    }
    
109
110
111
    insertElement(el->isLeaf());
    
    if (!el->isLeaf()) {
112
113
      int s1 = el->getSubObjOfChild(0, subObj, ithObj, elType);
      int s2 = el->getSubObjOfChild(1, subObj, ithObj, elType);
114

115
116
117
118
119
120
121
122
      if (debugMode) {
	MSG("Child index %d  %d\n", 
	    el->getFirstChild()->getIndex(),
	    el->getSecondChild()->getIndex());
	MSG("s1 = %d    s2 = %d\n", s1, s2);
	MSG("   \n");
      }

123
124
      if (!reverseOrder) {
	if (s1 != -1) 
125
	  addAlongSide(el->getFirstChild(), subObj, s1, el->getChildType(elType), reverseOrder);
126
	if (s2 != -1)
127
	  addAlongSide(el->getSecondChild(), subObj, s2, el->getChildType(elType), reverseOrder);
128
129
      } else {
	if (s2 != -1)
130
	  addAlongSide(el->getSecondChild(), subObj, s2, el->getChildType(elType), reverseOrder);
131
	if (s1 != -1) 
132
	  addAlongSide(el->getFirstChild(), subObj, s1, el->getChildType(elType), reverseOrder);
133
      }
134
135
136
    }
  }

137

138
139
140
141
142
  void MeshStructure::reset() 
  {
    currentIndex = 0;
    pos = 0;
    currentElement = 0;
143
144
145
146
147

    if (code.size() > 0)
      currentCode = code[0];
    else 
      currentCode = 0;
148
149
  }

150

151
152
  bool MeshStructure::nextElement(MeshStructure *insert)
  {
153
154
155
    FUNCNAME("MeshStructure::nextElement()");

    if (insert)
156
157
      insert->insertElement(isLeafElement());

158
159
    pos++;
    currentElement++;
160

161
162
    if (currentElement >= nElements) 
      return false;
163

164
165
166
167
168
169
    if (pos >= unsignedLongSize) {
      currentIndex++;
      TEST_EXIT_DBG(currentIndex < static_cast<int>(code.size()))
	("End of structure reached!\n");
      pos = 0;
      currentCode = code[currentIndex];
170
    } else {
171
      currentCode >>= 1;
172
    }
173

174
175
176
    return true;
  }

177

178
179
  bool MeshStructure::skipBranch(MeshStructure *insert)
  {
180
181
    FUNCNAME("MeshStructure::skipBranch()");

182
    if (isLeafElement()) {
183
184
185
186
      return nextElement(insert);
    } else {
      bool cont = nextElement(insert);
      cont = skipBranch(insert); // left branch
187
      TEST_EXIT_DBG(cont)("Invalid structure!\n");
188
189
190
191
192
      cont = skipBranch(insert); // righ branch
      return cont;
    }
  }

193

194
195
196
197
  void MeshStructure::merge(MeshStructure *structure1,
			    MeshStructure *structure2,
			    MeshStructure *result)
  {
198
199
    FUNCNAME("MeshStructure::merge()");

200
201
202
203
204
    result->clear();
    structure1->reset();
    structure2->reset();

    bool cont = true;
205
    while (cont) {
206
      bool cont1, cont2;
207
      if (structure1->isLeafElement() == structure2->isLeafElement()) {
208
209
210
	cont1 = structure1->nextElement(result);
	cont2 = structure2->nextElement();
      } else {
211
	if (structure1->isLeafElement()) {
212
213
214
215
216
217
218
	  cont1 = structure1->nextElement();
	  cont2 = structure2->skipBranch(result);
	} else {
	  cont1 = structure1->skipBranch(result);
	  cont2 = structure2->nextElement();
	}
      }
219
      TEST_EXIT_DBG(cont1 == cont2)("Structures don't match!\n");
220
221
222
223
224
225
      cont = cont1;
    }

    result->commit();
  }

226

227
228
  void MeshStructure::fitMeshToStructure(Mesh *mesh,
					 RefinementManager *manager,
229
					 bool checkPartition,
230
					 bool debugMode,
Thomas Witkowski's avatar
Thomas Witkowski committed
231
232
					 int macroElIndex,
					 bool ignoreFinerMesh) 
233
234
235
236
237
238
239
  {
    FUNCNAME("MeshStructure::fitMeshToStructure()");

    bool cont = true;

    // decorate leaf data
    reset();
240
241
    TraverseStack stack;
    ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER);
242
    while (elInfo) {
243
244
245
246
247
      if (macroElIndex >= 0 && 
	  elInfo->getMacroElement()->getElement()->getIndex() != macroElIndex) {
	elInfo = stack.traverseNext(elInfo);
	continue;
      }
248
249
250

      Element *element = elInfo->getElement();

251
252
      TEST_EXIT(cont)("unexpected structure code end!\n");

253
      if (isLeafElement()) {
Thomas Witkowski's avatar
Thomas Witkowski committed
254
255
256
257
258
259
260
261
262
263
	if (ignoreFinerMesh && !element->isLeaf()) {
	  int level = elInfo->getLevel();
	  while (elInfo && level >= elInfo->getLevel())
	    elInfo = stack.traverseNext(elInfo);
	} else {
	  TEST_EXIT(element->isLeaf())
	    ("Mesh is finer than strucutre code! (Element index: %d\n", 
	     element->getIndex());	
	}
      } 
264

265
      if (element->isLeaf() && !isLeafElement()) {
Thomas Witkowski's avatar
Thomas Witkowski committed
266
	MeshStructure *structure = new MeshStructure();
267
268
269
270
	cont = skipBranch(structure);
	structure->commit();

	bool decorate = true;
271
	if (checkPartition) {
272
273
	  PartitionElementData *partitionData = dynamic_cast<PartitionElementData*>
	    (element->getElementData(PARTITION_ED));
274
	  TEST_EXIT_DBG(partitionData)("no partition element data\n");
275
	  PartitionStatus status = partitionData->getPartitionStatus();
276
	  if (debugMode == false && (status == OUT || status == UNDEFINED))
277
278
279
	    decorate = false;
	}

280
	if (decorate) {
Thomas Witkowski's avatar
Thomas Witkowski committed
281
	  MeshStructure_ED *elData = new MeshStructure_ED(element->getElementData());
282
283
284
	  elData->setStructure(structure);
	  element->setElementData(elData);
	} else {
Thomas Witkowski's avatar
Thomas Witkowski committed
285
	  delete structure;
286
287
288
289
290
	}
      } else {
	cont = nextElement();
      }

Thomas Witkowski's avatar
Thomas Witkowski committed
291
292
      if (elInfo)
	elInfo = stack.traverseNext(elInfo);
293
294
295
    }

    // refine mesh
296
    bool finished = true;
297
298
299
300

    do {
      finished = true;
      elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
301
      while (elInfo) {
302
303
304
305
306
307
	if (macroElIndex >= 0 && 
	    elInfo->getMacroElement()->getElement()->getIndex() != macroElIndex) {
	  elInfo = stack.traverseNext(elInfo);
	  continue;
	}

308
	Element *element = elInfo->getElement();
309
	if (element->getElementData(MESH_STRUCTURE) != NULL) {
310
311
312
313
314
315
316
317
	  element->setMark(1);
	  finished = false;
	} else {
	  element->setMark(0);
	}
	elInfo = stack.traverseNext(elInfo);
      }
      manager->refineMesh(mesh);
318
    } while (!finished);
319
320
  }

321

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  void MeshStructure::print(bool resetCode)
  {
    FUNCNAME("MeshStructure::print()");
    
    std::stringstream oss;
    
    if (empty()) {
      oss << "-" << std::endl;
    }	else {	
      if (resetCode)
	reset();

      bool cont = true;
      while (cont) {
	if (isLeafElement())
	  oss << "0";
	else
	  oss << "1";
	
	cont = nextElement();
      }
    }
344
345
346
347
348
349
350
351
352
353
   
    if (oss.str().length() < 255) {
      MSG("Mesh structure code: %s\n", oss.str().c_str());
    } else {
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
      std::cout << "[" << MPI::COMM_WORLD.Get_rank() << "]                Mesh structure code: " << oss.str() << "\n";
#else
      std::cout << "                Mesh structure code: " << oss.str() << "\n";
#endif
    }
354
355
356
  }


357
358
359
360
  bool MeshStructure::compare(MeshStructure &other)
  {
    return (other.getCode() == code);
  }
361
}