gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
CellComplex.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 //
6 // Contributed by Matti Pellikka <matti.pellikka@gmail.com>.
7 
8 #include "CellComplex.h"
9 #include "MElement.h"
10 #include "OS.h"
11 
12 double CellComplex::_patience = 10;
13 
14 CellComplex::CellComplex(GModel *model, std::vector<MElement *> &domainElements,
15  std::vector<MElement *> &subdomainElements,
16  std::vector<MElement *> &nondomainElements,
17  std::vector<MElement *> &nonsubdomainElements,
18  std::vector<MElement *> &immuneElements,
19  bool saveOriginalComplex)
20  : _model(model), _dim(0), _simplicial(true), _saveorig(saveOriginalComplex),
21  _relative(false)
22 {
23  _smallestCell.second = -1.;
24  _biggestCell.second = -1.;
25  _deleteCount = 0;
26  _createCount = 0;
27  _insertCells(subdomainElements, 1);
28  if(getSize(0) > 0) _relative = true;
29  for(int i = 0; i < 4; i++) _numSubdomainCells[i] = getSize(i);
30 
31  _insertCells(domainElements, 0);
32  for(int i = 0; i < 4; i++)
34 
35  _removeCells(nonsubdomainElements, 1);
36  _removeCells(nondomainElements, 0);
37  _immunizeCells(immuneElements);
38  int num = 0;
39  for(int dim = 0; dim < 4; dim++) {
40  if(getSize(dim) != 0) _dim = dim;
41  if(_saveorig) _ocells[dim] = _cells[dim];
42  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
43  Cell *cell = *cit;
44  cell->setNum(++num);
45  cell->increaseGlobalNum();
46  cell->saveCellBoundary();
47  }
48  }
49 
50  _reduced = false;
51 
52  Msg::Debug("Cells in domain:");
53  Msg::Debug(" %d volumes, %d faces, %d edges, and %d vertices",
54  getNumCells(3, 1), getNumCells(2, 1), getNumCells(1, 1),
55  getNumCells(0, 1));
56  Msg::Debug("Cells in subdomain:");
57  Msg::Debug(" %d volumes, %d faces, %d edges, and %d vertices",
58  getNumCells(3, 2), getNumCells(2, 2), getNumCells(1, 2),
59  getNumCells(0, 2));
60  Msg::Debug("Cells in relative domain:");
61  Msg::Debug(" %d volumes, %d faces, %d edges, and %d vertices",
62  getNumCells(3, 0), getNumCells(2, 0), getNumCells(1, 0),
63  getNumCells(0, 0));
64 }
65 
66 bool CellComplex::_insertCells(std::vector<MElement *> &elements, int domain)
67 {
68  std::pair<Cell *, double> smallestElement[4];
69  std::pair<Cell *, double> biggestElement[4];
70  for(int i = 0; i < 4; i++) {
71  smallestElement[i].second = -1.;
72  biggestElement[i].second = -1.;
73  }
74  _dim = 0;
75 
76  double t1 = Cpu();
77 
78  for(std::size_t i = 0; i < elements.size(); i++) {
79  MElement *element = elements.at(i);
80  int dim = element->getDim();
81  int type = element->getType();
82  if(type == TYPE_POLYG || type == TYPE_POLYH) {
83  Msg::Error("Mesh element type %d not implemented in homology solver",
84  type);
85  }
86  if(type == TYPE_QUA || type == TYPE_HEX || type == TYPE_PYR ||
87  type == TYPE_PRI)
88  _simplicial = false;
89  std::pair<Cell *, bool> maybeCell = Cell::createCell(element, domain);
90  if(!maybeCell.second) {
91  delete maybeCell.first;
92  continue;
93  }
94 
95  if(_dim < dim) _dim = dim;
96  Cell *cell = maybeCell.first;
97  std::pair<citer, bool> insert = _cells[cell->getDim()].insert(cell);
98  if(!insert.second) {
99  delete cell;
100  cell = *(insert.first);
101  if(domain) cell->setDomain(domain);
102  }
103  else
104  _createCount++;
105 
106  if(domain == 0) {
107  double size = fabs(element->getVolume());
108  if(smallestElement[dim].second < 0. || smallestElement[dim].second > size)
109  smallestElement[dim] = std::make_pair(cell, size);
110  if(biggestElement[dim].second < 0. || biggestElement[dim].second < size)
111  biggestElement[dim] = std::make_pair(cell, size);
112  }
113  }
114  _smallestCell = smallestElement[_dim];
115  _biggestCell = biggestElement[_dim];
116 
117  for(int dim = 3; dim > 0; dim--) {
118  double t2 = Cpu();
119  if(t2 - t1 > CellComplex::_patience && dim > 1) {
120  if(domain == 0)
121  Msg::Info(" - Creating domain %d-cells", dim);
122  else if(domain == 1)
123  Msg::Info(" - Creating subdomain %d-cells", dim);
124  }
125 
126  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
127  Cell *cell = *cit;
128  for(int i = 0; i < cell->getNumBdElements(); i++) {
129  std::pair<Cell *, bool> maybeCell = Cell::createCell(cell, i);
130  if(!maybeCell.second) {
131  delete maybeCell.first;
132  continue;
133  }
134  Cell *newCell = maybeCell.first;
135  std::pair<citer, bool> insert =
136  _cells[newCell->getDim()].insert(newCell);
137  if(!insert.second) {
138  delete newCell;
139  newCell = *(insert.first);
140  if(domain) newCell->setDomain(domain);
141  }
142  else
143  _createCount++;
144  if(domain == 0) {
145  int ori = cell->findBdCellOrientation(newCell, i);
146  cell->addBoundaryCell(ori, newCell, true);
147  if(_smallestCell.first == cell)
148  _smallestCell = std::make_pair(newCell, _smallestCell.second);
149  if(_biggestCell.first == cell)
150  _biggestCell = std::make_pair(newCell, _biggestCell.second);
151  }
152  }
153  }
154  }
155  return true;
156 }
157 
158 bool CellComplex::_removeCells(std::vector<MElement *> &elements, int domain)
159 {
160  if(elements.empty()) return true;
161  Msg::Debug("Removing %d elements and their subcells from the cell complex.",
162  (int)elements.size());
163  std::set<Cell *, CellPtrLessThan> removed[4];
164 
165  for(std::size_t i = 0; i < elements.size(); i++) {
166  MElement *element = elements.at(i);
167  int type = element->getType();
168  if(type == TYPE_PYR || type == TYPE_PRI || type == TYPE_POLYG ||
169  type == TYPE_POLYH) {
170  Msg::Error("Mesh element type %d not implemented in homology solver",
171  type);
172  return false;
173  }
174  Cell *cell = new Cell(element, domain);
175  int dim = cell->getDim();
176  auto cit = _cells[dim].find(cell);
177  if(cit != lastCell(dim)) {
178  removeCell(*cit);
179  removed[dim].insert(cell);
180  }
181  else
182  delete cell;
183  }
184 
185  for(int dim = 3; dim > 0; dim--) {
186  for(auto cit = removed[dim].begin(); cit != removed[dim].end(); cit++) {
187  Cell *cell = *cit;
188  for(int i = 0; i < cell->getNumBdElements(); i++) {
189  Cell *newCell = new Cell(cell, i);
190 
191  auto cit2 = _cells[dim - 1].find(newCell);
192  if(cit2 != lastCell(dim - 1)) {
193  removeCell(*cit2);
194  removed[dim - 1].insert(newCell);
195  }
196  else
197  delete newCell;
198  }
199  }
200  }
201  for(int dim = 3; dim >= 0; dim--) {
202  for(auto cit = removed[dim].begin(); cit != removed[dim].end(); cit++) {
203  delete *cit;
204  }
205  }
206  Msg::Debug("Removed %d volumes, %d faces, %d edges, and %d vertices from the "
207  "cell complex",
208  (int)removed[3].size(), (int)removed[2].size(),
209  (int)removed[1].size(), (int)removed[0].size());
210  return true;
211 }
212 
213 bool CellComplex::_immunizeCells(std::vector<MElement *> &elements)
214 {
215  for(std::size_t i = 0; i < elements.size(); i++) {
216  MElement *element = elements.at(i);
217  Cell *cell = new Cell(element, 0);
218  int dim = cell->getDim();
219  auto cit = _cells[dim].find(cell);
220  if(cit != lastCell(dim)) (*cit)->setImmune(true);
221  delete cell;
222  }
223  return true;
224 }
225 
227 {
228  for(int i = 0; i < 4; i++) {
229  for(auto cit = _cells[i].begin(); cit != _cells[i].end(); cit++) {
230  Cell *cell = *cit;
231  delete cell;
232  _deleteCount++;
233  }
234  }
235 
236  for(std::size_t i = 0; i < _removedcells.size(); i++) {
237  delete _removedcells.at(i);
238  _deleteCount++;
239  }
240 
241  Msg::Debug("Total number of cells created: %d", _createCount);
242  Msg::Debug("Total number of cells deleted: %d", _deleteCount);
243 }
244 
246 {
247  std::pair<citer, bool> insertInfo = _cells[cell->getDim()].insert(cell);
248  if(!insertInfo.second) {
249  Msg::Debug("Cell not inserted");
250  Cell *oldCell = (*insertInfo.first);
251  cell->printCell();
252  oldCell->printCell();
253  }
254 }
255 
256 void CellComplex::removeCell(Cell *cell, bool other, bool del)
257 {
258  std::map<Cell *, short int, CellPtrLessThan> coboundary;
259  cell->getCoboundary(coboundary);
260  std::map<Cell *, short int, CellPtrLessThan> boundary;
261  cell->getBoundary(boundary);
262 
263  for(auto it = coboundary.begin(); it != coboundary.end(); it++) {
264  Cell *cbdCell = (*it).first;
265  cbdCell->removeBoundaryCell(cell, other);
266  }
267 
268  for(auto it = boundary.begin(); it != boundary.end(); it++) {
269  Cell *bdCell = (*it).first;
270  bdCell->removeCoboundaryCell(cell, other);
271  }
272 
273  int dim = cell->getDim();
274  int erased = _cells[dim].erase(cell);
275  if(relative()) {
276  if(cell->inSubdomain())
277  _numSubdomainCells[dim] -= 1;
278  else
279  _numRelativeCells[dim] -= 1;
280  }
281  if(!erased)
282  Msg::Debug("Tried to remove a cell from the cell complex \n");
283  else if(!del)
284  _removedcells.push_back(cell);
285 }
286 
288  std::map<Cell *, short int, CellPtrLessThan> &cells, std::queue<Cell *> &Q,
289  std::set<Cell *, CellPtrLessThan> &Qset)
290 {
291  for(auto cit = cells.begin(); cit != cells.end(); cit++) {
292  Cell *cell = (*cit).first;
293  auto it = Qset.find(cell);
294  if(it == Qset.end()) {
295  Qset.insert(cell);
296  Q.push(cell);
297  }
298  }
299 }
300 
301 int CellComplex::coreduction(Cell *startCell, int omit,
302  std::vector<Cell *> &omittedCells)
303 {
304  int coreductions = 0;
305 
306  std::queue<Cell *> Q;
307  std::set<Cell *, CellPtrLessThan> Qset;
308 
309  Q.push(startCell);
310  Qset.insert(startCell);
311 
312  std::map<Cell *, short int, CellPtrLessThan> bd_s;
313  std::map<Cell *, short int, CellPtrLessThan> cbd_c;
314 
315  Cell *s;
316  while(!Q.empty()) {
317  s = Q.front();
318  Q.pop();
319  Qset.erase(s);
320  if(s->getBoundarySize() == 1 &&
321  inSameDomain(s, s->firstBoundary()->first) && !s->getImmune() &&
322  !s->firstBoundary()->first->getImmune() &&
323  abs(s->firstBoundary()->second.get()) < 2) {
324  s->getBoundary(bd_s);
325  removeCell(s);
326  bd_s.begin()->first->getCoboundary(cbd_c);
327  enqueueCells(cbd_c, Q, Qset);
328  removeCell(bd_s.begin()->first);
329  if(bd_s.begin()->first->getDim() == omit) {
330  omittedCells.push_back(bd_s.begin()->first);
331  }
332  coreductions++;
333  }
334  else if(s->getBoundarySize() == 0) {
335  s->getCoboundary(cbd_c);
336  enqueueCells(cbd_c, Q, Qset);
337  }
338  }
339  _reduced = true;
340  return coreductions;
341 }
342 
343 int CellComplex::reduction(int dim, int omit, std::vector<Cell *> &omittedCells)
344 {
345  if(dim < 1 || dim > 3) return 0;
346 
347  int numCells[4];
348  for(int i = 0; i < 4; i++) numCells[i] = getSize(i);
349 
350  int count = 0;
351 
352  bool reduced = true;
353  while(reduced) {
354  reduced = false;
355  auto cit = firstCell(dim - 1);
356  while(cit != lastCell(dim - 1)) {
357  Cell *cell = *cit;
358  if(cell->getCoboundarySize() == 1 &&
359  inSameDomain(cell, cell->firstCoboundary()->first) &&
360  !cell->getImmune() && !cell->firstCoboundary()->first->getImmune() &&
361  !cell->firstCoboundary()->first->getImmune() &&
362  abs(cell->firstCoboundary()->second.get()) < 2) {
363  cit++;
364  if(dim == omit) {
365  omittedCells.push_back(cell->firstCoboundary()->first);
366  }
367  removeCell(cell->firstCoboundary()->first);
368  removeCell(cell);
369  count++;
370  reduced = true;
371  }
372 
373  if(getSize(dim) == 0 || getSize(dim - 1) == 0) break;
374  if(cit != lastCell(dim - 1)) cit++;
375  }
376  }
377  _reduced = true;
378  Msg::Debug("Cell complex %d-reduction removed %dv, %df, %de, %dn", dim,
379  numCells[3] - getSize(3), numCells[2] - getSize(2),
380  numCells[1] - getSize(1), numCells[0] - getSize(0));
381  return count;
382 }
383 
384 int CellComplex::coreduction(int dim, int omit,
385  std::vector<Cell *> &omittedCells)
386 {
387  if(dim < 1 || dim > 3) return 0;
388 
389  int numCells[4];
390  for(int i = 0; i < 4; i++) numCells[i] = getSize(i);
391 
392  int count = 0;
393 
394  bool reduced = true;
395  while(reduced) {
396  reduced = false;
397  auto cit = firstCell(dim);
398  while(cit != lastCell(dim)) {
399  Cell *cell = *cit;
400  if(cell->getBoundarySize() == 1 &&
401  inSameDomain(cell, cell->firstBoundary()->first) &&
402  !cell->getImmune() && !cell->firstBoundary()->first->getImmune() &&
403  abs(cell->firstBoundary()->second.get()) < 2) {
404  ++cit;
405  if(dim - 1 == omit) {
406  omittedCells.push_back(cell->firstBoundary()->first);
407  }
408  removeCell(cell->firstBoundary()->first);
409  removeCell(cell);
410  count++;
411  reduced = true;
412  }
413 
414  if(getSize(dim) == 0 || getSize(dim - 1) == 0) break;
415  if(cit != lastCell(dim)) cit++;
416  }
417  }
418  _reduced = true;
419  Msg::Debug("Cell complex %d-coreduction removed %dv, %df, %de, %dn", dim,
420  numCells[3] - getSize(3), numCells[2] - getSize(2),
421  numCells[1] - getSize(1), numCells[0] - getSize(0));
422  return count;
423 }
424 
425 int CellComplex::getSize(int dim, bool orig)
426 {
427  if(dim == -1) {
428  std::size_t size = 0;
429  if(!orig)
430  for(int i = 0; i < 4; i++) size += _cells[i].size();
431  else
432  for(int i = 0; i < 4; i++) size += _ocells[i].size();
433  return size;
434  }
435  if(!orig)
436  return _cells[dim].size();
437  else
438  return _ocells[dim].size();
439 }
440 
441 int CellComplex::getDomain(Cell *cell, std::string &str)
442 {
443  int domain = 0;
444  if(cell->inSubdomain()) {
445  str = "subdomain";
446  domain = 2;
447  }
448  if(!cell->inSubdomain()) {
449  if(relative()) {
450  str = "relative domain";
451  domain = 0;
452  }
453  else {
454  str = "domain";
455  domain = 1;
456  }
457  }
458  return domain;
459 }
460 
461 Cell *CellComplex::_omitCell(Cell *cell, bool dual)
462 {
463  Msg::Debug("Omitting %d-cell from the cell complex", cell->getDim());
464  removeCell(cell, false);
465  std::vector<Cell *> omittedCells;
466  omittedCells.push_back(cell);
467  int count = 0;
468 
469  int numCells[4];
470  for(int i = 0; i < 4; i++) numCells[i] = getSize(i);
471 
472  if(!dual) {
473  for(int j = 3; j > 0; j--)
474  count += reduction(j, cell->getDim(), omittedCells);
475  }
476  else {
477  count += coreduction(cell, cell->getDim(), omittedCells);
478  for(int j = 1; j <= getDim(); j++)
479  count += coreduction(j, cell->getDim(), omittedCells);
480  }
481 
482  CombinedCell *newcell = new CombinedCell(omittedCells);
483  _createCount++;
484 
485  std::string domainstr = "";
486  int domain = getDomain(cell, domainstr);
487 
488  Msg::Debug("Cell complex %d-omit removed %dv, %df, %de, %dn (total %d)",
489  cell->getDim(),
490  numCells[3] - getSize(3), numCells[2] - getSize(2),
491  numCells[1] - getSize(1), numCells[0] - getSize(0),
492  count);
493  Msg::Debug(" - number of %d-cells left in %s: %d", cell->getDim(),
494  domainstr.c_str(), getNumCells(cell->getDim(), domain));
495 
496  return newcell;
497 }
498 
499 int CellComplex::reduceComplex(int combine, bool omit, bool homseq)
500 {
501  if(!getSize(0)) return 0;
502 
503  double t1 = Cpu();
504  int count = 0;
505  if(relative() && !homseq) removeSubdomain();
506  std::vector<Cell *> empty;
507  for(int i = 3; i > 0; i--) count = count + reduction(i, -1, empty);
508 
509  if(omit && !homseq) {
510  std::vector<Cell *> newCells;
511 
512  while(getSize(getDim()) != 0) {
513  auto cit = firstCell(getDim());
514  Cell *cell = *cit;
515 
516  newCells.push_back(_omitCell(cell, false));
517  }
518 
519  for(std::size_t i = 0; i < newCells.size(); i++) {
520  insertCell(newCells.at(i));
521  }
522  }
523 
524  double t2 = Cpu();
525  if(t2 - t1 > CellComplex::_patience) {
526  Msg::Info(" - %d volumes, %d faces, %d edges, and %d vertices", getSize(3),
527  getSize(2), getSize(1), getSize(0));
528  }
529 
530  if(combine > 0) this->combine(3);
531 
532  if(combine > 2)
533  for(int i = 3; i > 0; i--) reduction(i, -1, empty);
534  else if(combine > 1)
535  reduction(2, -1, empty);
536 
537  if(combine > 0) this->combine(2);
538 
539  if(combine > 2)
540  for(int i = 3; i > 0; i--) reduction(i, -1, empty);
541  else if(combine > 1)
542  reduction(1, -1, empty);
543 
544  if(combine > 0) this->combine(1);
545 
546  if(combine > 2)
547  for(int i = 3; i > 0; i--) reduction(i, -1, empty);
548  else if(combine > 1)
549  reduction(0, -1, empty);
550 
551  _reduced = true;
552  return count;
553 }
554 
556 {
557  std::vector<Cell *> toRemove;
558  for(int i = 0; i < 4; i++) {
559  for(auto cit = firstCell(i); cit != lastCell(i); ++cit) {
560  Cell *cell = *cit;
561  if(cell->inSubdomain()) toRemove.push_back(cell);
562  }
563  }
564  for(std::size_t i = 0; i < toRemove.size(); i++) removeCell(toRemove[i]);
565  _reduced = true;
566 }
567 
569 {
570  if(dim < 0 || dim > 3) return;
571  std::vector<Cell *> toRemove;
572  for(auto cit = firstCell(dim); cit != lastCell(dim); ++cit) {
573  toRemove.push_back(*cit);
574  }
575  for(std::size_t i = 0; i < toRemove.size(); i++) removeCell(toRemove[i]);
576  _reduced = true;
577 }
578 
579 int CellComplex::coreduceComplex(int combine, bool omit, int heuristic)
580 {
581  if(!getSize(0)) return 0;
582 
583  double t1 = Cpu();
584 
585  int count = 0;
586  if(relative()) removeSubdomain();
587  std::vector<Cell *> empty;
588  for(int dim = 0; dim < 4; dim++) {
589  auto cit = firstCell(dim);
590  while(cit != lastCell(dim)) {
591  Cell *cell = *cit;
592  int count = +coreduction(cell, -1, empty);
593  if(count != 0) break;
594  cit++;
595  }
596  }
597 
598  for(int j = 1; j <= getDim(); j++) count += coreduction(j, -1, empty);
599 
600  if(omit) {
601  std::vector<Cell *> newCells;
602  while(getSize(0) != 0) {
603  auto cit = firstCell(0);
604  Cell *cell = *cit;
605 
606  if(heuristic == -1 && _smallestCell.second != 0. &&
607  hasCell(_smallestCell.first)) {
608  Msg::Debug("Omitted a cell in the smallest mesh element with volume %g",
609  _smallestCell.second);
610  cell = _smallestCell.first;
611  }
612  else if(heuristic == 1 && _biggestCell.second != 0. &&
613  hasCell(_biggestCell.first)) {
614  Msg::Debug("Omitted a cell in the biggest mesh element with volume %g",
615  _biggestCell.second);
616  cell = _biggestCell.first;
617  }
618 
619  newCells.push_back(_omitCell(cell, true));
620  }
621  for(std::size_t i = 0; i < newCells.size(); i++) {
622  insertCell(newCells.at(i));
623  }
624  }
625 
626  double t2 = Cpu();
627  if(t2 - t1 > CellComplex::_patience) {
628  Msg::Info(" - %d volumes, %d faces, %d edges, and %d vertices", getSize(3),
629  getSize(2), getSize(1), getSize(0));
630  }
631 
632  if(combine > 0) this->cocombine(0);
633 
634  if(combine > 2)
635  for(int i = 1; i < 4; i++) coreduction(i, -1, empty);
636  else if(combine > 1)
637  coreduction(1, -1, empty);
638 
639  if(combine > 0) this->cocombine(1);
640 
641  if(combine > 2)
642  for(int i = 1; i < 4; i++) coreduction(i, -1, empty);
643  else if(combine > 1)
644  coreduction(2, -1, empty);
645 
646  if(combine > 0) this->cocombine(2);
647 
648  if(combine > 2)
649  for(int i = 1; i < 4; i++) coreduction(i, -1, empty);
650  else if(combine > 1)
651  coreduction(3, -1, empty);
652 
653  coherent();
654 
655  _reduced = true;
656  return count;
657 }
658 
660 {
661  reduceComplex(3, true);
662  for(int i = 1; i <= 3; i++) cocombine(i - 1);
663  return;
664 }
665 
667 {
668  if(dim < 1 || dim > 3) return 0;
669 
670  int numCells[4];
671  for(int i = 0; i < 4; i++) numCells[i] = getSize(i);
672 
673  double t1 = Cpu();
674 
675  std::queue<Cell *> Q;
676  std::set<Cell *, CellPtrLessThan> Qset;
677  std::map<Cell *, short int, CellPtrLessThan> bd_c;
678  int count = 0;
679 
680  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
681  double t2 = Cpu();
682  if(t2 - t1 > CellComplex::_patience) {
683  t1 = Cpu();
684  Msg::Info(" - %d volumes, %d faces, %d edges, and %d vertices",
685  getSize(3), getSize(2), getSize(1), getSize(0));
686  }
687 
688  Cell *cell = *cit;
689  cell->getBoundary(bd_c);
690  enqueueCells(bd_c, Q, Qset);
691 
692  while(Q.size() != 0) {
693  Cell *s = Q.front();
694  Q.pop();
695 
696  if(s->getCoboundarySize() == 2 && !s->getImmune()) {
697  auto it = s->firstCoboundary();
698  int or1 = it->second.get();
699  Cell *c1 = it->first;
700  it++;
701  while(it->second.get() == 0) it++;
702  int or2 = it->second.get();
703  Cell *c2 = it->first;
704 
705  if(!(*c1 == *c2) && abs(or1) == abs(or2) && inSameDomain(s, c1) &&
706  inSameDomain(s, c2) && c1->getImmune() == c2->getImmune()) {
707  removeCell(s, true, false);
708 
709  c1->getBoundary(bd_c);
710  enqueueCells(bd_c, Q, Qset);
711  c2->getBoundary(bd_c);
712  enqueueCells(bd_c, Q, Qset);
713 
714  CombinedCell *newCell = new CombinedCell(c1, c2, (or1 != or2));
715  _createCount++;
716  removeCell(c1, true, c1->isCombined());
717  removeCell(c2, true, c2->isCombined());
718  insertCell(newCell);
719 
720  cit = firstCell(dim);
721  count++;
722 
723  if(c1->isCombined()) {
724  delete c1;
725  _deleteCount++;
726  }
727  if(c2->isCombined()) {
728  delete c2;
729  _deleteCount++;
730  }
731  }
732  }
733  Qset.erase(s);
734  }
735  }
736 
737  Msg::Debug("Cell complex %d-combine removed %dv, %df, %de, %dn", dim,
738  numCells[3] - getSize(3), numCells[2] - getSize(2),
739  numCells[1] - getSize(1), numCells[0] - getSize(0));
740  _reduced = true;
741  return count;
742 }
743 
745 {
746  if(dim < 0 || dim > 2) return 0;
747 
748  int numCells[4];
749  for(int i = 0; i < 4; i++) numCells[i] = getSize(i);
750 
751  double t1 = Cpu();
752 
753  std::queue<Cell *> Q;
754  std::set<Cell *, CellPtrLessThan> Qset;
755  std::map<Cell *, short int, CellPtrLessThan> cbd_c;
756  int count = 0;
757 
758  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
759  double t2 = Cpu();
760  if(t2 - t1 > CellComplex::_patience) {
761  t1 = Cpu();
762  Msg::Info(" - %d volumes, %d faces, %d edges, and %d vertices",
763  getSize(3), getSize(2), getSize(1), getSize(0));
764  }
765 
766  Cell *cell = *cit;
767 
768  cell->getCoboundary(cbd_c);
769  enqueueCells(cbd_c, Q, Qset);
770 
771  while(Q.size() != 0) {
772  Cell *s = Q.front();
773  Q.pop();
774  if(s->getBoundarySize() == 2) {
775  auto it = s->firstBoundary();
776  int or1 = it->second.get();
777  Cell *c1 = it->first;
778  it++;
779  while(it->second.get() == 0) it++;
780  int or2 = it->second.get();
781  Cell *c2 = it->first;
782 
783  if(!(*c1 == *c2) && abs(or1) == abs(or2) && inSameDomain(s, c1) &&
784  inSameDomain(s, c2) && c1->getImmune() == c2->getImmune()) {
785  removeCell(s, true, false);
786 
787  c1->getCoboundary(cbd_c);
788  enqueueCells(cbd_c, Q, Qset);
789  c2->getCoboundary(cbd_c);
790  enqueueCells(cbd_c, Q, Qset);
791 
792  CombinedCell *newCell = new CombinedCell(c1, c2, (or1 != or2), true);
793  _createCount++;
794  removeCell(c1, true, c1->isCombined());
795  removeCell(c2, true, c2->isCombined());
796  insertCell(newCell);
797 
798  cit = firstCell(dim);
799  count++;
800 
801  if(c1->isCombined()) {
802  delete c1;
803  _deleteCount++;
804  }
805  if(c2->isCombined()) {
806  delete c2;
807  _deleteCount++;
808  }
809  }
810  }
811  Qset.erase(s);
812  }
813  }
814 
815  Msg::Debug("Cell complex %d-cocombine removed %dv, %df, %de, %dn", dim,
816  numCells[3] - getSize(3), numCells[2] - getSize(2),
817  numCells[1] - getSize(1), numCells[0] - getSize(0));
818  _reduced = true;
819  return count;
820 }
821 
823 {
824  bool coherent = true;
825  for(int i = 0; i < 4; i++) {
826  for(auto cit = firstCell(i); cit != lastCell(i); cit++) {
827  Cell *cell = *cit;
828  std::map<Cell *, short int, CellPtrLessThan> boundary;
829  cell->getBoundary(boundary);
830  for(auto it = boundary.begin(); it != boundary.end(); it++) {
831  Cell *bdCell = (*it).first;
832  int ori = (*it).second;
833  auto cit = _cells[bdCell->getDim()].find(bdCell);
834  if(cit == lastCell(bdCell->getDim())) {
835  Msg::Debug("Boundary cell not in cell complex! Boundary removed");
836  cell->removeBoundaryCell(bdCell, false);
837  coherent = false;
838  }
839  if(!bdCell->hasCoboundary(cell)) {
840  Msg::Debug("Incoherent boundary/coboundary pair! Fixed");
841  bdCell->addCoboundaryCell(ori, cell, false);
842  coherent = false;
843  }
844  }
845  std::map<Cell *, short int, CellPtrLessThan> coboundary;
846  cell->getCoboundary(coboundary);
847  for(auto it = coboundary.begin(); it != coboundary.end(); it++) {
848  Cell *cbdCell = (*it).first;
849  int ori = (*it).second;
850  auto cit = _cells[cbdCell->getDim()].find(cbdCell);
851  if(cit == lastCell(cbdCell->getDim())) {
852  Msg::Debug("Coboundary cell not in cell complex! Coboundary removed");
853  cell->removeCoboundaryCell(cbdCell, false);
854  coherent = false;
855  }
856  if(!cbdCell->hasBoundary(cell)) {
857  Msg::Debug("Incoherent coboundary/boundary pair! Fixed");
858  cbdCell->addBoundaryCell(ori, cell, false);
859  coherent = false;
860  }
861  }
862  }
863  }
864  return coherent;
865 }
866 
867 bool CellComplex::hasCell(Cell *cell, bool orig)
868 {
869  citer cit;
870  if(!orig)
871  cit = _cells[cell->getDim()].find(cell);
872  else
873  cit = _ocells[cell->getDim()].find(cell);
874  if(cit == lastCell(cell->getDim(), orig))
875  return false;
876  else
877  return true;
878 }
879 
880 void CellComplex::getCells(std::set<Cell *, CellPtrLessThan> &cells, int dim,
881  int domain)
882 {
883  cells.clear();
884  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
885  Cell *cell = *cit;
886  if((domain == 0 && !cell->inSubdomain()) || domain == 1 ||
887  (domain == 2 && cell->inSubdomain())) {
888  cells.insert(cell);
889  }
890  }
891 }
892 
893 int CellComplex::getNumCells(int dim, int domain)
894 {
895  if(domain == 0)
896  return _numRelativeCells[dim];
897  else if(domain == 1)
898  return getSize(dim);
899  else if(domain == 2)
900  return _numSubdomainCells[dim];
901  return 0;
902 }
903 
904 Cell *CellComplex::getACell(int dim, int domain)
905 {
906  int num = getNumCells(dim, domain);
907  if(num < 0) Msg::Debug("Domain cell counts not in sync.");
908 
909  if(num <= 0) {
910  if(domain == 0)
911  Msg::Warning("%d cells in relative domain", num);
912  else if(domain == 1)
913  Msg::Warning("%d cells in domain", num);
914  else if(domain == 2)
915  Msg::Warning("%d cells in subdomain", num);
916  return nullptr;
917  }
918 
919  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
920  Cell *cell = *cit;
921  if((domain == 1) || (domain == 0 && !cell->inSubdomain()) ||
922  (domain == 2 && cell->inSubdomain()))
923  return cell;
924  }
925  Msg::Debug("Domain cell counts not in sync.");
926  return nullptr;
927 }
928 
930 {
931  if(_saveorig) {
932  for(std::size_t i = 0; i < _removedcells.size(); i++) {
933  Cell *cell = _removedcells.at(i);
934  if(cell->isCombined()) {
935  delete cell;
936  _deleteCount++;
937  }
938  }
939  _removedcells.clear();
940 
941  for(int i = 0; i < 4; i++) {
942  for(auto cit = _cells[i].begin(); cit != _cells[i].end(); cit++) {
943  Cell *cell = *cit;
944  if(cell->isCombined()) {
945  delete cell;
946  _deleteCount++;
947  }
948  }
949 
950  _cells[i] = _ocells[i];
951  for(auto cit = firstCell(i); cit != lastCell(i); cit++) {
952  Cell *cell = *cit;
953  cell->restoreCellBoundary();
954  if(relative()) {
955  if(cell->inSubdomain())
956  _numSubdomainCells[i] += 1;
957  else
958  _numRelativeCells[i] += 1;
959  }
960  }
961  }
962 
963  Msg::Info("Restored Cell Complex:");
964  Msg::Info("%d volumes, %d faces, %d edges, and %d vertices", getSize(3),
965  getSize(2), getSize(1), getSize(0));
966  _reduced = false;
967  return true;
968  }
969  else {
970  Msg::Error("Cannot restore cell complex");
971  return false;
972  }
973 }
974 
976 {
977  if(getSize(dim) == 0) Msg::Info("Cell complex dimension %d is empty", dim);
978  for(auto cit = firstCell(dim); cit != lastCell(dim); cit++) {
979  Cell *cell = *cit;
980  cell->printCell();
981  cell->printBoundary();
982  cell->printCoboundary();
983  printf("--- \n");
984  }
985 }
986 
987 int CellComplex::saveComplex(const std::string &filename)
988 {
989  /*FILE *fp = Fopen (filename.c_str(), "w");
990  if(!fp){
991  printf("\nUnable to open file '%s' \n", filename.c_str());
992  return 0;
993  }
994  printf("\nWriting file '%s'...\n", filename.c_str());
995 
996  fprintf(fp, "$Cells\n");
997  fprintf(fp, "%d\n", getSize(0)+getSize(1)+getSize(2)+getSize(3));
998  for(int dim = 0; dim < 4; dim++){
999  for(citer cit = firstCell(dim); cit != lastCell(dim); cit++){
1000  Cell* cell = *cit;
1001  fprintf(fp, "%d %d %d %d %lu", cell->getNum(), cell->getType(),
1002  1, cell->getDomain(), cell->getNumVertices());
1003  for(std::size_t i = 0; i < cell->getNumVertices(); i++){
1004  fprintf(fp, " %d", cell->getVertex(i));
1005  }
1006  fprintf(fp, " %d", cell->getBoundarySize());
1007  for(Cell::biter bit = cell->firstBoundary();
1008  bit != cell->lastBoundary(); bit++){
1009  fprintf(fp, " %d %d", bit->first->getNum(), bit->second);
1010  }
1011  fprintf(fp, " %d", cell->getCoboundarySize());
1012  for(Cell::biter bit = cell->firstCoboundary();
1013  bit != cell->lastCoboundary(); bit++){
1014  fprintf(fp, " %d %d", bit->first->getNum(), bit->second);
1015  }
1016  fprintf(fp, "\n");
1017  }
1018  }
1019 
1020  fclose(fp);
1021 
1022  printf("Wrote %d cells to '%s' \n",
1023  getSize(0)+getSize(1)+getSize(2)+getSize(3), filename.c_str());
1024  */
1025  return 1;
1026 }
1027 
1028 int CellComplex::loadComplex(const std::string &filename)
1029 {
1030  /* FILE *fp = Fopen (filename.c_str(), "r");
1031  if(!fp){
1032  printf("\nUnable to open file '%s' \n", filename.c_str());
1033  return 0;
1034  }
1035 
1036  std::map<int, Cell*> numToCell;
1037 
1038  char str[256] = "XXX";
1039  while(1) {
1040 
1041  while(str[0] != '$'){
1042  if(!fgets(str, sizeof(str), fp) || feof(fp))
1043  break;
1044  }
1045 
1046  if(feof(fp))
1047  break;
1048 
1049  if(!strncmp(&str[1], "Cells", 5)) {
1050  if(!fgets(str, sizeof(str), fp)) return 0;
1051  int numCells;
1052  sscanf(str, "%d", &numCells);
1053  for(int i = 0; i < numCells; i++) {
1054  int num, type, numTags;
1055  std::vector<int> domain;
1056  int tag;
1057  if(fscanf(fp, "%d %d %d", &num, &type, &numTags) != 3) return 0;
1058  for(int j = 0; j < numTags; j++){
1059  if(fscanf(fp, "%d", &tag) != 1) return 0;
1060  domain.push_back(tag);
1061  }
1062 
1063  std::vector<int> vertices;
1064  if(fscanf(fp, "%d", &numTags) != 1) return 0;
1065  for(int j = 0; j < numTags; j++){
1066  if(fscanf(fp, "%d", &tag) != 1) return 0;
1067  vertices.push_back(tag);
1068  }
1069 
1070  int dim = 0;
1071  if(type == 1){
1072  if(vertices.size() == 2) dim = 1;
1073  else if(vertices.size() == 3) dim = 2;
1074  else if(vertices.size() == 4) dim = 3;
1075  }
1076 
1077  Cell* cell = new Cell(num, dim, type, domain, vertices);
1078  numToCell[num] = cell;
1079 
1080 
1081  int numCell;
1082  if(fscanf(fp, "%d", &numTags) != 1) return 0;
1083  for(int j = 0; j < numTags; j++){
1084  if(fscanf(fp, "%d %d", &numCell, &tag) != 1) return 0;
1085  }
1086  if(fscanf(fp, "%d", &numTags) != 1) return 0;
1087  for(int j = 0; j < numTags; j++){
1088  if(fscanf(fp, "%d %d", &numCell, &tag) != 1) return 0;
1089  }
1090 
1091  }
1092  }
1093 
1094  }
1095 
1096  fclose(fp);
1097 */
1098  return 1;
1099 }
CellComplex::_saveorig
bool _saveorig
Definition: CellComplex.h:48
CellComplex::removeCells
void removeCells(int dim)
Definition: CellComplex.cpp:568
CellComplex::getCells
void getCells(std::set< Cell *, CellPtrLessThan > &cells, int dim, int domain=0)
Definition: CellComplex.cpp:880
Cell::getCoboundarySize
int getCoboundarySize(bool orig=false)
Definition: Cell.cpp:661
CellComplex::citer
std::set< Cell *, CellPtrLessThan >::iterator citer
Definition: CellComplex.h:120
CellComplex::CellComplex
CellComplex(GModel *model, std::vector< MElement * > &domainElements, std::vector< MElement * > &subdomainElements, std::vector< MElement * > &nondomainElements, std::vector< MElement * > &nonsubdomainElements, std::vector< MElement * > &immuneElements, bool saveOriginalComplex=true)
Definition: CellComplex.cpp:14
Cell::isCombined
bool isCombined() const
Definition: Cell.h:147
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
Cell::hasBoundary
bool hasBoundary(Cell *cell, bool orig=false)
Definition: Cell.cpp:597
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Cell::saveCellBoundary
void saveCellBoundary()
Definition: Cell.cpp:517
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
CellComplex::getSize
int getSize(int dim, bool orig=false)
Definition: CellComplex.cpp:425
CellComplex::_removeCells
bool _removeCells(std::vector< MElement * > &elements, int domain)
Definition: CellComplex.cpp:158
CellComplex::_removedcells
std::vector< Cell * > _removedcells
Definition: CellComplex.h:39
Cell::setNum
void setNum(int num)
Definition: Cell.h:80
CellComplex::_smallestCell
std::pair< Cell *, double > _smallestCell
Definition: CellComplex.h:26
Cell::removeCoboundaryCell
void removeCoboundaryCell(Cell *cell, bool other)
Definition: Cell.cpp:587
Cell::hasCoboundary
bool hasCoboundary(Cell *cell, bool orig=false)
Definition: Cell.cpp:611
Cell::printCoboundary
virtual void printCoboundary()
Definition: Cell.cpp:707
CellComplex::getACell
Cell * getACell(int dim, int domain=0)
Definition: CellComplex.cpp:904
CellComplex::_numRelativeCells
int _numRelativeCells[4]
Definition: CellComplex.h:59
CellComplex::coreduction
int coreduction(Cell *startCell, int omit, std::vector< Cell * > &omittedCells)
Definition: CellComplex.cpp:301
Cell::removeBoundaryCell
void removeBoundaryCell(Cell *cell, bool other)
Definition: Cell.cpp:577
CellComplex::_deleteCount
int _deleteCount
Definition: CellComplex.h:53
CellComplex::lastCell
citer lastCell(int dim, bool orig=false)
Definition: CellComplex.h:127
Cell::increaseGlobalNum
void increaseGlobalNum()
Definition: Cell.h:98
TYPE_PRI
#define TYPE_PRI
Definition: GmshDefines.h:70
Cell::firstBoundary
biter firstBoundary(bool orig=false)
Definition: Cell.cpp:625
Cell::addCoboundaryCell
void addCoboundaryCell(int orientation, Cell *cell, bool other)
Definition: Cell.cpp:560
CellComplex::_cells
std::set< Cell *, CellPtrLessThan > _cells[4]
Definition: CellComplex.h:33
CellComplex::_ocells
std::set< Cell *, CellPtrLessThan > _ocells[4]
Definition: CellComplex.h:36
CellComplex::_dim
int _dim
Definition: CellComplex.h:42
Cell::getImmune
bool getImmune() const
Definition: Cell.h:87
Cell::getDim
virtual int getDim() const
Definition: Cell.h:82
CellComplex::coreduceComplex
int coreduceComplex(int combine=1, bool omit=true, int heuristic=0)
Definition: CellComplex.cpp:579
Cell::inSubdomain
bool inSubdomain() const
Definition: Cell.h:83
CellComplex::removeCell
void removeCell(Cell *cell, bool other=true, bool del=false)
Definition: CellComplex.cpp:256
Cell::getBoundarySize
int getBoundarySize(bool orig=false)
Definition: Cell.cpp:649
CellComplex::~CellComplex
~CellComplex()
Definition: CellComplex.cpp:226
CellComplex::_simplicial
bool _simplicial
Definition: CellComplex.h:45
CellComplex::coherent
bool coherent()
Definition: CellComplex.cpp:822
CellComplex::_relative
bool _relative
Definition: CellComplex.h:51
CellComplex::_insertCells
bool _insertCells(std::vector< MElement * > &elements, int domain)
Definition: CellComplex.cpp:66
Cell::findBdCellOrientation
int findBdCellOrientation(Cell *cell, int i) const
Definition: Cell.cpp:194
CellComplex::getDomain
int getDomain(Cell *cell, std::string &str)
Definition: CellComplex.cpp:441
GModel
Definition: GModel.h:44
Cpu
double Cpu()
Definition: OS.cpp:366
CellComplex::_immunizeCells
bool _immunizeCells(std::vector< MElement * > &elements)
Definition: CellComplex.cpp:213
Cell
Definition: Cell.h:42
CellComplex::_biggestCell
std::pair< Cell *, double > _biggestCell
Definition: CellComplex.h:27
CellComplex::_omitCell
Cell * _omitCell(Cell *cell, bool dual)
Definition: CellComplex.cpp:461
CellComplex::removeSubdomain
void removeSubdomain()
Definition: CellComplex.cpp:555
MElement
Definition: MElement.h:30
CellComplex::insertCell
void insertCell(Cell *cell)
Definition: CellComplex.cpp:245
Cell::getBoundary
void getBoundary(std::map< Cell *, short int, CellPtrLessThan > &boundary, bool orig=false)
Definition: Cell.cpp:673
CellComplex::enqueueCells
void enqueueCells(std::map< Cell *, short int, CellPtrLessThan > &cells, std::queue< Cell * > &Q, std::set< Cell *, CellPtrLessThan > &Qset)
Definition: CellComplex.cpp:287
element
Definition: shapeFunctions.h:12
CellComplex.h
TYPE_PYR
#define TYPE_PYR
Definition: GmshDefines.h:69
CellComplex::printComplex
void printComplex(int dim)
Definition: CellComplex.cpp:975
CellComplex::combine
int combine(int dim)
Definition: CellComplex.cpp:666
TYPE_QUA
#define TYPE_QUA
Definition: GmshDefines.h:67
TYPE_POLYG
#define TYPE_POLYG
Definition: GmshDefines.h:72
CellComplex::bettiReduceComplex
void bettiReduceComplex()
Definition: CellComplex.cpp:659
Cell::addBoundaryCell
void addBoundaryCell(int orientation, Cell *cell, bool other)
Definition: Cell.cpp:543
Cell::printCell
virtual void printCell()
Definition: Cell.cpp:506
Cell::firstCoboundary
biter firstCoboundary(bool orig=false)
Definition: Cell.cpp:637
Cell::createCell
static std::pair< Cell *, bool > createCell(MElement *element, int domain)
Definition: Cell.cpp:45
MElement.h
Cell::getCoboundary
void getCoboundary(std::map< Cell *, short int, CellPtrLessThan > &coboundary, bool orig=false)
Definition: Cell.cpp:684
Cell::restoreCellBoundary
void restoreCellBoundary()
Definition: Cell.cpp:527
TYPE_HEX
#define TYPE_HEX
Definition: GmshDefines.h:71
CellComplex::getDim
int getDim() const
Definition: CellComplex.h:94
CellComplex::loadComplex
int loadComplex(const std::string &filename)
Definition: CellComplex.cpp:1028
CombinedCell
Definition: Cell.h:164
CellComplex::_createCount
int _createCount
Definition: CellComplex.h:54
Cell::getNumBdElements
int getNumBdElements() const
Definition: Cell.cpp:171
CellComplex::firstCell
citer firstCell(int dim, bool orig=false)
Definition: CellComplex.h:123
CellComplex::restoreComplex
bool restoreComplex()
Definition: CellComplex.cpp:929
Cell::setDomain
void setDomain(int domain)
Definition: Cell.h:78
CellComplex::inSameDomain
bool inSameDomain(Cell *c1, Cell *c2) const
Definition: CellComplex.h:136
CellComplex::reduceComplex
int reduceComplex(int combine=1, bool omit=true, bool homseq=false)
Definition: CellComplex.cpp:499
CellComplex::relative
bool relative() const
Definition: CellComplex.h:96
CellComplex::cocombine
int cocombine(int dim)
Definition: CellComplex.cpp:744
CellComplex::hasCell
bool hasCell(Cell *cell, bool orig=false)
Definition: CellComplex.cpp:867
c1
const double c1
Definition: GaussQuadratureHex.cpp:16
CellComplex::_patience
static double _patience
Definition: CellComplex.h:82
Cell::printBoundary
virtual void printBoundary()
Definition: Cell.cpp:695
TYPE_POLYH
#define TYPE_POLYH
Definition: GmshDefines.h:73
CellComplex::saveComplex
int saveComplex(const std::string &filename)
Definition: CellComplex.cpp:987
CellComplex::_reduced
bool _reduced
Definition: CellComplex.h:57
CellComplex::reduction
int reduction(int dim, int omit, std::vector< Cell * > &omittedCells)
Definition: CellComplex.cpp:343
CellComplex::getNumCells
int getNumCells(int dim, int domain=0)
Definition: CellComplex.cpp:893
CellComplex::_numSubdomainCells
int _numSubdomainCells[4]
Definition: CellComplex.h:60