diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp index 24616c6e7095da78c3ea33e2cf18a0b2e578a7cc..1d6337ad85f06ba81cd9a6c05fed2b745a7197cb 100644 --- a/Geo/CellComplex.cpp +++ b/Geo/CellComplex.cpp @@ -11,6 +11,8 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su _domain = domain; _subdomain = subdomain; + + // determine mesh entities on boundary of the domain bool duplicate = false; for(unsigned int j=0; j < _domain.size(); j++){ if(_domain.at(j)->dim() == 3){ @@ -40,16 +42,13 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su GEntity* entity = *itb; if(edge->tag() == entity->tag()){ _boundary.erase(itb); - //erase = itb; duplicate = true; break; } } - //if(duplicate) _boundary.erase(erase); if(!duplicate) _boundary.push_back(edge); } } - else if(_domain.at(j)->dim() == 1){ std::list<GVertex*> vertices = _domain.at(j)->vertices(); for(std::list<GVertex*>::iterator it = vertices.begin(); it != vertices.end(); it++){ @@ -69,28 +68,62 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su } } - + // insert cells into cell complex // subdomain need to be inserted first! - insertCells(true, true); - insertCells(false, true); - insertCells(false, false); - + insert_cells2(true, true); + insert_cells2(false, true); + insert_cells2(false, false); + + // find mesh vertices in the domain + for(unsigned int j=0; j < domain.size(); j++) { + for(unsigned int i=0; i < domain.at(j)->getNumMeshElements(); i++){ + for(int k=0; k < domain.at(j)->getMeshElement(i)->getNumVertices(); k++){ + MVertex* vertex = domain.at(j)->getMeshElement(i)->getVertex(k); + _domainVertices.insert(vertex); + } + } + } + for(unsigned int j=0; j < subdomain.size(); j++) { + for(unsigned int i=0; i < subdomain.at(j)->getNumMeshElements(); i++){ + for(int k=0; k < subdomain.at(j)->getMeshElement(i)->getNumVertices(); k++){ + MVertex* vertex = subdomain.at(j)->getMeshElement(i)->getVertex(k); + _domainVertices.insert(vertex); + } + } + } + + + // attach induvivial tags to cells int tag = 1; for(int i = 0; i < 4; i++){ for(citer cit = firstCell(i); cit != lastCell(i); cit++){ Cell* cell = *cit; cell->setTag(tag); tag++; + + // make sure that boundary and coboundary information is coherent + std::list<Cell*> boundary = cell->getBoundary(); + boundary.sort(Less_Cell()); + boundary.unique(Equal_Cell()); + cell->setBoundary(boundary); + + std::list<Cell*> coboundary = cell->getCoboundary(); + coboundary.sort(Less_Cell()); + coboundary.unique(Equal_Cell()); + cell->setCoboundary(coboundary); + + } + _originalCells[i] = _cells[i]; } - + _simplicial = true; } -void CellComplex::insertCells(bool subdomain, bool boundary){ +void CellComplex::insert_cells(bool subdomain, bool boundary){ std::vector<GEntity*> domain; @@ -101,26 +134,34 @@ void CellComplex::insertCells(bool subdomain, bool boundary){ std::vector<int> vertices; int vertex = 0; + std::pair<citer, bool> insertInfo; + for(unsigned int j=0; j < domain.size(); j++) { for(unsigned int i=0; i < domain.at(j)->getNumMeshElements(); i++){ vertices.clear(); + for(int k=0; k < domain.at(j)->getMeshElement(i)->getNumVertices(); k++){ MVertex* vertex = domain.at(j)->getMeshElement(i)->getVertex(k); vertices.push_back(vertex->getNum()); //_cells[0].insert(new ZeroSimplex(vertex->getNum(), subdomain, vertex->x(), vertex->y(), vertex->z() )); // Add vertices - _cells[0].insert(new ZeroSimplex(vertex->getNum(), subdomain, boundary)); - } + Cell* cell = new ZeroSimplex(vertex->getNum(), subdomain, boundary); + insertInfo = _cells[0].insert(cell); + if(!insertInfo.second) delete cell; + } if(domain.at(j)->getMeshElement(i)->getDim() == 3){ - _cells[3].insert(new ThreeSimplex(vertices, subdomain, boundary)); // Add volumes + Cell* cell = new ThreeSimplex(vertices, subdomain, boundary); // Add volumes + insertInfo = _cells[3].insert(cell); + if(!insertInfo.second) delete cell; } - for(int k=0; k < domain.at(j)->getMeshElement(i)->getNumFaces(); k++){ vertices.clear(); for(int l=0; l < domain.at(j)->getMeshElement(i)->getFace(k).getNumVertices(); l++){ vertex = domain.at(j)->getMeshElement(i)->getFace(k).getVertex(l)->getNum(); vertices.push_back(vertex); } - _cells[2].insert(new TwoSimplex(vertices, subdomain, boundary)); // Add faces + Cell* cell = new TwoSimplex(vertices, subdomain, boundary); // Add faces + insertInfo = _cells[2].insert(cell); + if(!insertInfo.second) delete cell; } for(int k=0; k < domain.at(j)->getMeshElement(i)->getNumEdges(); k++){ @@ -129,14 +170,81 @@ void CellComplex::insertCells(bool subdomain, bool boundary){ vertex = domain.at(j)->getMeshElement(i)->getEdge(k).getVertex(l)->getNum(); vertices.push_back(vertex); } - _cells[1].insert(new OneSimplex(vertices, subdomain, boundary)); // Add edges + Cell* cell = new OneSimplex(vertices, subdomain, boundary); // Add edges + insertInfo = _cells[1].insert(cell); + if(!insertInfo.second) delete cell; } - + } } } +void CellComplex::insert_cells2(bool subdomain, bool boundary){ + + // works only for simplcial meshes at the moment! + + std::vector<GEntity*> domain; + + if(subdomain) domain = _subdomain; + else if(boundary) domain = _boundary; + else domain = _domain; + + std::vector<int> vertices; + int vertex = 0; + + std::pair<citer, bool> insertInfo; + + // add highest dimensional cells + for(unsigned int j=0; j < domain.size(); j++) { + for(unsigned int i=0; i < domain.at(j)->getNumMeshElements(); i++){ + vertices.clear(); + + for(int k=0; k < domain.at(j)->getMeshElement(i)->getNumVertices(); k++){ + MVertex* vertex = domain.at(j)->getMeshElement(i)->getVertex(k); + vertices.push_back(vertex->getNum()); + } + + int dim = domain.at(j)->getMeshElement(i)->getDim(); + int type = domain.at(j)->getMeshElement(i)->getTypeForMSH(); + Cell* cell; + if(dim == 3) cell = new ThreeSimplex(vertices, subdomain, boundary); + else if(dim == 2) cell = new TwoSimplex(vertices, subdomain, boundary); + else if(dim == 1) cell = new OneSimplex(vertices, subdomain, boundary); + else cell = new ZeroSimplex(vertices.at(0), subdomain, boundary); + insertInfo = _cells[dim].insert(cell); + if(!insertInfo.second) delete cell; + } + } + + // add lower dimensional cells recursively + for (int dim = 3; dim > 0; dim--){ + for(citer cit = firstCell(dim); cit != lastCell(dim); cit++){ + Cell* cell = *cit; + std::vector<int> vertices; + for(int i = 0; i < cell->getNumFacets(); i++){ + cell->getFacetVertices(i, vertices); + Cell* newCell; + if(dim == 3) newCell = new TwoSimplex(vertices, subdomain, boundary); + else if(dim == 2) newCell = new OneSimplex(vertices, subdomain, boundary); + else if(dim == 1) newCell = new ZeroSimplex(vertices.at(0), subdomain, boundary); + insertInfo = _cells[dim-1].insert(newCell); + if(!insertInfo.second){ + delete newCell; + Cell* oldCell = *(insertInfo.first); + oldCell->addCoboundaryCell(cell); + cell->addBoundaryCell(oldCell); + } + else{ + cell->addBoundaryCell(newCell); + newCell->addCoboundaryCell(cell); + } + } + } + } + +} + void CellComplex::insertCell(Cell* cell){ _cells[cell->getDim()].insert(cell); } @@ -157,25 +265,32 @@ int Simplex::kappa(Cell* tau) const{ return value; } std::set<Cell*, Less_Cell>::iterator CellComplex::findCell(int dim, std::vector<int>& vertices, bool original){ - if(!original){ - if(dim == 0) return _cells[dim].find(new ZeroSimplex(vertices.at(0))); - if(dim == 1) return _cells[dim].find(new OneSimplex(vertices)); - if(dim == 2) return _cells[dim].find(new TwoSimplex(vertices)); - return _cells[3].find(new ThreeSimplex(vertices)); - } - else{ - if(dim == 0) return _originalCells[dim].find(new ZeroSimplex(vertices.at(0))); - if(dim == 1) return _originalCells[dim].find(new OneSimplex(vertices)); - if(dim == 2) return _originalCells[dim].find(new TwoSimplex(vertices)); - return _originalCells[3].find(new ThreeSimplex(vertices)); - } + Cell* cell; + + if(dim == 0) cell = new ZeroSimplex(vertices.at(0)); + else if(dim == 1) cell = new OneSimplex(vertices); + else if(dim == 2) cell = new TwoSimplex(vertices); + else cell = new ThreeSimplex(vertices); + + citer cit; + if(!original) cit = _cells[dim].find(cell); + else cit = _originalCells[dim].find(cell); + + delete cell; + return cit; } std::set<Cell*, Less_Cell>::iterator CellComplex::findCell(int dim, int vertex, int dummy){ - if(dim == 0) return _cells[dim].lower_bound(new ZeroSimplex(vertex)); - if(dim == 1) return _cells[dim].lower_bound(new OneSimplex(vertex, dummy)); - if(dim == 2) return _cells[dim].lower_bound(new TwoSimplex(vertex, dummy)); - return _cells[3].lower_bound(new ThreeSimplex(vertex, dummy)); + Cell* cell; + if(dim == 0) cell = new ZeroSimplex(vertex); + else if(dim == 1) cell = new OneSimplex(vertex, dummy); + else if(dim == 2) cell = new TwoSimplex(vertex, dummy); + else cell = new ThreeSimplex(vertex, dummy); + + citer cit = _cells[dim].lower_bound(cell); + + delete cell; + return cit; } @@ -184,19 +299,41 @@ std::vector<Cell*> CellComplex::bd(Cell* sigma){ int dim = sigma->getDim(); if(dim < 1) return boundary; - - citer start = findCell(dim-1, sigma->getVertex(0), 0); - if(start == lastCell(dim-1)) return boundary; - - citer end = findCell(dim-1, sigma->getVertex(sigma->getNumVertices()-1), sigma->getVertex(sigma->getNumVertices()-1)); - if(end != lastCell(dim-1)) end++; - - //for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){ - for(citer cit = start; cit != end; cit++){ - if(kappa(sigma, *cit) != 0){ - boundary.push_back(*cit); - if(boundary.size() == sigma->getBdMaxSize()){ - return boundary; + if(simplicial()){ // faster + std::vector<int> vertices = sigma->getVertexVector(); + + for(int j=0; j < vertices.size(); j++){ + std::vector<int> bVertices; + + // simplicial mesh assumed here! + for(int k=0; k < vertices.size(); k++){ + if (k !=j ) bVertices.push_back(vertices.at(k)); + } + citer cit2 = findCell(dim-1, bVertices); + if(cit2 != lastCell(dim-1)){ + boundary.push_back(*cit2); + if(boundary.size() == sigma->getBdMaxSize()){ + return boundary; + } + } + } + + } + else{ + citer start = findCell(dim-1, sigma->getVertex(0), 0); + if(start == lastCell(dim-1)) return boundary; + + citer end = findCell(dim-1, sigma->getVertex(sigma->getNumVertices()-1), sigma->getVertex(sigma->getNumVertices()-1)); + if(end != lastCell(dim-1)) end++; + + //for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){ + for(citer cit = start; cit != end; cit++){ + //if(kappa(sigma, *cit) != 0){ + if(sigma->kappa(*cit) != 0){ + boundary.push_back(*cit); + if(boundary.size() == sigma->getBdMaxSize()){ + return boundary; + } } } } @@ -238,15 +375,19 @@ std::vector<Cell*> CellComplex::cbd(Cell* tau){ } for(citer cit = firstCell(dim+1); cit != lastCell(dim+1); cit++){ - if(kappa(*cit, tau) != 0){ + //if(kappa(*cit, tau) != 0){ + Cell* cell = *cit; + if(cell->kappa(tau) != 0){ coboundary.push_back(*cit); if(coboundary.size() == tau->getCbdMaxSize()){ return coboundary; } } } + return coboundary; } + std::vector< std::set<Cell*, Less_Cell>::iterator > CellComplex::cbdIt(Cell* tau){ std::vector< std::set<Cell*, Less_Cell>::iterator > coboundary; @@ -268,20 +409,31 @@ std::vector< std::set<Cell*, Less_Cell>::iterator > CellComplex::cbdIt(Cell* tau } -void CellComplex::removeCell(Cell* cell, bool deleteCell){ - _cells[cell->getDim()].erase(cell); - //if(deleteCell) delete cell; +void CellComplex::removeCell(Cell* cell){ + _cells[cell->getDim()].erase(cell); + + std::list<Cell*> coboundary = cell->getCoboundary(); + std::list<Cell*> boundary = cell->getBoundary(); + + for(std::list<Cell*>::iterator it = coboundary.begin(); it != coboundary.end(); it++){ + Cell* cbdCell = *it; + cbdCell->removeBoundaryCell(cell); + } + for(std::list<Cell*>::iterator it = boundary.begin(); it != boundary.end(); it++){ + Cell* bdCell = *it; + bdCell->removeCoboundaryCell(cell); + } + } void CellComplex::removeCellIt(std::set<Cell*, Less_Cell>::iterator cell){ Cell* c = *cell; int dim = c->getDim(); _cells[dim].erase(cell); - //delete c; + } void CellComplex::removeCellQset(Cell*& cell, std::set<Cell*, Less_Cell>& Qset){ Qset.erase(cell); - //delete cell; } void CellComplex::enqueueCellsIt(std::vector< std::set<Cell*, Less_Cell>::iterator >& cells, @@ -295,21 +447,23 @@ void CellComplex::enqueueCellsIt(std::vector< std::set<Cell*, Less_Cell>::iterat } } } -void CellComplex::enqueueCells(std::vector<Cell*>& cells, std::queue<Cell*>& Q, std::set<Cell*, Less_Cell>& Qset){ - for(unsigned int i=0; i < cells.size(); i++){ - citer cit = Qset.find(cells.at(i)); - if(cit == Qset.end()){ - Qset.insert(cells.at(i)); - Q.push(cells.at(i)); +void CellComplex::enqueueCells(std::list<Cell*>& cells, std::queue<Cell*>& Q, std::set<Cell*, Less_Cell>& Qset){ + for(std::list<Cell*>::iterator cit = cells.begin(); cit != cells.end(); cit++){ + Cell* cell = *cit; + citer it = Qset.find(cell); + if(it == Qset.end()){ + Qset.insert(cell); + Q.push(cell); } } } -void CellComplex::enqueueCells(std::vector<Cell*>& cells, std::list<Cell*>& Q){ - for(unsigned int i=0; i < cells.size(); i++){ - std::list<Cell*>::iterator it = std::find(Q.begin(), Q.end(), cells.at(i)); +void CellComplex::enqueueCells(std::list<Cell*>& cells, std::list<Cell*>& Q){ + for(std::list<Cell*>::iterator cit = cells.begin(); cit != cells.end(); cit++){ + Cell* cell = *cit; + std::list<Cell*>::iterator it = std::find(Q.begin(), Q.end(), cell); if(it == Q.end()){ - Q.push_back(cells.at(i)); + Q.push_back(cell); } } } @@ -327,35 +481,37 @@ int CellComplex::coreductionMrozek(Cell* generator){ Qset.insert(generator); //removeCell(generator); - std::vector<Cell*> bd_s; - std::vector<Cell*> cbd_c; + std::list<Cell*> bd_s; + std::list<Cell*> cbd_c; Cell* s; int round = 0; while( !Q.empty() ){ round++; //printf("%d ", round); + s = Q.front(); Q.pop(); removeCellQset(s, Qset); - bd_s = bd(s); - if( bd_s.size() == 1 && inSameDomain(s, bd_s.at(0)) ){ + bd_s = s->getBoundary(); + if( bd_s.size() == 1 && inSameDomain(s, bd_s.front()) ){ removeCell(s); - cbd_c = cbd(bd_s.at(0)); + cbd_c = bd_s.front()->getCoboundary(); enqueueCells(cbd_c, Q, Qset); - removeCell(bd_s.at(0)); + removeCell(bd_s.front()); coreductions++; } else if(bd_s.empty()){ - cbd_c = cbd(s); + cbd_c = s->getCoboundary(); enqueueCells(cbd_c, Q, Qset); } - + } //printf("Coreduction: %d loops with %d coreductions\n", round, coreductions); return coreductions; } + int CellComplex::coreductionMrozek2(Cell* generator){ int coreductions = 0; @@ -364,8 +520,8 @@ int CellComplex::coreductionMrozek2(Cell* generator){ Q.push_back(generator); - std::vector<Cell*> bd_s; - std::vector<Cell*> cbd_c; + std::list<Cell*> bd_s; + std::list<Cell*> cbd_c; Cell* s; int round = 0; while( !Q.empty() ){ @@ -373,16 +529,16 @@ int CellComplex::coreductionMrozek2(Cell* generator){ //printf("%d ", round); s = Q.front(); Q.pop_front(); - bd_s = bd(s); - if( bd_s.size() == 1 && inSameDomain(s, bd_s.at(0)) ){ + bd_s = s->getBoundary(); + if( bd_s.size() == 1 && inSameDomain(s, bd_s.front()) ){ removeCell(s); - cbd_c = cbd(bd_s.at(0)); + cbd_c = bd_s.front()->getCoboundary(); enqueueCells(cbd_c, Q); - removeCell(bd_s.at(0)); + removeCell(bd_s.front()); coreductions++; } else if(bd_s.empty()){ - cbd_c = cbd(s); + cbd_c = s->getCoboundary(); enqueueCells(cbd_c, Q); } @@ -392,6 +548,7 @@ int CellComplex::coreductionMrozek2(Cell* generator){ //printf("Coreduction: %d loops with %d coreductions\n", round, coreductions); return coreductions; } + int CellComplex::coreductionMrozek3(Cell* generator){ int coreductions = 0; @@ -430,7 +587,7 @@ int CellComplex::coreductionMrozek3(Cell* generator){ //printf("Coreduction: %d loops with %d coreductions\n", round, coreductions); return coreductions; } -int CellComplex::coreduction(int dim, bool deleteCells){ +int CellComplex::coreduction(int dim){ if(dim < 0 || dim > 2) return 0; @@ -445,8 +602,8 @@ int CellComplex::coreduction(int dim, bool deleteCells){ bd_c = bd(cell); if(bd_c.size() == 1 && inSameDomain(cell, bd_c.at(0)) ){ - removeCell(cell, deleteCells); - removeCell(bd_c.at(0), deleteCells); + removeCell(cell); + removeCell(bd_c.at(0)); count++; coreduced = true; } @@ -475,8 +632,8 @@ int CellComplex::coreduction(int dim, std::set<Cell*, Less_Cell>& removedCells){ if(bd_c.size() == 1 && inSameDomain(cell, bd_c.at(0)) ){ removedCells.insert(cell); removedCells.insert(bd_c.at(0)); - removeCell(cell, false); - removeCell(bd_c.at(0), false); + removeCell(cell); + removeCell(bd_c.at(0)); count++; coreduced = true; } @@ -488,12 +645,40 @@ int CellComplex::coreduction(int dim, std::set<Cell*, Less_Cell>& removedCells){ } +int CellComplex::coreduction2(int dim){ + + if(dim < 0 || dim > 2) return 0; + + std::list<Cell*> bd_c; + + int count = 0; + + bool coreduced = true; + while (coreduced){ + coreduced = false; + for(citer cit = firstCell(dim+1); cit != lastCell(dim+1); cit++){ + Cell* cell = *cit; + + bd_c = cell->getBoundary(); + if(bd_c.size() == 1 && inSameDomain(cell, bd_c.front()) ){ + removeCell(cell); + removeCell(bd_c.front()); + count++; + coreduced = true; + } + + } + } + return count; +} + -int CellComplex::reduction(int dim, bool deleteCells){ +int CellComplex::reduction(int dim){ if(dim < 1 || dim > 3) return 0; std::vector<Cell*> cbd_c; + std::vector<Cell*> bd_c; int count = 0; bool reduced = true; @@ -503,23 +688,49 @@ int CellComplex::reduction(int dim, bool deleteCells){ Cell* cell = *cit; cbd_c = cbd(cell); if(cbd_c.size() == 1 && inSameDomain(cell, cbd_c.at(0)) ){ - removeCell(cell, deleteCells); - removeCell(cbd_c.at(0), deleteCells); + removeCell(cell); + removeCell(cbd_c.at(0)); count++; reduced = true; } - } } return count; } + +int CellComplex::reduction2(int dim){ + if(dim < 1 || dim > 3) return 0; + + std::list<Cell*> bd_c; + std::list<Cell*> cbd_c; + int count = 0; + + bool reduced = true; + while (reduced){ + reduced = false; + for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){ + Cell* cell = *cit; + cbd_c = cell->getCoboundary(); + if(cbd_c.size() == 1 && inSameDomain(cell, cbd_c.front()) ){ + removeCell(cell); + removeCell(cbd_c.front()); + count++; + reduced = true; + } + } + } + + return count; +} + + void CellComplex::reduceComplex(){ printf("Cell complex before reduction: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); - reduction(3); - reduction(2); - reduction(1); + reduction2(3); + reduction2(2); + reduction2(1); printf("Cell complex after reduction: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); } @@ -541,7 +752,7 @@ void CellComplex::coreduceComplex(int generatorDim, std::set<Cell*, Less_Cell>& } generatorCells[i].insert(cell); removedCells.insert(cell); - removeCell(cell, false); + removeCell(cell); coreduction(0, removedCells); coreduction(1, removedCells); coreduction(2, removedCells); @@ -575,11 +786,11 @@ void CellComplex::coreduceComplex(int generatorDim){ cit++; } generatorCells[i].insert(cell); - removeCell(cell, false); + removeCell(cell); - //coreduction(0); - //coreduction(1); - //coreduction(2); + //coreduction2(0); + //coreduction2(1); + //coreduction2(2); coreductionMrozek(cell); } if(generatorDim == i) break; @@ -597,9 +808,12 @@ void CellComplex::coreduceComplex(int generatorDim){ return; } -void CellComplex::repairComplex(){ +void CellComplex::repairComplex(int i){ - for(int i = 3; i > 0; i--){ + printf("Cell complex before repair: %d volumes, %d faces, %d edges and %d vertices.\n", + getSize(3), getSize(2), getSize(1), getSize(0)); + + while(i > 0){ for(citer cit = firstCell(i); cit != lastCell(i); cit++){ Cell* cell = *cit; @@ -617,18 +831,13 @@ void CellComplex::repairComplex(){ } } + i--; } -/* - int tag = 1; - for(int i = 0; i < 4; i++){ - for(citer cit = firstCell(i); cit != lastCell(i); cit++){ - Cell* cell = *cit; - cell->setTag(tag); - tag++; - } - } - */ + + printf("Cell complex after repair: %d volumes, %d faces, %d edges and %d vertices.\n", + getSize(3), getSize(2), getSize(1), getSize(0)); + return; } @@ -714,13 +923,13 @@ int CellComplex::writeComplexMSH(const std::string &name){ fprintf(fp, "$Nodes\n"); - std::set<MVertex*, Less_MVertex> domainVertices; - getDomainVertices(domainVertices, true); - getDomainVertices(domainVertices, false); + //std::set<MVertex*, Less_MVertex> domainVertices; + //getDomainVertices(domainVertices, true); + //getDomainVertices(domainVertices, false); - fprintf(fp, "%d\n", domainVertices.size()); + fprintf(fp, "%d\n", _domainVertices.size()); - for(std::set<MVertex*, Less_MVertex>::iterator vit = domainVertices.begin(); vit != domainVertices.end(); vit++){ + for(std::set<MVertex*, Less_MVertex>::iterator vit = _domainVertices.begin(); vit != _domainVertices.end(); vit++){ MVertex* vertex = *vit; fprintf(fp, "%d %.16g %.16g %.16g\n", vertex->getNum(), vertex->x(), vertex->y(), vertex->z() ); } diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h index 587bfd68bde24bf0136a6a15ad526e16445b1685..ebeafaedec417de6a7c084a95c0cab501b4e62bf 100644 --- a/Geo/CellComplex.h +++ b/Geo/CellComplex.h @@ -33,9 +33,6 @@ class Cell // maximum number of higher dimensional cells on the coboundary of this cell int _cbdMaxSize; - int _bdSize; - int _cbdSize; - // whether this cell belongs to a subdomain // used in relative homology computation bool _inSubdomain; @@ -43,8 +40,13 @@ class Cell // whether this cell belongs to the boundary of a cell complex bool _onDomainBoundary; + // unique tag for each cell int _tag; + // cells on the boundary and on the coboundary of thhis cell + std::list<Cell*> _boundary; + std::list<Cell*> _coboundary; + public: Cell(){} virtual ~Cell(){} @@ -70,10 +72,31 @@ class Cell virtual unsigned int getBdMaxSize() const { return _bdMaxSize; }; virtual unsigned int getCbdMaxSize() const { return _cbdMaxSize; }; - virtual int getBdSize() { return _bdSize; } - virtual void setBdSize(int size) { _bdSize = size; } - virtual int getCbdSize() { return _cbdSize; } - virtual void setCbdSize(int size) { _cbdSize = size; } + virtual int getBoundarySize() { return _boundary.size(); } + virtual int getCoboundarySize() { return _coboundary.size(); } + + virtual void setBoundary(std::list<Cell*> boundary){ _boundary = boundary; } + virtual void setBoundary(std::vector<Cell*> boundary){ + for(int i = 0; i < boundary.size(); i++) _boundary.push_back(boundary.at(i)); } + virtual void setCoboundary(std::list<Cell*> coboundary){ _coboundary = coboundary; } + virtual void setCoboundary(std::vector<Cell*> coboundary){ + for(int i = 0; i < coboundary.size(); i++) _coboundary.push_back(coboundary.at(i)); } + virtual std::list<Cell*> getBoundary() { return _boundary; } + virtual std::list<Cell*> getCoboundary() { return _coboundary; } + virtual void addBoundaryCell(Cell* cell) { _boundary.push_back(cell); } + virtual void addCoboundaryCell(Cell* cell) { _coboundary.push_back(cell); } + virtual void removeBoundaryCell(Cell* cell) { + for(std::list<Cell*>::iterator it = _boundary.begin(); it != _boundary.end(); it++){ + Cell* cell2 = *it; + if(cell2->getTag() == cell->getTag()) { _boundary.erase(it); break; } + } + } + virtual void removeCoboundaryCell(Cell* cell) { + for(std::list<Cell*>::iterator it = _coboundary.begin(); it != _coboundary.end(); it++){ + Cell* cell2 = *it; + if(cell2->getTag() == cell->getTag()) { _coboundary.erase(it); break; } + } + } virtual bool inSubdomain() const { return _inSubdomain; } virtual void setInSubdomain(bool subdomain) { _inSubdomain = subdomain; } @@ -89,6 +112,9 @@ class Cell virtual inline double y() const { return 0; } virtual inline double z() const { return 0; } + virtual int getNumFacets() const { return 0; } + virtual void getFacetVertices(const int num, std::vector<int> &v) const {}; + bool operator==(const Cell* c2){ if(this->getNumVertices() != c2->getNumVertices()){ return false; @@ -106,15 +132,13 @@ class Cell return (this->getNumVertices() < c2->getNumVertices()); } for(int i=0; i < this->getNumVertices();i++){ - if(this->getVertex(i) < c2->getVertex(i)){ - return true; - } + if(this->getVertex(i) < c2->getVertex(i)) return true; + else if (this->getVertex(i) > c2->getVertex(i)) return false; } return false; } - }; // Simplicial cell type. @@ -123,8 +147,7 @@ class Simplex : public Cell public: Simplex() : Cell() { - _cbdSize = 1000; // big number - _bdSize = 1000; + } virtual ~Simplex(){} @@ -203,17 +226,24 @@ class OneSimplex : public Simplex _v[1] = dummy; } - virtual ~OneSimplex(){} + ~OneSimplex(){} - virtual int getDim() const { return 1; } - virtual int getNumVertices() const { return 2; } - virtual int getVertex(int vertex) const {return _v[vertex]; } - virtual bool hasVertex(int vertex) const {return (_v[0] == vertex || _v[1] == vertex); } + int getDim() const { return 1; } + int getNumVertices() const { return 2; } + int getNumFacets() const { return 2; } + int getVertex(int vertex) const {return _v[vertex]; } + bool hasVertex(int vertex) const {return (_v[0] == vertex || _v[1] == vertex); } - virtual std::vector<int> getVertexVector() const { + std::vector<int> getVertexVector() const { return std::vector<int>(_v, _v + sizeof(_v)/sizeof(int) ); } - virtual void printCell() const { printf("Vertices: %d %d\n", _v[0], _v[1]); } + void getFacetVertices(const int num, std::vector<int> &v) const { + v.resize(1); + v[0] = _v[num]; + } + + + void printCell() const { printf("Vertices: %d %d\n", _v[0], _v[1]); } }; // Two simplex cell type. @@ -223,6 +253,16 @@ class TwoSimplex : public Simplex // numbers of the vertices of this simplex // same as the corresponding vertices in the finite element mesh int _v[3]; + + int edges_tri(const int edge, const int vert) const{ + static const int e[3][2] = { + {0, 1}, + {1, 2}, + {2, 0} + }; + return e[edge][vert]; + } + public: TwoSimplex(std::vector<int> vertices, bool subdomain=false, bool boundary=false) : Simplex(){ @@ -243,17 +283,24 @@ class TwoSimplex : public Simplex _v[2] = dummy; } - virtual ~TwoSimplex(){} + ~TwoSimplex(){} - virtual int getDim() const { return 2; } - virtual int getNumVertices() const { return 3; } - virtual int getVertex(int vertex) const {return _v[vertex]; } - virtual bool hasVertex(int vertex) const {return + int getDim() const { return 2; } + int getNumVertices() const { return 3; } + int getNumFacets() const { return 3; } + int getVertex(int vertex) const {return _v[vertex]; } + bool hasVertex(int vertex) const {return (_v[0] == vertex || _v[1] == vertex || _v[2] == vertex); } - virtual std::vector<int> getVertexVector() const { + std::vector<int> getVertexVector() const { return std::vector<int>(_v, _v + sizeof(_v)/sizeof(int) ); } - virtual void printCell() const { printf("Vertices: %d %d %d\n", _v[0], _v[1], _v[2]); } + void getFacetVertices(const int num, std::vector<int> &v) const { + v.resize(2); + v[0] = _v[edges_tri(num, 0)]; + v[1] = _v[edges_tri(num, 1)]; + } + + void printCell() const { printf("Vertices: %d %d %d\n", _v[0], _v[1], _v[2]); } }; // Three simplex cell type. @@ -263,6 +310,17 @@ class ThreeSimplex : public Simplex // numbers of the vertices of this simplex // same as the corresponding vertices in the finite element mesh int _v[4]; + + int faces_tetra(const int face, const int vert) const{ + static const int f[4][3] = { + {0, 2, 1}, + {0, 1, 3}, + {0, 3, 2}, + {3, 1, 2} + }; + return f[face][vert]; + } + public: ThreeSimplex(std::vector<int> vertices, bool subdomain=false, bool boundary=false) : Simplex(){ @@ -285,16 +343,24 @@ class ThreeSimplex : public Simplex _v[3] = dummy; } - virtual ~ThreeSimplex(){} + ~ThreeSimplex(){} - virtual int getDim() const { return 3; } - virtual int getNumVertices() const { return 4; } - virtual int getVertex(int vertex) const {return _v[vertex]; } - virtual bool hasVertex(int vertex) const {return + int getDim() const { return 3; } + int getNumVertices() const { return 4; } + int getNumFacets() const { return 4; } + int getVertex(int vertex) const {return _v[vertex]; } + bool hasVertex(int vertex) const {return (_v[0] == vertex || _v[1] == vertex || _v[2] == vertex || _v[3] == vertex); } - virtual std::vector<int> getVertexVector() const { + std::vector<int> getVertexVector() const { return std::vector<int>(_v, _v + sizeof(_v)/sizeof(int) ); } + void getFacetVertices(const int num, std::vector<int> &v) const { + v.resize(3); + v[0] = _v[faces_tetra(num, 0)]; + v[1] = _v[faces_tetra(num, 1)]; + v[2] = _v[faces_tetra(num, 2)]; + } + virtual void printCell() const { printf("Vertices: %d %d %d %d\n", _v[0], _v[1], _v[2], _v[3]); } }; @@ -323,15 +389,16 @@ class Less_Cell{ } }; - class Equal_Cell{ public: - bool operator()(const Cell* c1, const Cell* c2) const { - - if(c1->getNumVertices() != c2->getNumVertices()) return false; - + bool operator ()(const Cell* c1, const Cell* c2){ + if(c1->getNumVertices() != c2->getNumVertices()){ + return false; + } for(int i=0; i < c1->getNumVertices();i++){ - if(c1->getVertex(i) != c2->getVertex(i)) return false; + if(c1->getVertex(i) != c2->getVertex(i)){ + return false; + } } return true; } @@ -359,21 +426,25 @@ class CellComplex std::vector<GEntity*> _boundary; + std::set<MVertex*, Less_MVertex> _domainVertices; + // sorted containers of unique cells in this cell complex // one for each dimension std::set<Cell*, Less_Cell> _cells[4]; std::set<Cell*, Less_Cell> _originalCells[4]; + bool _simplicial; + public: // iterator for the cells of same dimension typedef std::set<Cell*, Less_Cell>::iterator citer; protected: // enqueue cells in queue if they are not there already - virtual void enqueueCells(std::vector<Cell*>& cells, + virtual void enqueueCells(std::list<Cell*>& cells, std::queue<Cell*>& Q, std::set<Cell*, Less_Cell>& Qset); - virtual void enqueueCells(std::vector<Cell*>& cells, std::list<Cell*>& Q); + virtual void enqueueCells(std::list<Cell*>& cells, std::list<Cell*>& Q); virtual void enqueueCellsIt(std::vector< std::set<Cell*, Less_Cell>::iterator >& cells, std::queue<Cell*>& Q, std::set<Cell*, Less_Cell>& Qset); @@ -381,7 +452,8 @@ class CellComplex virtual void removeCellQset(Cell*& cell, std::set<Cell*, Less_Cell>& Qset); // insert cells into this cell complex - virtual void insertCells(bool subdomain, bool boundary); + virtual void insert_cells(bool subdomain, bool boundary); + virtual void insert_cells2(bool subdomain, bool boundary); public: CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain, std::set<Cell*, Less_Cell> cells ) { @@ -395,6 +467,8 @@ class CellComplex CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain ); virtual ~CellComplex(){} + virtual bool simplicial() { return _simplicial; } + // get the number of certain dimensional cells virtual int getSize(int dim){ return _cells[dim].size(); } @@ -413,7 +487,7 @@ class CellComplex // kappa for two cells of this cell complex // implementation will vary depending on cell type - virtual int kappa(Cell* sigma, Cell* tau) const { return sigma->kappa(tau); } + virtual inline int kappa(Cell* sigma, Cell* tau) const { return sigma->kappa(tau); } // cells on the boundary of a cell virtual std::vector<Cell*> bd(Cell* sigma); @@ -423,7 +497,7 @@ class CellComplex virtual std::vector< std::set<Cell*, Less_Cell>::iterator > cbdIt(Cell* tau); // remove a cell from this cell complex - virtual void removeCell(Cell* cell, bool deleteCell=false); + virtual void removeCell(Cell* cell); virtual void removeCellIt(std::set<Cell*, Less_Cell>::iterator cell); virtual void insertCell(Cell* cell); @@ -434,12 +508,14 @@ class CellComplex // coreduction of this cell complex // removes corection pairs of cells of dimension dim and dim+1 - virtual int coreduction(int dim, bool deleteCells=false); + virtual int coreduction(int dim); + virtual int coreduction2(int dim); // stores removed cells virtual int coreduction(int dim, std::set<Cell*, Less_Cell>& removedCells); // reduction of this cell complex // removes reduction pairs of cell of dimension dim and dim-1 - virtual int reduction(int dim, bool deleteCells=false); + virtual int reduction(int dim); + virtual int reduction2(int dim); // useful functions for (co)reduction of cell complex virtual void reduceComplex(); @@ -455,11 +531,23 @@ class CellComplex virtual int coreductionMrozek(Cell* generator); virtual int coreductionMrozek2(Cell* generator); virtual int coreductionMrozek3(Cell* generator); - - virtual void restoreComplex(){ for(int i = 0; i < 4; i++) _cells[i] = _originalCells[i]; } + + // never use, O(n^2) complexity + virtual void restoreComplex(){ + for(int i = 0; i < 4; i++) _cells[i] = _originalCells[i]; + + for(int i = 0; i < 4; i++){ + for(citer cit = firstCell(i); cit != lastCell(i); cit++){ + Cell* cell = *cit; + cell->setBoundary(bd(cell)); + cell->setCoboundary(cbd(cell)); + } + } + + } // add every volume, face and edge its missing boundary cells - virtual void repairComplex(); + virtual void repairComplex(int i=3); // change non-subdomain cells to be in subdomain, subdomain cells to not to be in subdomain virtual void swapSubdomain(); diff --git a/Geo/ChainComplex.cpp b/Geo/ChainComplex.cpp index 524e6235f87c050b1e15f96ea77a11f607791693..c0eae87ce57ebaf0f4487d95a5b1532a97c6b1cf 100644 --- a/Geo/ChainComplex.cpp +++ b/Geo/ChainComplex.cpp @@ -279,7 +279,7 @@ void ChainComplex::computeHomology(bool dual){ gmp_matrix_rows(getKerHMatrix(lowDim)), gmp_matrix_cols(getKerHMatrix(lowDim))) ); } - + // 5) General case: // 1) Find the bases of boundaries B and cycles Z // 2) find j: B -> Z and @@ -321,7 +321,7 @@ void ChainComplex::computeHomology(bool dual){ setCodHMatrix(lowDim, NULL); setJMatrix(lowDim, NULL); setQMatrix(lowDim, NULL); - + } diff --git a/Geo/Makefile b/Geo/Makefile index b834b47e646fbf89bffbe341fe5df24453129bd1..248d3aa02dad6f2ab6526cb5a2ae96503a53eddc 100644 --- a/Geo/Makefile +++ b/Geo/Makefile @@ -47,7 +47,7 @@ OBJ = ${SRC:.cpp=${OBJEXT}} .SUFFIXES: ${OBJEXT} .cpp -${LIB}: ${OBJ} +${LIB}: ${OBJ} ${AR} ${ARFLAGS}${LIB} ${OBJ} ${RANLIB} ${LIB} diff --git a/utils/misc/celldriver.cpp b/utils/misc/celldriver.cpp index d54683dfd4800f9f1bf64da09b3fc7fcda52f1aa..14040cae5b07d901a12649106f1a098448791f7f 100755 --- a/utils/misc/celldriver.cpp +++ b/utils/misc/celldriver.cpp @@ -93,15 +93,16 @@ int main(int argc, char **argv) } delete chains; + delete complex; - // restore the cell complex to its prereduced state - complex->restoreComplex(); + // create new complex to compute the cuts + CellComplex* complex2 = new CellComplex(domain, subdomain); // reduce the complex by coreduction, this removes all vertices, hence 0 as an argument - complex->coreduceComplex(0); + complex2->coreduceComplex(0); // create a chain complex of a cell complex (construct boundary operator matrices) - ChainComplex* dualChains = new ChainComplex(complex); + ChainComplex* dualChains = new ChainComplex(complex2); // transpose the boundary operator matrices, // these are the boundary operator matrices for the dual chain complex @@ -120,7 +121,7 @@ int main(int argc, char **argv) convert(3-(j-1), dimension); std::string name = dimension + "D Dual cut " + generator; - Chain* chain = new Chain(complex->getCells(j-1), dualChains->getCoeffVector(j,i), complex, name); + Chain* chain = new Chain(complex2->getCells(j-1), dualChains->getCoeffVector(j,i), complex2, name); chain->writeChainMSH("chains.msh"); delete chain; } @@ -129,7 +130,7 @@ int main(int argc, char **argv) delete dualChains; - delete complex; + delete complex2; delete m; GmshFinalize();