Mesh.cc 33.2 KB
Newer Older
Thomas Witkowski's avatar
Thomas Witkowski committed
1
2
3
4
5
6
#include <algorithm>
#include <set>
#include <map>

#include "time.h"

7
8
9
10
#include "AdaptStationary.h"
#include "AdaptInstationary.h"
#include "FiniteElemSpace.h"
#include "ElementData.h"
Thomas Witkowski's avatar
Thomas Witkowski committed
11
#include "ElementDofIterator.h"
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "MacroElement.h"
#include "MacroReader.h"
#include "Mesh.h"
#include "Traverse.h"
#include "Parameters.h"
#include "FixVec.h"
#include "DOFVector.h"
#include "CoarseningManager.h"
#include "DOFIterator.h"
#include "VertexVector.h"
#include "MacroWriter.h"
#include "PeriodicMap.h"
#include "Projection.h"
Thomas Witkowski's avatar
Thomas Witkowski committed
25
#include "ElInfoStack.h"
26

27
28
#include "mpi.h"

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
namespace AMDiS {

#define TIME_USED(f,s) ((double)((s)-(f))/(double)CLOCKS_PER_SEC)

  //**************************************************************************
  //  flags, which information should be present in the elInfo structure     
  //**************************************************************************

  const Flag Mesh::FILL_NOTHING    = 0X00L;
  const Flag Mesh::FILL_COORDS     = 0X01L;
  const Flag Mesh::FILL_BOUND      = 0X02L;
  const Flag Mesh::FILL_NEIGH      = 0X04L;
  const Flag Mesh::FILL_OPP_COORDS = 0X08L;
  const Flag Mesh::FILL_ORIENTATION= 0X10L;
  const Flag Mesh::FILL_DET        = 0X20L;
  const Flag Mesh::FILL_GRD_LAMBDA = 0X40L;
  const Flag Mesh::FILL_ADD_ALL    = 0X80L;


48
49
50
  const Flag Mesh::FILL_ANY_1D = (0X01L|0X02L|0X04L|0X08L|0x20L|0X40L|0X80L);
  const Flag Mesh::FILL_ANY_2D = (0X01L|0X02L|0X04L|0X08L|0x20L|0X40L|0X80L);
  const Flag Mesh::FILL_ANY_3D = (0X01L|0X02L|0X04L|0X08L|0X10L|0x20L|0X40L|0X80L);
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

  //**************************************************************************
  //  flags for Mesh traversal                                                
  //**************************************************************************

  const Flag Mesh::CALL_EVERY_EL_PREORDER  = 0X0100L;
  const Flag Mesh::CALL_EVERY_EL_INORDER   = 0X0200L;
  const Flag Mesh::CALL_EVERY_EL_POSTORDER = 0X0400L;
  const Flag Mesh::CALL_LEAF_EL            = 0X0800L;
  const Flag Mesh::CALL_LEAF_EL_LEVEL      = 0X1000L;
  const Flag Mesh::CALL_EL_LEVEL           = 0X2000L;
  const Flag Mesh::CALL_MG_LEVEL           = 0X4000L ; // used in mg methods 


  // const Flag Mesh::USE_PARAMETRIC          = 0X8000L ; // used in mg methods 

  DOFAdmin* Mesh::compressAdmin = NULL;
  Mesh* Mesh::traversePtr = NULL;
Thomas Witkowski's avatar
Thomas Witkowski committed
69
  std::vector<DegreeOfFreedom> Mesh::dof_used;
70
  const int Mesh::MAX_DOF = 100;
71
  std::map<std::pair<DegreeOfFreedom, int>, DegreeOfFreedom*> Mesh::serializedDOFs;
72
73
74

  struct delmem { 
    DegreeOfFreedom* ptr;
75
    int len;
76
77
78
  };


Thomas Witkowski's avatar
Thomas Witkowski committed
79
  Mesh::Mesh(std::string aName, int dimension) 
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    : name(aName), 
      dim(dimension), 
      nVertices(0),
      nEdges(0),
      nLeaves(0), 
      nElements(0),
      parametric(NULL), 
      preserveCoarseDOFs(false),
      nDOFEl(0),
      nDOF(dimension, DEFAULT_VALUE, 0),
      nNodeEl(0),
      node(dimension, DEFAULT_VALUE, 0),
      elementPrototype(NULL),
      elementDataPrototype(NULL),
      elementIndex(-1),
      initialized(false),
96
      macroFileInfo(NULL),
97
98
99
      final_lambda(dimension, DEFAULT_VALUE, 0.0)
  {

100
    FUNCNAME("Mesh::Mesh()");
101
102
103
104

    // set default element prototype
    switch(dim) {
    case 1:
Thomas Witkowski's avatar
Thomas Witkowski committed
105
      elementPrototype = new Line(this);
106
107
      break;
    case 2:
Thomas Witkowski's avatar
Thomas Witkowski committed
108
      elementPrototype = new Triangle(this);
109
110
      break;
    case 3:
Thomas Witkowski's avatar
Thomas Witkowski committed
111
      elementPrototype = new Tetrahedron(this);
112
113
114
115
116
117
118
      break;
    default:
      ERROR_EXIT("invalid dimension\n");
    }

    elementPrototype->setIndex(-1);

119
120
    elementIndex = 0;
  }
121
122

