gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
ChainComplex.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 "GmshConfig.h"
9 #if defined(HAVE_KBIPACK)
10 
11 #include "ChainComplex.h"
12 
13 ChainComplex::ChainComplex(CellComplex *cellComplex, int domain)
14 {
15  _dim = cellComplex->getDim();
16  _cellComplex = cellComplex;
17 
18  for(int i = 0; i < 5; i++) {
19  _hMatrix[i] = nullptr;
20  _kerH[i] = nullptr;
21  _codH[i] = nullptr;
22  _jMatrix[i] = nullptr;
23  _qMatrix[i] = nullptr;
24  _hbasis[i] = nullptr;
25  }
26 
27  int lastCols = 0;
28  for(int dim = 0; dim < 4; dim++) {
29  std::size_t cols = cellComplex->getSize(dim);
30  std::size_t rows = 0;
31 
32  int index = 1;
33  // ignore cells depending on domain
34  for(auto cit = cellComplex->firstCell(dim);
35  cit != cellComplex->lastCell(dim); cit++) {
36  Cell *cell = *cit;
37  cols--;
38  if((domain == 0 && !cell->inSubdomain()) || domain == 1 ||
39  (domain == 2 && cell->inSubdomain())) {
40  cols++;
41  _cellIndices[dim][cell] = index;
42  index++;
43  }
44  else
45  _cellIndices[dim][cell] = 0;
46  }
47 
48  if(dim > 0) rows = lastCols;
49  lastCols = cols;
50 
51  if(cols == 0) { // no dim-cells, no map
52  _hMatrix[dim] = nullptr;
53  }
54  else if(rows == 0) { // no dim-1-cells, maps everything to zero
55  _hMatrix[dim] = create_gmp_matrix_zero(1, cols);
56  }
57  else {
58  mpz_t elem;
59  mpz_init(elem);
60  _hMatrix[dim] = create_gmp_matrix_zero(rows, cols);
61  for(auto cit = cellComplex->firstCell(dim);
62  cit != cellComplex->lastCell(dim); cit++) {
63  Cell *cell = *cit;
64  if((domain == 0 && !cell->inSubdomain()) || domain == 1 ||
65  (domain == 2 && cell->inSubdomain())) {
66  for(auto it = cell->firstBoundary(); it != cell->lastBoundary();
67  it++) {
68  Cell *bdCell = it->first;
69  if(it->second.get() == 0) continue;
70  if((domain == 0 && !bdCell->inSubdomain()) || domain == 1 ||
71  (domain == 2 && cell->inSubdomain())) {
72  int old_elem = 0;
73  int bdCellIndex = getCellIndex(bdCell);
74  int cellIndex = getCellIndex(cell);
75  if(bdCellIndex > (int)gmp_matrix_rows(_hMatrix[dim]) ||
76  bdCellIndex < 1 ||
77  cellIndex > (int)gmp_matrix_cols(_hMatrix[dim]) ||
78  cellIndex < 1) {
79  Msg::Debug("Index out of bound! HMatrix: %d", dim);
80  }
81  else {
82  gmp_matrix_get_elem(elem, bdCellIndex, cellIndex,
83  _hMatrix[dim]);
84  old_elem = mpz_get_si(elem);
85  mpz_set_si(elem, old_elem + it->second.get());
86  if(abs((old_elem + it->second.get())) > 1) {
87  // printf("Incidence index: %d, in HMatrix: %d. \n", (old_elem
88  // + (*it).second), dim);
89  }
90  gmp_matrix_set_elem(elem, bdCellIndex, cellIndex,
91  _hMatrix[dim]);
92  }
93  }
94  }
95  }
96  }
97  mpz_clear(elem);
98  }
99  _kerH[dim] = nullptr;
100  _codH[dim] = nullptr;
101  _jMatrix[dim] = nullptr;
102  _qMatrix[dim] = nullptr;
103  _hbasis[dim] = nullptr;
104  }
105 }
106 
107 ChainComplex::~ChainComplex()
108 {
109  for(int i = 0; i < 5; i++) {
110  destroy_gmp_matrix(_hMatrix[i]);
111  destroy_gmp_matrix(_kerH[i]);
112  destroy_gmp_matrix(_codH[i]);
113  destroy_gmp_matrix(_jMatrix[i]);
114  destroy_gmp_matrix(_qMatrix[i]);
115  destroy_gmp_matrix(_hbasis[i]);
116  }
117 }
118 
119 void ChainComplex::transposeHMatrices()
120 {
121  for(int i = 0; i < 5; i++)
122  if(_hMatrix[i] != nullptr) gmp_matrix_transp(_hMatrix[i]);
123 }
124 void ChainComplex::transposeHMatrix(int dim)
125 {
126  if(dim > -1 && dim < 5 && _hMatrix[dim] != nullptr)
127  gmp_matrix_transp(_hMatrix[dim]);
128 }
129 
130 void ChainComplex::KerCod(int dim)
131 {
132  if(dim < 0 || dim > 3 || _hMatrix[dim] == nullptr) return;
133 
134  gmp_matrix *HMatrix =
135  copy_gmp_matrix(_hMatrix[dim], 1, 1, gmp_matrix_rows(_hMatrix[dim]),
136  gmp_matrix_cols(_hMatrix[dim]));
137 
138  gmp_normal_form *normalForm =
139  create_gmp_Hermite_normal_form(HMatrix, NOT_INVERTED, INVERTED);
140  // printMatrix(normalForm->left);
141  // printMatrix(normalForm->canonical);
142  // printMatrix(normalForm->right);
143 
144  int minRowCol = std::min(gmp_matrix_rows(normalForm->canonical),
145  gmp_matrix_cols(normalForm->canonical));
146  int rank = 0;
147  mpz_t elem;
148  mpz_init(elem);
149 
150  // find the rank
151  while(rank < minRowCol) {
152  gmp_matrix_get_elem(elem, rank + 1, rank + 1, normalForm->canonical);
153  if(mpz_cmp_si(elem, 0) == 0) break;
154  rank++;
155  }
156 
157  if(rank != (int)gmp_matrix_cols(normalForm->canonical)) {
158  _kerH[dim] = copy_gmp_matrix(normalForm->right, 1, rank + 1,
159  gmp_matrix_rows(normalForm->right),
160  gmp_matrix_cols(normalForm->right));
161  }
162 
163  if(rank > 0) {
164  _codH[dim] = copy_gmp_matrix(normalForm->canonical, 1, 1,
165  gmp_matrix_rows(normalForm->canonical), rank);
166  gmp_matrix_left_mult(normalForm->left, _codH[dim]);
167  }
168 
169  mpz_clear(elem);
170  destroy_gmp_normal_form(normalForm);
171 
172  return;
173 }
174 
175 // j:B_k->Z_k
176 void ChainComplex::Inclusion(int lowDim, int highDim)
177 {
178  if(getKerHMatrix(lowDim) == nullptr || getCodHMatrix(highDim) == nullptr ||
179  abs(lowDim - highDim) != 1)
180  return;
181 
182  gmp_matrix *Zbasis =
183  copy_gmp_matrix(_kerH[lowDim], 1, 1, gmp_matrix_rows(_kerH[lowDim]),
184  gmp_matrix_cols(_kerH[lowDim]));
185  gmp_matrix *Bbasis =
186  copy_gmp_matrix(_codH[highDim], 1, 1, gmp_matrix_rows(_codH[highDim]),
187  gmp_matrix_cols(_codH[highDim]));
188 
189  int rows = gmp_matrix_rows(Bbasis);
190  int cols = gmp_matrix_cols(Bbasis);
191  if(rows < cols) {
192  destroy_gmp_matrix(Zbasis);
193  destroy_gmp_matrix(Bbasis);
194  return;
195  }
196 
197  rows = gmp_matrix_rows(Zbasis);
198  cols = gmp_matrix_cols(Zbasis);
199  if(rows < cols) {
200  destroy_gmp_matrix(Zbasis);
201  destroy_gmp_matrix(Bbasis);
202  return;
203  }
204 
205  // inv(U)*A*inv(V) = S
206  gmp_normal_form *normalForm =
207  create_gmp_Smith_normal_form(Zbasis, INVERTED, INVERTED);
208 
209  mpz_t elem;
210  mpz_init(elem);
211 
212  for(int i = 1; i <= cols; i++) {
213  gmp_matrix_get_elem(elem, i, i, normalForm->canonical);
214  if(mpz_cmp_si(elem, 0) == 0) {
215  destroy_gmp_matrix(Bbasis);
216  destroy_gmp_normal_form(normalForm);
217  return;
218  }
219  }
220 
221  gmp_matrix_left_mult(normalForm->left, Bbasis);
222 
223  gmp_matrix *LB = copy_gmp_matrix(Bbasis, 1, 1, gmp_matrix_cols(Zbasis),
224  gmp_matrix_cols(Bbasis));
225  destroy_gmp_matrix(Bbasis);
226 
227  rows = gmp_matrix_rows(LB);
228  cols = gmp_matrix_cols(LB);
229 
230  mpz_t divisor;
231  mpz_init(divisor);
232  mpz_t remainder;
233  mpz_init(remainder);
234  mpz_t result;
235  mpz_init(result);
236 
237  for(int i = 1; i <= rows; i++) {
238  gmp_matrix_get_elem(divisor, i, i, normalForm->canonical);
239  for(int j = 1; j <= cols; j++) {
240  gmp_matrix_get_elem(elem, i, j, LB);
241  mpz_cdiv_qr(result, remainder, elem, divisor);
242  if(mpz_cmp_si(remainder, 0) == 0) {
243  gmp_matrix_set_elem(result, i, j, LB);
244  }
245  else {
246  destroy_gmp_matrix(Zbasis);
247  destroy_gmp_matrix(LB);
248  destroy_gmp_normal_form(normalForm);
249  return;
250  }
251  }
252  }
253 
254  gmp_matrix_left_mult(normalForm->right, LB);
255 
256  setJMatrix(lowDim, LB);
257 
258  mpz_clear(elem);
259  mpz_clear(divisor);
260  mpz_clear(result);
261  destroy_gmp_normal_form(normalForm);
262 }
263 
264 void ChainComplex::Quotient(int dim, int setDim)
265 {
266  if(dim < 0 || dim > 4 || _jMatrix[dim] == nullptr) return;
267  if(setDim < 0 || setDim > 4) return;
268 
269  gmp_matrix *JMatrix =
270  copy_gmp_matrix(_jMatrix[dim], 1, 1, gmp_matrix_rows(_jMatrix[dim]),
271  gmp_matrix_cols(_jMatrix[dim]));
272  int rows = gmp_matrix_rows(JMatrix);
273  int cols = gmp_matrix_cols(JMatrix);
274 
275  gmp_normal_form *normalForm =
276  create_gmp_Smith_normal_form(JMatrix, NOT_INVERTED, NOT_INVERTED);
277 
278  // printMatrix(normalForm->left);
279  // printMatrix(normalForm->canonical);
280  // printMatrix(normalForm->right);
281 
282  mpz_t elem;
283  mpz_init(elem);
284 
285  for(int i = 1; i <= cols; i++) {
286  gmp_matrix_get_elem(elem, i, i, normalForm->canonical);
287  if(mpz_cmp_si(elem, 0) == 0) {
288  destroy_gmp_normal_form(normalForm);
289  return;
290  }
291  if(mpz_cmp_si(elem, 1) > 0) {
292  _torsion[setDim].push_back(mpz_get_si(elem));
293  }
294  }
295 
296  int rank = cols - _torsion[setDim].size();
297  if(rows - rank > 0) {
298  gmp_matrix *Hbasis =
299  copy_gmp_matrix(normalForm->left, 1, rank + 1, rows, rows);
300  _qMatrix[dim] = Hbasis;
301  }
302 
303  mpz_clear(elem);
304  destroy_gmp_normal_form(normalForm);
305  return;
306 }
307 
308 void ChainComplex::computeHomology(bool dual)
309 {
310  int lowDim = 0;
311  int highDim = 0;
312  int setDim = 0;
313 
314  if(dual) transposeHMatrices();
315 
316  for(int i = -1; i < 4; i++) {
317  if(dual) {
318  lowDim = getDim() + 1 - i;
319  highDim = getDim() + 1 - (i + 1);
320  setDim = highDim;
321  }
322  else {
323  lowDim = i;
324  highDim = i + 1;
325  setDim = lowDim;
326  }
327 
328  KerCod(highDim);
329 
330  // 1) no edges, but zero cells
331  if(lowDim == 0 && !dual && gmp_matrix_cols(getHMatrix(lowDim)) > 0 &&
332  getHMatrix(highDim) == nullptr) {
333  setHbasis(setDim, create_gmp_matrix_identity(
334  gmp_matrix_cols(getHMatrix(lowDim))));
335  }
336  else if(highDim == 0 && dual && gmp_matrix_rows(getHMatrix(highDim)) > 0 &&
337  getHMatrix(lowDim) == nullptr) {
338  setHbasis(setDim, create_gmp_matrix_identity(
339  gmp_matrix_rows(getHMatrix(highDim))));
340  }
341 
342  // 2) this dimension is empty
343  else if(getHMatrix(setDim) == nullptr) {
344  setHbasis(setDim, nullptr);
345  }
346  // 3) No higher dimension cells -> none of the cycles are boundaries
347  else if(getHMatrix(highDim) == nullptr) {
348  setHbasis(setDim,
349  copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
350  gmp_matrix_rows(getKerHMatrix(lowDim)),
351  gmp_matrix_cols(getKerHMatrix(lowDim))));
352  }
353 
354  // 5) General case:
355  // 1) Find the bases of boundaries B and cycles Z
356  // 2) find j: B -> Z and
357  // 3) find quotient Z/j(B)
358  else {
359  // 4) No lower dimension cells -> all chains are cycles
360  if(getHMatrix(lowDim) == nullptr) {
361  setKerHMatrix(lowDim, create_gmp_matrix_identity(
362  gmp_matrix_rows(getHMatrix(highDim))));
363  }
364  Inclusion(lowDim, highDim);
365  Quotient(lowDim, setDim);
366 
367  if(getCodHMatrix(highDim) == nullptr) {
368  setHbasis(setDim,
369  copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
370  gmp_matrix_rows(getKerHMatrix(lowDim)),
371  gmp_matrix_cols(getKerHMatrix(lowDim))));
372  }
373  else if(getJMatrix(lowDim) == nullptr || getQMatrix(lowDim) == nullptr) {
374  setHbasis(setDim, nullptr);
375  }
376  else {
377  setHbasis(setDim,
378  copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
379  gmp_matrix_rows(getKerHMatrix(lowDim)),
380  gmp_matrix_cols(getKerHMatrix(lowDim))));
381 
382  gmp_matrix_right_mult(getHbasis(setDim), getQMatrix(lowDim));
383  }
384  }
385 
386  destroy_gmp_matrix(getJMatrix(lowDim));
387  destroy_gmp_matrix(getQMatrix(lowDim));
388 
389  setJMatrix(lowDim, nullptr);
390  setQMatrix(lowDim, nullptr);
391  }
392  return;
393 }
394 
395 void ChainComplex::matrixTest()
396 {
397  const int rows = 3;
398  const int cols = 6;
399 
400  long int elems[rows * cols];
401  for(int i = 1; i <= rows * cols; i++) elems[i - 1] = i;
402 
403  gmp_matrix *matrix = create_gmp_matrix_int(rows, cols, elems);
404  gmp_matrix *copymatrix = copy_gmp_matrix(matrix, 3, 2, 3, 5);
405  printMatrix(matrix);
406  printMatrix(copymatrix);
407  destroy_gmp_matrix(matrix);
408  destroy_gmp_matrix(copymatrix);
409 }
410 
411 std::vector<int> ChainComplex::getCoeffVector(int dim, int chainNumber)
412 {
413  std::vector<int> coeffVector;
414 
415  if(dim < 0 || dim > 4) return coeffVector;
416  if(_hbasis[dim] == nullptr ||
417  (int)gmp_matrix_cols(_hbasis[dim]) < chainNumber)
418  return coeffVector;
419 
420  int rows = gmp_matrix_rows(_hbasis[dim]);
421 
422  int elemi;
423  long int elemli;
424  mpz_t elem;
425  mpz_init(elem);
426 
427  for(int i = 1; i <= rows; i++) {
428  gmp_matrix_get_elem(elem, i, chainNumber, _hbasis[dim]);
429  elemli = mpz_get_si(elem);
430  elemi = elemli;
431  coeffVector.push_back(elemi);
432  // printf("coeff: %d \n", coeffVector.at(i-1));
433  }
434 
435  mpz_clear(elem);
436  return coeffVector;
437 }
438 
439 gmp_matrix *ChainComplex::getBasis(int dim, int basis)
440 {
441  if(dim > -2 && dim < 4 && basis == 2) return _codH[dim + 1];
442  if(dim < 0 || dim > 4)
443  return nullptr;
444  else if(basis == 1)
445  return _kerH[dim];
446  else if(basis == 3)
447  return _hbasis[dim];
448  else
449  return nullptr;
450 }
451 
452 void ChainComplex::getBasisChain(std::map<Cell *, int, CellPtrLessThan> &chain,
453  int num, int dim, int basis, bool deform)
454 {
455  if(basis < 0 || basis > 3) return;
456  gmp_matrix *basisMatrix = getBasis(dim, basis);
457 
458  chain.clear();
459  if(dim < 0 || dim > 3) return;
460  if(basisMatrix == nullptr || (int)gmp_matrix_cols(basisMatrix) < num) {
461  return;
462  }
463 
464  int elemi;
465  long int elemli;
466  mpz_t elem;
467  mpz_init(elem);
468 
469  int torsion = 1;
470  if(basis == 3) torsion = getTorsion(dim, num);
471 
472  for(auto cit = this->firstCell(dim); cit != this->lastCell(dim); cit++) {
473  Cell *cell = cit->first;
474  int index = cit->second;
475  gmp_matrix_get_elem(elem, index, num, basisMatrix);
476  elemli = mpz_get_si(elem);
477  elemi = elemli;
478  if(elemli != 0) {
479  std::map<Cell *, int, CellPtrLessThan> subCells;
480  cell->getCells(subCells);
481  for(auto it = subCells.begin(); it != subCells.end(); it++) {
482  Cell *subCell = it->first;
483  int coeff = it->second * elemi * torsion;
484  if(coeff == 0) continue;
485  chain[subCell] = coeff;
486  }
487  }
488  }
489  mpz_clear(elem);
490 
491  if(deform && basis == 3 && (dim == 1 || dim == 2)) smoothenChain(chain);
492 }
493 
494 int ChainComplex::getBasisSize(int dim, int basis)
495 {
496  gmp_matrix *basisMatrix;
497  if(basis == 0 && _hMatrix[dim] != nullptr) {
498  return gmp_matrix_cols(_hMatrix[dim]);
499  }
500  else if(basis == 1)
501  basisMatrix = getBasis(dim, 1);
502  else if(basis == 2)
503  basisMatrix = getBasis(dim, 2);
504  else if(basis == 3)
505  basisMatrix = getBasis(dim, 3);
506  else
507  return 0;
508 
509  if(basisMatrix != nullptr && gmp_matrix_rows(basisMatrix) != 0)
510  return gmp_matrix_cols(basisMatrix);
511  else
512  return 0;
513 }
514 
515 int ChainComplex::getTorsion(int dim, int num)
516 {
517  if(dim < 0 || dim > 4) return 0;
518  if(_hbasis[dim] == nullptr || (int)gmp_matrix_cols(_hbasis[dim]) < num)
519  return 0;
520  if(_torsion[dim].empty() || (int)_torsion[dim].size() < num)
521  return 1;
522  else
523  return _torsion[dim].at(num - 1);
524 }
525 
526 bool ChainComplex::deform(
527  std::map<Cell *, int, CellPtrLessThan> &cells,
528  std::map<Cell *, int, CellPtrLessThan> &cellsInChain,
529  std::map<Cell *, int, CellPtrLessThan> &cellsNotInChain)
530 {
531  std::vector<int> cc;
532  std::vector<int> bc;
533 
534  for(auto cit = cellsInChain.begin(); cit != cellsInChain.end(); cit++) {
535  Cell *c = (*cit).first;
536  c->setImmune(false);
537  if(!c->inSubdomain()) {
538  int coeff = 0;
539  auto it = cells.find(c);
540  if(it != cells.end()) coeff = it->second;
541  cc.push_back(coeff);
542  bc.push_back((*cit).second);
543  }
544  }
545 
546  if(cc.empty() || (getDim() == 2 && cc.size() < 2)) return false;
547  int inout = cc[0] * bc[0];
548  for(std::size_t i = 0; i < cc.size(); i++) {
549  if(cc[i] * bc[i] != inout) return false;
550  }
551 
552  for(auto cit = cellsInChain.begin(); cit != cellsInChain.end(); cit++) {
553  Cell *cell = cit->first;
554  auto it = cells.find(cell);
555  if(it != cells.end()) cells[cell] = 0;
556  }
557 
558  int n = 1;
559  for(auto cit = cellsNotInChain.begin(); cit != cellsNotInChain.end(); cit++) {
560  Cell *cell = (*cit).first;
561  if(n == 2)
562  cell->setImmune(true);
563  else
564  cell->setImmune(false);
565  int coeff = -1 * inout * (*cit).second;
566 
567  std::pair<citer, bool> insert = cells.insert(std::make_pair(cell, coeff));
568  if(!insert.second && (*insert.first).second == 0) {
569  (*insert.first).second = coeff;
570  }
571  else if(!insert.second && (*insert.first).second != 0) {
572  Msg::Error("Invalid chain smoothening add!");
573  }
574  n++;
575  }
576  return true;
577 }
578 
579 bool ChainComplex::deformChain(std::map<Cell *, int, CellPtrLessThan> &cells,
580  std::pair<Cell *, int> cell, bool bend)
581 {
582  Cell *c1 = cell.first;
583  int dim = c1->getDim();
584  for(auto cit = c1->firstCoboundary(true); cit != c1->lastCoboundary();
585  cit++) {
586  std::map<Cell *, int, CellPtrLessThan> cellsInChain;
587  std::map<Cell *, int, CellPtrLessThan> cellsNotInChain;
588  Cell *c1CbdCell = cit->first;
589 
590  for(auto cit2 = c1CbdCell->firstBoundary(true);
591  cit2 != c1CbdCell->lastBoundary(); cit2++) {
592  Cell *c1CbdBdCell = cit2->first;
593  int coeff = cit2->second.geto();
594  if(coeff == 0) continue;
595  if((cells.find(c1CbdBdCell) != cells.end() && cells[c1CbdBdCell] != 0) ||
596  c1CbdBdCell->inSubdomain()) {
597  cellsInChain.insert(std::make_pair(c1CbdBdCell, coeff));
598  }
599  else
600  cellsNotInChain.insert(std::make_pair(c1CbdBdCell, coeff));
601  }
602 
603  bool next = false;
604 
605  for(auto cit2 = cellsInChain.begin(); cit2 != cellsInChain.end(); cit2++) {
606  Cell *c = (*cit2).first;
607  int coeff = 0;
608  auto it = cells.find(c);
609  if(it != cells.end()) coeff = it->second;
610  if(c->getImmune()) next = true;
611  if(c->inSubdomain()) bend = false;
612  if(coeff > 1 || coeff < -1) next = true;
613  }
614 
615  for(auto cit2 = cellsNotInChain.begin(); cit2 != cellsNotInChain.end();
616  cit2++) {
617  Cell *c = (*cit2).first;
618  if(c->inSubdomain()) next = true;
619  }
620  if(next) continue;
621 
622  if((dim == 1 && cellsInChain.size() == 2 && cellsNotInChain.size() == 1) ||
623  (dim == 2 && cellsInChain.size() == 3 && cellsNotInChain.size() == 1)) {
624  // printf("straighten \n");
625  return deform(cells, cellsInChain, cellsNotInChain);
626  }
627  else if((dim == 1 && cellsInChain.size() == 1 &&
628  cellsNotInChain.size() == 2 && bend) ||
629  (dim == 2 && cellsInChain.size() == 2 &&
630  cellsNotInChain.size() == 2 && bend)) {
631  // printf("bend \n");
632  return deform(cells, cellsInChain, cellsNotInChain);
633  }
634  else if((dim == 1 && cellsInChain.size() == 3 &&
635  cellsNotInChain.size() == 0) ||
636  (dim == 2 && cellsInChain.size() == 4 &&
637  cellsNotInChain.size() == 0)) {
638  // printf("remove boundary \n");
639  return deform(cells, cellsInChain, cellsNotInChain);
640  }
641  }
642 
643  return false;
644 }
645 
646 void ChainComplex::smoothenChain(std::map<Cell *, int, CellPtrLessThan> &cells)
647 {
648  if(!_cellComplex->simplicial() || cells.size() < 2) return;
649  int dim = cells.begin()->first->getDim();
650  int start = cells.size();
651 
652  int useless = 0;
653  for(int i = 0; i < 20; i++) {
654  int size = cells.size();
655  for(auto cit = cells.begin(); cit != cells.end(); cit++) {
656  if(dim == 2) deformChain(cells, *cit, true);
657  deformChain(cells, *cit, false);
658  }
659 
660  deImmuneCells(cells);
661  eraseNullCells(cells);
662 
663  if(size >= (int)cells.size())
664  useless++;
665  else
666  useless = 0;
667  if(useless > 5) break;
668  }
669 
670  deImmuneCells(cells);
671  for(auto cit = cells.begin(); cit != cells.end(); cit++) {
672  deformChain(cells, *cit, false);
673  }
674  eraseNullCells(cells);
675  int size = cells.size();
676  Msg::Debug("Simplified a %d-chain from %d cells to %d cells", dim, start,
677  size);
678 }
679 
680 void ChainComplex::eraseNullCells(std::map<Cell *, int, CellPtrLessThan> &cells)
681 {
682  std::vector<Cell *> toRemove;
683  for(auto cit = cells.begin(); cit != cells.end(); cit++) {
684  if(cit->second == 0) toRemove.push_back(cit->first);
685  }
686  for(std::size_t i = 0; i < toRemove.size(); i++) cells.erase(toRemove[i]);
687 }
688 
689 void ChainComplex::deImmuneCells(std::map<Cell *, int, CellPtrLessThan> &cells)
690 {
691  for(auto cit = cells.begin(); cit != cells.end(); cit++) {
692  Cell *cell = (*cit).first;
693  cell->setImmune(false);
694  }
695 }
696 
697 #endif
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
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::lastCell
citer lastCell(int dim, bool orig=false)
Definition: CellComplex.h:127
Cell::getCells
virtual void getCells(std::map< Cell *, int, CellPtrLessThan > &cells)
Definition: Cell.h:150
Cell::firstBoundary
biter firstBoundary(bool orig=false)
Definition: Cell.cpp:625
Cell::inSubdomain
bool inSubdomain() const
Definition: Cell.h:83
ChainComplex.h
CellComplex
Definition: CellComplex.h:24
Cell
Definition: Cell.h:42
Cell::setImmune
void setImmune(bool immune)
Definition: Cell.h:86
CellComplex::getDim
int getDim() const
Definition: CellComplex.h:94
Cell::lastBoundary
biter lastBoundary()
Definition: Cell.cpp:635
CellComplex::firstCell
citer firstCell(int dim, bool orig=false)
Definition: CellComplex.h:123
c1
const double c1
Definition: GaussQuadratureHex.cpp:16
elem
Definition: OctreeInternals.h:17