  Mesh::~Mesh()
123
  {
124
    Element::deletedDOFs.clear();
125
126
127
128
129

    for (std::deque<MacroElement*>::const_iterator it = macroElements.begin();
	 it != macroElements.end();
	 ++it) {
      (*it)->getElement()->deleteElementDOFs();
Thomas Witkowski's avatar
Thomas Witkowski committed
130
      delete *it;
131
132
    }    

133
    Element::deletedDOFs.clear();
134

135
    if (macroFileInfo != NULL) {
Thomas Witkowski's avatar
Thomas Witkowski committed
136
      delete macroFileInfo;
137
    }
138
    if (elementPrototype) {
Thomas Witkowski's avatar
Thomas Witkowski committed
139
      delete elementPrototype;
140
141
    }
    if (elementDataPrototype) {
Thomas Witkowski's avatar
Thomas Witkowski committed
142
      delete elementDataPrototype;
143
144
145
    }
    
    for (int i = 0; i < static_cast<int>(admin.size()); i++) {
Thomas Witkowski's avatar
Thomas Witkowski committed
146
      delete admin[i];
147
    }
148
  }
149
150

  Mesh& Mesh::operator=(const Mesh& m)
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
    FUNCNAME("Mesh::operator=()");

    if (this == &m)
      return *this;

    TEST_EXIT(dim == m.dim)("operator= works only on meshes with equal dim!\n");

    name = m.name;
    nVertices = m.nVertices;
    nEdges = m.nEdges;
    nLeaves = m.nLeaves;
    nElements = m.nElements;
    nFaces = m.nFaces;
    maxEdgeNeigh = m.maxEdgeNeigh;
    diam = m.diam;
    parametric = NULL;

    preserveCoarseDOFs = m.preserveCoarseDOFs;
    nDOFEl = m.nDOFEl;
    nDOF = m.nDOF;
    nNodeEl = m.nNodeEl;
    node = m.node;
    newDOF = m.newDOF;
    elementIndex = m.elementIndex;
    initialized = m.initialized;
    final_lambda = m.final_lambda;
    
    /* ====================== Create new DOFAdmins ================== */
    admin.resize(m.admin.size());
    for (int i = 0; i < static_cast<int>(admin.size()); i++) {
Thomas Witkowski's avatar
Thomas Witkowski committed
182
      admin[i] = new DOFAdmin(this);
183
      *(admin[i]) = *(m.admin[i]);
184
185
      admin[i]->setMesh(this);
    }
186

187

188
    /* ====================== Copy macro elements =================== */
189
  
190
191
192
193
194
195
196
197
198
    // mapIndex[i] is the index of the MacroElement element in the vector
    // macroElements, for which holds: element->getIndex() = i    
    std::map<int, int> mapIndex;

    // We use this map for coping the DOFs of the Elements within the
    // MacroElements objects.
    Mesh::serializedDOFs.clear();

    int insertCounter = 0;
199

200
201
    macroElements.clear();

202
203
204
205
206
    // Go through all MacroElements of mesh m, and create for every a new
    // MacroElement in this mesh.
    for (std::deque<MacroElement*>::const_iterator it = m.macroElements.begin();
	 it != m.macroElements.end();
	 ++it, insertCounter++) {
207

208
      // Create new MacroElement.
Thomas Witkowski's avatar
Thomas Witkowski committed
209
      MacroElement *el = new MacroElement(dim);
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
      // Use copy operator to copy all the data to the new MacroElement.
      *el = **it;

      // Make a copy of the Element data, together with all DOFs
      el->setElement((*it)->getElement()->cloneWithDOFs());

      // Insert the new MacroElement in the vector of all MacroElements.
      macroElements.push_back(el);

      // Update the index map.
      mapIndex.insert(std::pair<int, int>(el->getIndex(), insertCounter));
    }

    // Now we have to go through all the new MacroElements, and update the neighbour
    // connections.
    insertCounter = 0;
    for (std::deque<MacroElement*>::const_iterator it = m.macroElements.begin();
	 it != m.macroElements.end();
	 ++it, insertCounter++) {
      // Go through all neighbours.
      for (int i = 0; i < dim; i++) {
	// 1. Get index of the old MacroElement for its i-th neighbour.
	// 2. Because the index in the new MacroElement is the same, search
	//    for the vector index the corresponding element is stored in.
	// 3. Get this element from macroElements, and set it as the i-th
	//    neighbour for the current element.
	macroElements[insertCounter]->
	  setNeighbour(i, macroElements[mapIndex[(*it)->getNeighbour(i)->getIndex()]]);
      }
    }

    // Cleanup
    Mesh::serializedDOFs.clear();

    /* ================== Things will be done when required ============ */
      
    TEST_EXIT(elementDataPrototype == NULL)("TODO\n");
    TEST_EXIT(m.parametric == NULL)("TODO\n");
    TEST_EXIT(periodicAssociations.size() == 0)("TODO\n");

    return *this;
  }

254
255
256
257
258
259
260
261
262
263
264
265
  void Mesh::updateNumberOfLeaves()
  {
    nLeaves = 0;

    TraverseStack stack;
    ElInfo *elInfo = stack.traverseFirst(this, -1, Mesh::CALL_LEAF_EL);
    while (elInfo) {
      nLeaves++;
      elInfo = stack.traverseNext(elInfo);
    }
  }

266
267
268
269
270
271
  void Mesh::addMacroElement(MacroElement* me) 
  {
    macroElements.push_back(me); 
    me->setIndex(macroElements.size());
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
272
273
  void Mesh::removeMacroElements(std::vector<MacroElement*>& macros,
				 const FiniteElemSpace *feSpace) 
274
275
276
  {
    FUNCNAME("Mesh::removeMacroElement()");

Thomas Witkowski's avatar
Thomas Witkowski committed
277
278
279
280
281
282
283
284
    typedef std::map<const DegreeOfFreedom*, std::set<MacroElement*> > DofElMap;
    typedef std::map<const DegreeOfFreedom*, GeoIndex> DofPosMap;

    TEST_EXIT(dim == 2)("Not yet implemented for dim != 2!\n");
    TEST_EXIT(admin.size() == 1)("Not yet implemented for multiple admins!\n");
    TEST_EXIT(admin[0])("There is something wrong!\n");

    ElementDofIterator elDofIter(feSpace);
285

286
287
    // Map that stores for each dof pointer (which may have a list of dofs)
    // all macro element indices that own the dof.
Thomas Witkowski's avatar
Thomas Witkowski committed
288
289
    DofElMap dofsOwner;
    DofPosMap dofsPosIndex;
290
291
292
293
294
    
    // Determine all dof owner macro elements.
    for (std::deque<MacroElement*>::iterator macroIt = macroElements.begin();
	 macroIt != macroElements.end();
	 ++macroIt) {
Thomas Witkowski's avatar
Thomas Witkowski committed
295
296
297
298
299
      elDofIter.reset((*macroIt)->getElement());
      do {
	dofsOwner[elDofIter.getDofPtr()].insert(*macroIt);
	dofsPosIndex[elDofIter.getDofPtr()] = elDofIter.getPosIndex();
      } while (elDofIter.nextStrict());
300
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
301

302
303
304
305
    // Remove all the given macro elements.
    for (std::vector<MacroElement*>::iterator macroIt = macros.begin();
	 macroIt != macros.end();
	 ++macroIt) {
Thomas Witkowski's avatar
Thomas Witkowski committed
306
307
308
309
310
311
312

      std::deque<MacroElement*>::iterator mEl = 
	find(macroElements.begin(), macroElements.end(), *macroIt);
      TEST_EXIT(mEl != macroElements.end())
	("Cannot find MacroElement that should be removed!\n");
      macroElements.erase(mEl);

313
314
315
316
      // Go through all neighbours of the macro element and remove this macro element
      // to be neighbour of some other macro element.
      for (int i = 0; i <= dim; i++) {
	if ((*macroIt)->getNeighbour(i)) {
Thomas Witkowski's avatar
Thomas Witkowski committed
317
318
	  for (int j = 0; j <= dim; j++)
	    if ((*macroIt)->getNeighbour(i)->getNeighbour(j) == *macroIt)
319
320
321
322
323
	      (*macroIt)->getNeighbour(i)->setNeighbour(j, NULL);
	} else {
	  // There is no neighbour at this edge, so we have to decrease the number
	  // of edges in the mesh.
	  nEdges--;
324
	}
325
326
327
328
329
330
      }

      nLeaves--;
      nElements--;

      // Remove this macro element from the dof owner list.
Thomas Witkowski's avatar
Thomas Witkowski committed
331
332
      for (DofElMap::iterator dofsIt = dofsOwner.begin();
	   dofsIt != dofsOwner.end(); ++dofsIt) {
333
	std::set<MacroElement*>::iterator mIt = dofsIt->second.find(*macroIt);
Thomas Witkowski's avatar
Thomas Witkowski committed
334
	if (mIt != dofsIt->second.end())
335
336
337
338
339
340
341
	  dofsIt->second.erase(mIt);
      }

      // And remove the macro element from memory
      delete *macroIt;
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
342

343
344
345
    int nRemainDofs = 0;
    // Check now all the dofs, that have no owner anymore and therefore have to
    // be removed.
Thomas Witkowski's avatar
Thomas Witkowski committed
346
347
348
349
350
351
    for (DofElMap::iterator dofsIt = dofsOwner.begin(); 
	 dofsIt != dofsOwner.end(); ++dofsIt) {    
      if (dofsIt->second.size() == 0)
	freeDOF(const_cast<DegreeOfFreedom*>(dofsIt->first),
		dofsPosIndex[dofsIt->first]);
      else
352
	nRemainDofs++;
353
354
    }

355
    nVertices = nRemainDofs;
356
  }
357

358
  int Mesh::traverse(int level, Flag flag, int (*el_fct)(ElInfo*))
359
360
  {
    FUNCNAME("Mesh::traverse()");
Thomas Witkowski's avatar
Thomas Witkowski committed
361

Thomas Witkowski's avatar
Thomas Witkowski committed
362
    std::deque<MacroElement*>::iterator mel;
Thomas Witkowski's avatar
Thomas Witkowski committed
363
364
    ElInfoStack elInfoStack(this);
    ElInfo* elinfo = elInfoStack.getNextElement();
365
366
367
368
369
370
371
372
373
374
375
376
377
    Traverse tinfo(this, flag, level, el_fct);
    int sum = 0;
  
    elinfo->setFillFlag(flag);
  
    if (flag.isSet(Mesh::CALL_LEAF_EL_LEVEL) || 
	flag.isSet(Mesh::CALL_EL_LEVEL)      || 
	flag.isSet(Mesh::CALL_MG_LEVEL)) {
      TEST(level >= 0)("invalid level: %d\n", level);
    }
  
    for (mel = macroElements.begin(); mel != macroElements.end(); mel++) {
      elinfo->fillMacroInfo(*mel);
Thomas Witkowski's avatar
Thomas Witkowski committed
378
      sum += tinfo.recursive(&elInfoStack);
379
380
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
381
    elInfoStack.getBackElement();
382
383
384
385
386
387
388
389
390
391
    
    return (flag.isSet(Mesh::FILL_ADD_ALL)) ? sum : 0;
  }

  void Mesh::addDOFAdmin(DOFAdmin *localAdmin)
  {    
    FUNCNAME("Mesh::addDOFAdmin()");

    localAdmin->setMesh(this);

392
393
    std::vector<DOFAdmin*>::iterator dai = 
      std::find(admin.begin(),admin.end(),localAdmin);
394

Thomas Witkowski's avatar
Thomas Witkowski committed
395
396
397
    TEST_EXIT(dai == admin.end())
      ("admin %s is already associated to mesh %s\n",
       localAdmin->getName().c_str(), this->getName().c_str());
398

399
    // if this will be required, see the untested code in revision < 224
400
    //    TEST_EXIT(!initialized)("Adding DOFAdmins to initilized meshes does not work yet!\n");
Thomas Witkowski's avatar
Thomas Witkowski committed
401

402
403
404
405
406
    admin.push_back(localAdmin);

    nDOFEl = 0;

    localAdmin->setNumberOfPreDOFs(VERTEX,nDOF[VERTEX]);
407
    nDOF[VERTEX] += localAdmin->getNumberOfDOFs(VERTEX);
408
409
    nDOFEl += getGeo(VERTEX) * nDOF[VERTEX];

410
    if (dim > 1) {
411
      localAdmin->setNumberOfPreDOFs(EDGE,nDOF[EDGE]);
412
      nDOF[EDGE] += localAdmin->getNumberOfDOFs(EDGE);
413
414
415
416
417
418
419
      nDOFEl += getGeo(EDGE) * nDOF[EDGE];
    }

    localAdmin->setNumberOfPreDOFs(CENTER,nDOF[CENTER]);
    nDOF[CENTER]  += localAdmin->getNumberOfDOFs(CENTER);
    nDOFEl += nDOF[CENTER];

420
    TEST_EXIT_DBG(nDOF[VERTEX] > 0)("no vertex dofs\n");
421

422
423
    node[VERTEX] = 0;
    nNodeEl = getGeo(VERTEX);
424

425
426
    if (dim > 1) {
      node[EDGE] = nNodeEl;
427
428
      if (nDOF[EDGE] > 0) 
	nNodeEl += getGeo(EDGE);
429
430
    }

431
    if (dim == 3) {
432
      localAdmin->setNumberOfPreDOFs(FACE,nDOF[FACE]);
433
434
435
436
437
      nDOF[FACE] += localAdmin->getNumberOfDOFs(FACE);
      nDOFEl += getGeo(FACE) * nDOF[FACE];
      node[FACE] = nNodeEl;
      if (nDOF[FACE] > 0) 
	nNodeEl += getGeo(FACE);
438
439
    }

440
    node[CENTER] = nNodeEl;
441
    if (nDOF[CENTER] > 0)
442
      nNodeEl += 1;
443
444
445
446
  }

  void Mesh::dofCompress()
  {
447
448
    FUNCNAME("Mesh::dofCompress()");
    Flag fill_flag;
449

Thomas Witkowski's avatar
Thomas Witkowski committed
450
    for (int iadmin = 0; iadmin < static_cast<int>(admin.size()); iadmin++) {
451
452
453
      compressAdmin = admin[iadmin];

      TEST_EXIT_DBG(compressAdmin)("no admin[%d] in mesh\n", iadmin);
454
      
Thomas Witkowski's avatar
Thomas Witkowski committed
455
456
      int size = compressAdmin->getSize();
      if (size < 1) 
457
	continue;
Thomas Witkowski's avatar
Thomas Witkowski committed
458

459
460
      if (compressAdmin->getUsedDOFs() < 1)    
	continue;
Thomas Witkowski's avatar
Thomas Witkowski committed
461

462
463
      if (compressAdmin->getHoleCount() < 1)    
	continue;
Thomas Witkowski's avatar
Thomas Witkowski committed
464
  
465
466
467
468
469
470
471
472
      newDOF.resize(size);
      
      compressAdmin->compress(newDOF);
      
      if (preserveCoarseDOFs) {
	fill_flag = Mesh::CALL_EVERY_EL_PREORDER | Mesh::FILL_NOTHING;
      } else {
	fill_flag = Mesh::CALL_LEAF_EL | Mesh::FILL_NOTHING;
473
      }
474
      
Thomas Witkowski's avatar
Thomas Witkowski committed
475
476
      traverse(-1, fill_flag, newDOFFct1);
      traverse(-1, fill_flag, newDOFFct2);
477
478
479
      
      newDOF.resize(0);
    }   
480
481
482
483
484
  }


  DegreeOfFreedom *Mesh::getDOF(GeoIndex position)
  {
485
    FUNCNAME("Mesh::getDOF()");
486

487
    TEST_EXIT_DBG(position >= CENTER && position <= FACE)
488
      ("unknown position %d\n", position);
489

490
491
    int ndof = getNumberOfDOFs(position);
    if (ndof <= 0) 
492
      return NULL;
493

494
    DegreeOfFreedom *dof = new DegreeOfFreedom[ndof];
495

496
497
    for (int i = 0; i < getNumberOfDOFAdmin(); i++) {
      const DOFAdmin *localAdmin = &getDOFAdmin(i);
498
      TEST_EXIT_DBG(localAdmin)("no admin[%d]\n", i);
499
500
501
502
      
      int n  = localAdmin->getNumberOfDOFs(position);
      int n0 = localAdmin->getNumberOfPreDOFs(position);
      
503
      TEST_EXIT_DBG(n + n0 <= ndof)("n=%d, n0=%d too large: ndof=%d\n", n, n0, ndof);
504
      
505
      for (int j = 0; j < n; j++)
506
507
	dof[n0 + j] = const_cast<DOFAdmin*>(localAdmin)->getDOFIndex();
    }
508
 
509
    return dof;
510
511
512
513
514
  }


  DegreeOfFreedom **Mesh::createDOFPtrs()
  {
515
    FUNCNAME("Mesh::createDOFPtrs()");
516
517

    if (nNodeEl <= 0)
518
      return NULL;
519

520
    DegreeOfFreedom **ptrs = new DegreeOfFreedom*[nNodeEl];
521
    for (int i = 0; i < nNodeEl; i++)
522
523
      ptrs[i] = NULL;

524
    return ptrs;
525
526
527
528
  }

  void Mesh::freeDOFPtrs(DegreeOfFreedom **ptrs)
  {
529
    FUNCNAME("Mesh::freeDOFPtrs()");
530

531
    TEST_EXIT_DBG(ptrs)("ptrs=NULL\n");
532
533
534
535

    if (nNodeEl <= 0)
      return;
  
536
    delete [] ptrs;
537
538
539
  }


Thomas Witkowski's avatar
Thomas Witkowski committed
540
  const DOFAdmin *Mesh::createDOFAdmin(std::string lname, DimVec<int> lnDOF)
541
  {
542
    FUNCNAME("Mesh::createDOFAdmin()");
543

Thomas Witkowski's avatar
Thomas Witkowski committed
544
    DOFAdmin *localAdmin = new DOFAdmin(this, lname);
545

Thomas Witkowski's avatar
Thomas Witkowski committed
546
547
    for (int i = 0; i < dim + 1; i++)
      localAdmin->setNumberOfDOFs(i, lnDOF[i]);
548
549
550

    addDOFAdmin(localAdmin);

551
    return localAdmin;
552
553
554
555
556
557
558
  }


  const DOFAdmin* Mesh::getVertexAdmin() const
  {
    const DOFAdmin *localAdmin = NULL;

559
560
561
562
563
564
    for (int i = 0; i < static_cast<int>(admin.size()); i++) {
      if (admin[i]->getNumberOfDOFs(VERTEX)) {
	if (!localAdmin)  
	  localAdmin = admin[i];
	else if (admin[i]->getSize() < localAdmin->getSize())
	  localAdmin = admin[i];
565
      }
566
567
    }

568
    return localAdmin;
569
570
571
572
  }

  void Mesh::freeDOF(DegreeOfFreedom* dof, GeoIndex position)
  {
573
    FUNCNAME("Mesh::freeDOF()");
574

575
    TEST_EXIT_DBG(position >= CENTER && position <= FACE)
576
      ("unknown position %d\n", position);
577

578
579
580
581
    int ndof = nDOF[position];
    if (ndof) {
      if (!dof) {
	MSG("dof = NULL, but ndof=%d\n", ndof);
582
583
	return;
      }
584
585
586
587
588
589
    } else  {
      if (dof) {
	MSG("dof != NULL, but ndof=0\n");
      }
      return;
    }
590

591
    TEST_EXIT_DBG(ndof <= MAX_DOF)
592
      ("ndof too big: ndof=%d, MAX_DOF=%d\n", ndof, MAX_DOF);
593

594
595
596
597
598
599
600
601
602
603
    for (int i = 0; i < static_cast<int>(admin.size()); i++) {
      DOFAdmin *localAdmin = admin[i];
      int n = localAdmin->getNumberOfDOFs(position);
      int n0 = localAdmin->getNumberOfPreDOFs(position);
      
      TEST_EXIT_DBG(n + n0 <= ndof)("n=%d, n0=%d too large: ndof=%d\n", n, n0, ndof);
      
      for (int j = 0; j < n; j++)
	localAdmin->freeDOFIndex(dof[n0 + j]);
    }
604

605
    delete [] dof;
606
607
608
609
610
  }

  void Mesh::freeElement(Element* el)
  {
    freeDOFPtrs(const_cast<DegreeOfFreedom**>(el->getDOF()));
Thomas Witkowski's avatar
Thomas Witkowski committed
611
    delete el;
612
613
614
615
616
617
  }


  Element* Mesh::createNewElement(Element *parent)
  {
    FUNCNAME("Mesh::createNewElement()");
618
619

    TEST_EXIT_DBG(elementPrototype)("no element prototype\n");
620
621
622

    Element *el = parent ? parent->clone() : elementPrototype->clone();
  
623
    if (!parent && elementDataPrototype) {
624
625
626
627
628
629
630
631
      el->setElementData(elementDataPrototype->clone()); 
    } else {
      el->setElementData(NULL); // must be done in ElementData::refineElementData()
    }

    return el;
  }

632

633
634
635
636
  ElInfo* Mesh::createNewElInfo()
  {
    switch(dim) {
    case 1:
Thomas Witkowski's avatar
Thomas Witkowski committed
637
      return new ElInfo1d(this);
638
639
      break;
    case 2:
Thomas Witkowski's avatar
Thomas Witkowski committed
640
      return new ElInfo2d(this);
641
642
      break;
    case 3:
Thomas Witkowski's avatar
Thomas Witkowski committed
643
      return new ElInfo3d(this);
644
645
646
647
      break;
    default:
      ERROR_EXIT("invalid dim\n");
      return NULL;
648
    }
649
650
651
652
  }

  bool Mesh::findElInfoAtPoint(const WorldVector<double>& xy,
			       ElInfo *el_info,
653
654
			       DimVec<double>& bary,
			       const MacroElement *start_mel,
655
			       const WorldVector<double> *xy0,
656
			       double *sp)
657
658
659
660
661
662
663
664
665
666
  {
    static const MacroElement *mel = NULL;
    DimVec<double> lambda(dim, NO_INIT);
    ElInfo *mel_info = NULL;

    mel_info = createNewElInfo();

    if (start_mel != NULL)
      mel = start_mel;
    else
667
      if ((mel == NULL) || (mel->getElement()->getMesh() != this))
668
669
670
	mel = *(macroElements.begin());

    mel_info->setFillFlag(Mesh::FILL_COORDS);
671
    g_xy = &xy;
672
    g_xy0 = xy0;
673
    g_sp = sp;
674
675
676

    mel_info->fillMacroInfo(mel);

677
    int k;
678
679
680
681
682
683
684
685
686
687
    while ((k = mel_info->worldToCoord(xy, &lambda)) >= 0) {
      if (mel->getNeighbour(k)) {
	mel = mel->getNeighbour(k);
	mel_info->fillMacroInfo(mel);
	continue;
      }
      break;
    }

    /* now, descend in tree to find leaf element at point */
688
    bool inside = findElementAtPointRecursive(mel_info, lambda, k, el_info);
689
690
    for (int i = 0; i <= dim; i++)
      bary[i] = final_lambda[i];   
691
  
Thomas Witkowski's avatar
Thomas Witkowski committed
692
    delete mel_info;
693

694
    return inside;
695
696
697
  }

  bool Mesh::findElementAtPoint(const WorldVector<double>&  xy,
698
699
				Element **elp, 
				DimVec<double>& bary,
700
				const MacroElement *start_mel,
701
702
				const WorldVector<double> *xy0,
				double *sp)
703
  {
704
705
    ElInfo *el_info = createNewElInfo();
    int val = findElInfoAtPoint(xy, el_info, bary, start_mel, xy0, sp);
706
707
708

    *elp = el_info->getElement();

Thomas Witkowski's avatar
Thomas Witkowski committed
709
    delete el_info;
710

711
    return val;
712
713
  }

714
  bool Mesh::findElementAtPointRecursive(ElInfo *el_info,
715
					 const DimVec<double>& lambda,
716
					 int outside,
717
718
					 ElInfo* final_el_info)
  {
719
    FUNCNAME("Mesh::findElementAtPointRecursive()");
720
721
    Element *el = el_info->getElement();
    DimVec<double> c_lambda(dim, NO_INIT);
722
723
    int inside;
    int ichild, c_outside;
724
725
726
727

    if (el->isLeaf()) {
      *final_el_info = *el_info;
      if (outside < 0) {
728
729
730
731
	for (int i = 0; i <= dim; i++) {
	  final_lambda[i] = lambda[i];
	}

732
	return true;
733
734
735
736
737
738
739
740
741
742
743
744
      }  else {  /* outside */
	if (g_xy0) { /* find boundary point of [xy0, xy] */
	  el_info->worldToCoord(*(g_xy0), &c_lambda);
	  double s = lambda[outside] / (lambda[outside] - c_lambda[outside]);
	  for (int i = 0; i <= dim; i++) {
	    final_lambda[i] = s * c_lambda[i] + (1.0-s) * lambda[i];
	  }
	  if (g_sp) {
	    *(g_sp) = s;
	  }
	  if (dim == 3) 
	    MSG("outside finest level on el %d: s=%.3e\n", el->getIndex(), s);
745

746
	  return false;  /* ??? */
747
	} else {
748
	  return false;
749
	}
750
      }
751
752
    }

753
    ElInfo *c_el_info = createNewElInfo();
754

755
    if (dim == 1) {
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
      if (lambda[0] >= lambda[1]) {
	c_el_info->fillElInfo(0, el_info);
	if (outside >= 0) {
	  outside = el_info->worldToCoord(*(g_xy), &c_lambda);
	  if (outside >= 0) ERROR("point outside domain\n");
	} else {
	  c_lambda[0] = lambda[0] - lambda[1];
	  c_lambda[1] = 2.0 * lambda[1];
	}
      } else {
	c_el_info->fillElInfo(1, el_info);
	if (outside >= 0)  {
	  outside = el_info->worldToCoord(*(g_xy), &c_lambda);
	  if (outside >= 0) ERROR("point outside domain\n");
	} else {
	  c_lambda[1] = lambda[1] - lambda[0];
	  c_lambda[0] = 2.0 * lambda[0];
	}
      }
    } /* DIM == 1 */

777
    if (dim == 2) {
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
      if (lambda[0] >= lambda[1]) {
	c_el_info->fillElInfo(0, el_info);
	if (el->isNewCoordSet()) {
	  outside = c_el_info->worldToCoord(*(g_xy), &c_lambda);
	  if (outside >= 0) {
	    ERROR("outside curved boundary child 0\n");
	  }
	} else {
	  c_lambda[0] = lambda[2];
	  c_lambda[1] = lambda[0] - lambda[1];
	  c_lambda[2] = 2.0 * lambda[1];
	}
      } else {
	c_el_info->fillElInfo(1, el_info);
	if (el->isNewCoordSet()) {
	  outside = c_el_info->worldToCoord(*(g_xy), &c_lambda);
	  if (outside >= 0) {
	    ERROR("outside curved boundary child 1\n");
	  }
	} else {
	  c_lambda[0] = lambda[1] - lambda[0];
	  c_lambda[1] = lambda[2];
	  c_lambda[2] = 2.0 * lambda[0];
	}
      }
    } /* DIM == 2 */

805
    if (dim == 3) {
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
      if (el->isNewCoordSet()) {
	if (lambda[0] >= lambda[1])
	  ichild = 0;
	else
	  ichild = 1;
	c_el_info->fillElInfo(ichild, el_info);
	c_outside = c_el_info->worldToCoord(*(g_xy), &c_lambda);

	if (c_outside>=0) {  /* test is other child is better... */
	  DimVec<double> c_lambda2(dim, NO_INIT);
	  int c_outside2;
	  ElInfo *c_el_info2 = createNewElInfo();

	  c_el_info2->fillElInfo(1-ichild, el_info);
	  c_outside2 = c_el_info2->worldToCoord(*(g_xy), &c_lambda2);

	  MSG("new_coord CHILD %d: outside=%d, lambda=(%.2f %.2f %.2f %.2f)\n",
	      ichild, c_outside, c_lambda[0],c_lambda[1],c_lambda[2],c_lambda[3]);
	  MSG("new_coord CHILD %d: outside=%d, lambda=(%.2f %.2f %.2f %.2f)\n",
	      1-ichild, c_outside2, c_lambda2[0],c_lambda2[1],c_lambda2[2],
	      c_lambda2[3]);

	  if ((c_outside2 < 0) || (c_lambda2[c_outside2] > c_lambda[c_outside])) {
829
830
	    for (int i = 0; i <= dim; i++) 
	      c_lambda[i] = c_lambda2[i];	    
831
832
833
834
	    c_outside = c_outside2;
	    *c_el_info = *c_el_info2;
	    ichild = 1 - ichild;
	  }
Thomas Witkowski's avatar
Thomas Witkowski committed
835
	  delete c_el_info2;
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
	}
	outside = c_outside;
      } else {  /* no new_coord */
	if (lambda[0] >= lambda[1]) {
	  c_el_info->fillElInfo(0, el_info);
	  c_lambda[0] = lambda[0] - lambda[1];
	  c_lambda[1] = lambda[Tetrahedron::childVertex[(dynamic_cast<ElInfo3d*>(el_info))->
							getType()][0][1]];
	  c_lambda[2] = lambda[Tetrahedron::childVertex[(dynamic_cast<ElInfo3d*>(el_info))->
							getType()][0][2]];
	  c_lambda[3] = 2.0 * lambda[1];
	} else {
	  c_el_info->fillElInfo(1, el_info);
	  c_lambda[0] = lambda[1] - lambda[0];
	  c_lambda[1] = lambda[Tetrahedron::childVertex[(dynamic_cast<ElInfo3d*>(el_info))->
							getType()][1][1]];
	  c_lambda[2] = lambda[Tetrahedron::childVertex[(dynamic_cast<ElInfo3d*>(el_info))->
							getType()][1][2]];
	  c_lambda[3] = 2.0 * lambda[0];
	}
      }
    }  /* DIM == 3 */

    inside = findElementAtPointRecursive(c_el_info, c_lambda, outside, 
					 final_el_info);
Thomas Witkowski's avatar
Thomas Witkowski committed
861
    delete c_el_info;
862

863
    return inside; 
864
865
  }

866
867
868
869
870
871
872
  bool Mesh::getDofIndexCoords(const DegreeOfFreedom* dof, 
			       const FiniteElemSpace* feSpace,
			       WorldVector<double>& coords)
  {
    DimVec<double>* baryCoords;
    bool found = false;
    TraverseStack stack;
Thomas Witkowski's avatar
Thomas Witkowski committed
873
874
    Vector<DegreeOfFreedom> dofVec(feSpace->getBasisFcts()->getNumber());

875
    ElInfo *elInfo = stack.traverseFirst(this, -1, 
Thomas Witkowski's avatar
Thomas Witkowski committed
876
					 Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS);    
877
    while (elInfo) {
Thomas Witkowski's avatar
Thomas Witkowski committed
878
879
880
881
882
      feSpace->getBasisFcts()->getLocalIndicesVec(elInfo->getElement(),
						  feSpace->getAdmin(),
						  &dofVec);
      for (int i = 0; i < feSpace->getBasisFcts()->getNumber(); i++) {
	if (dofVec[i] == *dof) {
883
884
885
	  baryCoords = feSpace->getBasisFcts()->getCoords(i);
	  elInfo->coordToWorld(*baryCoords, coords);
	  found = true;
Thomas Witkowski's avatar
Thomas Witkowski committed
886
	  break;	  
887
	}
Thomas Witkowski's avatar
Thomas Witkowski committed
888
889
      }
      
890
891
      if (found)
	break;
Thomas Witkowski's avatar
Thomas Witkowski committed
892
      
893
894
895
896
897
      elInfo = stack.traverseNext(elInfo);
    }

    return found;
  }
898

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
  bool Mesh::getDofIndexCoords(DegreeOfFreedom dof, 
			       const FiniteElemSpace* feSpace,
			       WorldVector<double>& coords)
  {
    DimVec<double>* baryCoords;
    bool found = false;
    TraverseStack stack;
    Vector<DegreeOfFreedom> dofVec(feSpace->getBasisFcts()->getNumber());

    ElInfo *elInfo = stack.traverseFirst(this, -1, 
					 Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS);    
    while (elInfo) {
      feSpace->getBasisFcts()->getLocalIndicesVec(elInfo->getElement(),
						  feSpace->getAdmin(),
						  &dofVec);
      for (int i = 0; i < feSpace->getBasisFcts()->getNumber(); i++) {
	if (dofVec[i] == dof) {
	  baryCoords = feSpace->getBasisFcts()->getCoords(i);
	  elInfo->coordToWorld(*baryCoords, coords);
	  found = true;
	  break;	  
	}
      }
      
      if (found)
	break;
      
      elInfo = stack.traverseNext(elInfo);
    }

    return found;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
932
933
934
935
  void Mesh::setDiameter(const WorldVector<double>& w) 
  { 
    diam = w; 
  }
936

Thomas Witkowski's avatar
Thomas Witkowski committed
937
938
939
940
  void Mesh::setDiameter(int i, double w) 
  { 
    diam[i] = w; 
  }
941
942
943
944
945
946
947
948
949
950
951
952


  int Mesh::newDOFFct1(ElInfo* ei) {
    ei->getElement()->newDOFFct1(compressAdmin);
    return 0;
  }

  int Mesh::newDOFFct2(ElInfo* ei) {
    ei->getElement()->newDOFFct2(compressAdmin);
    return 0;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
953
  void Mesh::serialize(std::ostream &out)
954
955
956
957
  {
    serializedDOFs.clear();

    // write name
Thomas Witkowski's avatar
Thomas Witkowski committed
958
    out << name << "\n";
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999

    // write dim
    out.write(reinterpret_cast<const char*>(&dim), sizeof(int));

    // write nVertices
    out.write(reinterpret_cast<const char*>(&nVertices), sizeof(int));

    // write nEdges
    out.write(reinterpret_cast<const char*>(&nEdges), sizeof(int));

    // write nLeaves
    out.write(reinterpret_cast<const char*>(&nLeaves), sizeof(int));

    // write nElements
    out.write(reinterpret_cast<const char*>(&nElements), sizeof(int));

    // write nFaces
    out.write(reinterpret_cast<const char*>(&nFaces), sizeof(int));

    // write maxEdgeNeigh
    out.write(reinterpret_cast<const char*>(&maxEdgeNeigh), sizeof(int));

    // write diam
    diam.serialize(out);

    // write preserveCoarseDOFs
    out.write(reinterpret_cast<const char*>(&preserveCoarseDOFs), sizeof(bool));

    // write nDOFEl
    out.write(reinterpret_cast<const char*>(&nDOFEl), sizeof(int));

    // write nDOF
    nDOF.serialize(out);

    // write nNodeEl
    out.write(reinterpret_cast<const char*>(&nNodeEl), sizeof(int));

    // write node
    node.serialize(out);

    // write admins
1000
    int size = static_cast<int>(admin.size());
For faster browsing, not all history is shown. View entire blame