diff --git a/Geo/Cell.cpp b/Geo/Cell.cpp index fdfb1a6fd44c1d9e0c0f1c42b16647a5e4105ef8..a102d9dbc76ca1bfa371dabc72b73c8b81543a8f 100755 --- a/Geo/Cell.cpp +++ b/Geo/Cell.cpp @@ -18,7 +18,8 @@ bool Less_Cell::operator()(const Cell* c1, const Cell* c2) const { return (c1->getNumVertices() < c2->getNumVertices()); } - //"natural number" -like ordering (the number of a vertice corresponds a digit) + // "natural number" -like ordering + // (the number of a vertice corresponds a digit) for(int i=0; i < c1->getNumVertices();i++){ if(c1->getSortedVertex(i) < c2->getSortedVertex(i)) return true; @@ -28,8 +29,26 @@ bool Less_Cell::operator()(const Cell* c1, const Cell* c2) const { return false; } + +Cell::Cell(MElement* image, bool subdomain, bool boundary) : + _combined(false), _index(0), _immune(false), _image(NULL), + _deleteImage(false) { + _onDomainBoundary = boundary; + _inSubdomain = subdomain; + _dim = image->getDim(); + _image = image; + for(int i = 0; i < image->getNumVertices(); i++) + _vs.push_back(image->getVertex(i)->getNum()); + std::sort(_vs.begin(), _vs.end()); +} + +Cell::~Cell() { + if(_deleteImage) delete _image; +} + bool Cell::hasVertex(int vertex) const { - std::vector<int>::const_iterator it = std::find(_vs.begin(), _vs.end(), vertex); + std::vector<int>::const_iterator it = std::find(_vs.begin(), _vs.end(), + vertex); if (it != _vs.end()) return true; else return false; } @@ -96,25 +115,6 @@ void Cell::restoreCell(){ _immune = false; } -std::list< Cell* > Cell::getBoundary() { - std::list<Cell*> boundary; - for( biter it= _boundary.begin(); it != _boundary.end();it++){ - Cell* cell = (*it).first; - boundary.push_back(cell); - } - return boundary; -} - -std::list< Cell* > Cell::getCoboundary() { - std::list<Cell*> coboundary; - for( biter it= _coboundary.begin();it!= _coboundary.end();it++){ - Cell* cell = (*it).first; - coboundary.push_back(cell); - } - return coboundary; -} - - bool Cell::addBoundaryCell(int orientation, Cell* cell) { biter it = _boundary.find(cell); if(it != _boundary.end()){ @@ -256,32 +256,42 @@ CombinedCell::CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co) : Cell() { for(int i = 0; i < c1->getNumVertices(); i++) _v.push_back(c1->getVertex(i)); for(int i = 0; i < c2->getNumVertices(); i++){ - if(!this->hasVertex(c2->getVertex(i)->getNum())) _v.push_back(c2->getVertex(i)); + if(!this->hasVertex(c2->getVertex(i)->getNum())){ + _v.push_back(c2->getVertex(i)); + } } // sorted vertices - for(unsigned int i = 0; i < _v.size(); i++) _vs.push_back(_v.at(i)->getNum()); + for(unsigned int i = 0; i < _v.size(); i++){ + _vs.push_back(_v.at(i)->getNum()); + } std::sort(_vs.begin(), _vs.end()); // cells - _cells = c1->getCells(); - std::list< std::pair<int, Cell*> > c2Cells = c2->getCells(); - for(std::list< std::pair<int, Cell*> >::iterator it = c2Cells.begin(); it != c2Cells.end(); it++){ + c1->getCells(_cells); + std::list< std::pair<int, Cell*> > c2Cells; + c2->getCells(c2Cells); + for(std::list< std::pair<int, Cell*> >::iterator it = c2Cells.begin(); + it != c2Cells.end(); it++){ if(!orMatch) (*it).first = -1*(*it).first; _cells.push_back(*it); } // boundary cells - std::map< Cell*, int, Less_Cell > c1Boundary = c1->getOrientedBoundary(); - std::map< Cell*, int, Less_Cell > c2Boundary = c2->getOrientedBoundary(); + std::map< Cell*, int, Less_Cell > c1Boundary; + c1->getBoundary(c1Boundary); + std::map< Cell*, int, Less_Cell > c2Boundary; + c2->getBoundary(c2Boundary); - for(std::map<Cell*, int, Less_Cell>::iterator it = c1Boundary.begin(); it != c1Boundary.end(); it++){ + for(std::map<Cell*, int, Less_Cell>::iterator it = c1Boundary.begin(); + it != c1Boundary.end(); it++){ Cell* cell = (*it).first; int ori = (*it).second; cell->removeCoboundaryCell(c1); if(this->addBoundaryCell(ori, cell)) cell->addCoboundaryCell(ori, this); } - for(std::map<Cell*, int, Less_Cell >::iterator it = c2Boundary.begin(); it != c2Boundary.end(); it++){ + for(std::map<Cell*, int, Less_Cell >::iterator it = c2Boundary.begin(); + it != c2Boundary.end(); it++){ Cell* cell = (*it).first; if(!orMatch) (*it).second = -1*(*it).second; int ori = (*it).second; @@ -290,7 +300,11 @@ CombinedCell::CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co) : Cell() { std::map<Cell*, int, Less_Cell >::iterator it2 = c1Boundary.find(cell); bool old = false; if(it2 != c1Boundary.end()) old = true; - if(!old){ if(this->addBoundaryCell(ori, cell)) cell->addCoboundaryCell(ori, this); } + if(!old){ + if(this->addBoundaryCell(ori, cell)) { + cell->addCoboundaryCell(ori, this); + } + } } else{ if(this->addBoundaryCell(ori, cell)) cell->addCoboundaryCell(ori, this); @@ -298,16 +312,20 @@ CombinedCell::CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co) : Cell() { } // coboundary cells - std::map<Cell*, int, Less_Cell > c1Coboundary = c1->getOrientedCoboundary(); - std::map<Cell*, int, Less_Cell > c2Coboundary = c2->getOrientedCoboundary(); + std::map<Cell*, int, Less_Cell > c1Coboundary; + c1->getCoboundary(c1Coboundary); + std::map<Cell*, int, Less_Cell > c2Coboundary; + c2->getCoboundary(c2Coboundary); - for(std::map<Cell*, int, Less_Cell>::iterator it = c1Coboundary.begin(); it != c1Coboundary.end(); it++){ + for(std::map<Cell*, int, Less_Cell>::iterator it = c1Coboundary.begin(); + it != c1Coboundary.end(); it++){ Cell* cell = (*it).first; int ori = (*it).second; cell->removeBoundaryCell(c1); if(this->addCoboundaryCell(ori, cell)) cell->addBoundaryCell(ori, this); } - for(std::map<Cell*, int, Less_Cell>::iterator it = c2Coboundary.begin(); it != c2Coboundary.end(); it++){ + for(std::map<Cell*, int, Less_Cell>::iterator it = c2Coboundary.begin(); + it != c2Coboundary.end(); it++){ Cell* cell = (*it).first; if(!orMatch) (*it).second = -1*(*it).second; int ori = (*it).second; @@ -316,7 +334,11 @@ CombinedCell::CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co) : Cell() { std::map<Cell*, int, Less_Cell >::iterator it2 = c1Coboundary.find(cell); bool old = false; if(it2 != c1Coboundary.end()) old = true; - if(!old) { if(this->addCoboundaryCell(ori, cell)) cell->addBoundaryCell(ori, this); } + if(!old) { + if(this->addCoboundaryCell(ori, cell)){ + cell->addBoundaryCell(ori, this); + } + } } else { if(this->addCoboundaryCell(ori, cell)) cell->addBoundaryCell(ori, this); @@ -325,13 +347,4 @@ CombinedCell::CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co) : Cell() { } - -CombinedCell::~CombinedCell(){ - std::list< std::pair<int, Cell*> > cells = getCells(); - for(std::list< std::pair<int, Cell*> >::iterator it = cells.begin(); it != cells.end(); it++){ - Cell* cell2 = (*it).second; - delete cell2; - } -} - #endif diff --git a/Geo/Cell.h b/Geo/Cell.h index dd5b41bb3b2f5595df8f44e71062c32741c9f34e..f42d376cddcf2000bce15e510c44d8684a254c82 100644 --- a/Geo/Cell.h +++ b/Geo/Cell.h @@ -40,208 +40,203 @@ class Less_Cell{ // Class representing an elementary cell of a cell complex. class Cell { - protected: - - // cell dimension - int _dim; - - // whether this cell belongs to a subdomain, immutable - // used in relative homology computation - bool _inSubdomain; - - // whether this cell belongs to the boundary of a cell complex - bool _onDomainBoundary; - - // whether this cell a combinded cell of elemetary cells - bool _combined; - - // mutable index for each cell (used to create boundary operator matrices) - int _index; - - // for some algorithms to omit this cell - bool _immune; + protected: - // mutable list of cells on the boundary and on the coboundary of this cell - std::map< Cell*, int, Less_Cell > _boundary; - std::map< Cell*, int, Less_Cell > _coboundary; - - // immutable original boundary and coboundary before the reduction of the cell complex - std::map<Cell*, int, Less_Cell > _obd; - std::map<Cell*, int, Less_Cell > _ocbd; - - // The mesh element that is the image of this cell - MElement* _image; - // Whether to delete the mesh element when done (created for homology computation only) - bool _deleteImage; + // cell dimension + int _dim; - // sorted vertices of this cell (used for ordering of the cells) - std::vector<int> _vs; - - public: - Cell(){ - _combined = false; - _index = 0; - _immune = false; - _image = NULL; - _deleteImage = false; - } - - Cell(MElement* image, bool subdomain, bool boundary){ - _combined = false; - _index = 0; - _immune = false; - _image = image; - _onDomainBoundary = boundary; - _inSubdomain = subdomain; - _dim = image->getDim(); - _deleteImage = false; - for(int i = 0; i < image->getNumVertices(); i++) _vs.push_back(image->getVertex(i)->getNum()); - std::sort(_vs.begin(), _vs.end()); - } - virtual ~Cell() {if(_deleteImage) delete _image; } - - virtual MElement* getImageMElement() const { return _image; }; - - virtual int getDim() const { return _dim; }; - virtual int getIndex() const { return _index; }; - virtual void setIndex(int index) { _index = index; }; - virtual int getNum() { return _image->getNum(); } - virtual int getType() { return _image->getType(); } - virtual int getTypeForMSH() { return _image->getTypeForMSH(); } - virtual int getPartition() { return _image->getPartition(); } - virtual void setImmune(bool immune) { _immune = immune; }; - virtual bool getImmune() const { return _immune; }; - virtual void setDeleteImage(bool deleteImage) { _deleteImage = deleteImage; }; - virtual bool getDeleteImage() const { return _deleteImage; }; - - // get the number of vertices this cell has - virtual int getNumVertices() const { return _image->getNumVertices(); } - virtual MVertex* getVertex(int vertex) const { return _image->getVertex(vertex); } - virtual int getSortedVertex(int vertex) const { return _vs.at(vertex); } - - // restores the cell information to its original state before reduction - virtual void restoreCell(); - - // true if this cell has given vertex - virtual bool hasVertex(int vertex) const; + // whether this cell belongs to a subdomain, immutable + // used in relative homology computation + bool _inSubdomain; + + // whether this cell belongs to the boundary of a cell complex + bool _onDomainBoundary; + + // whether this cell a combinded cell of elemetary cells + bool _combined; + + // mutable index for each cell (used to create boundary operator matrices) + int _index; + + // for some algorithms to omit this cell + bool _immune; + + // mutable list of cells on the boundary and on the coboundary of this cell + std::map< Cell*, int, Less_Cell > _boundary; + std::map< Cell*, int, Less_Cell > _coboundary; + + // immutable original boundary and coboundary before the reduction of the + // cell complex + std::map<Cell*, int, Less_Cell > _obd; + std::map<Cell*, int, Less_Cell > _ocbd; + + // The mesh element that is the image of this cell + MElement* _image; + // Whether to delete the mesh element when done + // (created for homology computation only) + bool _deleteImage; + + // sorted vertices of this cell (used for ordering of the cells) + std::vector<int> _vs; + + public: - // (co)boundary cell iterator - typedef std::map<Cell*, int, Less_Cell>::iterator biter; - - virtual int getBoundarySize() { return _boundary.size(); } - virtual int getCoboundarySize() { return _coboundary.size(); } - - // get the cell boundary - virtual std::map<Cell*, int, Less_Cell > getOrientedBoundary() { return _boundary; } - virtual std::list< Cell* > getBoundary(); - virtual std::map<Cell*, int, Less_Cell > getOrientedCoboundary() { return _coboundary; } - virtual std::list< Cell* > getCoboundary(); - - // add (co)boundary cell - virtual bool addBoundaryCell(int orientation, Cell* cell); - virtual bool addCoboundaryCell(int orientation, Cell* cell); - - // remove (co)boundary cell - virtual int removeBoundaryCell(Cell* cell, bool other=true); - virtual int removeCoboundaryCell(Cell* cell, bool other=true); - - // true if has given cell on (original) (co)boundary - virtual bool hasBoundary(Cell* cell, bool org=false); - virtual bool hasCoboundary(Cell* cell, bool org=false); - - virtual void clearBoundary() { _boundary.clear(); } - virtual void clearCoboundary() { _coboundary.clear(); } - + Cell() : _combined(false), _index(0), _immune(false), _image(NULL), + _deleteImage(false) {} + Cell(MElement* image, bool subdomain, bool boundary); + + virtual ~Cell(); + + virtual MElement* getImageMElement() const { return _image; }; + + virtual int getDim() const { return _dim; }; + virtual int getIndex() const { return _index; }; + virtual void setIndex(int index) { _index = index; }; + virtual int getNum() { return _image->getNum(); } + virtual int getType() { return _image->getType(); } + virtual int getTypeForMSH() { return _image->getTypeForMSH(); } + virtual int getPartition() { return _image->getPartition(); } + virtual void setImmune(bool immune) { _immune = immune; }; + virtual bool getImmune() const { return _immune; }; + virtual void setDeleteImage(bool deleteImage) { + _deleteImage = deleteImage; }; + virtual bool getDeleteImage() const { return _deleteImage; }; + + // get the number of vertices this cell has + virtual int getNumVertices() const { return _image->getNumVertices(); } + virtual MVertex* getVertex(int vertex) const { + return _image->getVertex(vertex); } + virtual int getSortedVertex(int vertex) const { return _vs.at(vertex); } + + // restores the cell information to its original state before reduction + virtual void restoreCell(); + + // true if this cell has given vertex + virtual bool hasVertex(int vertex) const; + + // (co)boundary cell iterator + typedef std::map<Cell*, int, Less_Cell>::iterator biter; + + virtual int getBoundarySize() { return _boundary.size(); } + virtual int getCoboundarySize() { return _coboundary.size(); } + + // get the cell boundary + virtual void getBoundary(std::map<Cell*, int, Less_Cell >& boundary){ + boundary = _boundary; } + virtual void getCoboundary( std::map<Cell*, int, Less_Cell >& coboundary ){ + coboundary = _coboundary; } + + // add (co)boundary cell + virtual bool addBoundaryCell(int orientation, Cell* cell); + virtual bool addCoboundaryCell(int orientation, Cell* cell); + + // remove (co)boundary cell + virtual int removeBoundaryCell(Cell* cell, bool other=true); + virtual int removeCoboundaryCell(Cell* cell, bool other=true); + + // true if has given cell on (original) (co)boundary + virtual bool hasBoundary(Cell* cell, bool org=false); + virtual bool hasCoboundary(Cell* cell, bool org=false); + + virtual void clearBoundary() { _boundary.clear(); } + virtual void clearCoboundary() { _coboundary.clear(); } + // algebraic dual of the cell - virtual void makeDualCell(); - - // print cell info - virtual void printCell(); - virtual void printBoundary(); - virtual void printCoboundary(); - - // original (co)boundary - virtual void addOrgBdCell(int orientation, Cell* cell) { _obd.insert( std::make_pair(cell, orientation ) ); }; - virtual void addOrgCbdCell(int orientation, Cell* cell) { _ocbd.insert( std::make_pair(cell, orientation ) ); }; - virtual std::map<Cell*, int, Less_Cell > getOrgBd() { return _obd; } - virtual std::map<Cell*, int, Less_Cell > getOrgCbd() { return _ocbd; } - virtual void printOrgBd(); - virtual void printOrgCbd(); - - virtual bool inSubdomain() const { return _inSubdomain; } - virtual void setInSubdomain(bool subdomain) { _inSubdomain = subdomain; } - - virtual bool onDomainBoundary() const { return _onDomainBoundary; } - virtual void setOnDomainBoundary(bool domainboundary) { _onDomainBoundary = domainboundary; } - - // get the number of facets of this cell - virtual int getNumFacets() const; - // get the vertices on a facet of this cell - virtual void getFacetVertices(const int num, std::vector<MVertex*> &v) const; - - // get boundary cell orientation - virtual int getFacetOri(Cell* cell) { + virtual void makeDualCell(); + + // print cell info + virtual void printCell(); + virtual void printBoundary(); + virtual void printCoboundary(); + + // original (co)boundary + virtual void addOrgBdCell(int orientation, Cell* cell) { + _obd.insert( std::make_pair(cell, orientation ) ); }; + virtual void addOrgCbdCell(int orientation, Cell* cell) { + _ocbd.insert( std::make_pair(cell, orientation ) ); }; + virtual void getOrgBd( std::map<Cell*, int, Less_Cell >& obd) { + obd = _obd; } + virtual void getOrgCbd( std::map<Cell*, int, Less_Cell >& obdc) { + obdc = _ocbd; } + virtual void printOrgBd(); + virtual void printOrgCbd(); + + virtual bool inSubdomain() const { return _inSubdomain; } + virtual void setInSubdomain(bool subdomain) { _inSubdomain = subdomain; } + + virtual bool onDomainBoundary() const { return _onDomainBoundary; } + virtual void setOnDomainBoundary(bool domainboundary) { + _onDomainBoundary = domainboundary; } + + // get the number of facets of this cell + virtual int getNumFacets() const; + // get the vertices on a facet of this cell + virtual void getFacetVertices(const int num, std::vector<MVertex*> &v) const; + + // get boundary cell orientation + virtual int getFacetOri(Cell* cell) { std::vector<MVertex*> v; - for(int i = 0; i < cell->getNumVertices(); i++) v.push_back(cell->getVertex(i)); + for(int i = 0; i < cell->getNumVertices(); i++) { + v.push_back(cell->getVertex(i)); + } return getFacetOri(v); - } - virtual int getFacetOri(std::vector<MVertex*> &v); - - // tools for combined cells - virtual bool isCombined() { return _combined; } - virtual std::list< std::pair<int, Cell*> > getCells() { - std::list< std::pair<int, Cell*> >cells; - cells.push_back( std::make_pair(1, this)); - return cells; - } - virtual int getNumCells() {return 1;} - - // equivalence - bool operator==(const Cell& c2) const { - if(this->getNumVertices() != c2.getNumVertices()){ - return false; - } - for(int i=0; i < this->getNumVertices();i++){ - if(this->getSortedVertex(i) != c2.getSortedVertex(i)){ - return false; - } - } - return true; - } + } + virtual int getFacetOri(std::vector<MVertex*> &v); + + // tools for combined cells + virtual bool isCombined() { return _combined; } + virtual void getCells( std::list< std::pair<int, Cell*> >& cells) { + cells.clear(); + cells.push_back( std::make_pair(1, this)); + return; + } + virtual int getNumCells() {return 1;} + + // equivalence + bool operator==(const Cell& c2) const { + if(this->getNumVertices() != c2.getNumVertices()){ + return false; + } + for(int i=0; i < this->getNumVertices();i++){ + if(this->getSortedVertex(i) != c2.getSortedVertex(i)){ + return false; + } + } + return true; + } }; // A cell that is a combination of cells of same dimension class CombinedCell : public Cell{ - - private: - // vertices - std::vector<MVertex*> _v; - // sorted list of all vertices - std::vector<int> _vs; - // list of cells this cell is a combination of - std::list< std::pair<int, Cell*> > _cells; - int _num; - - public: - - CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co=false); - ~CombinedCell(); - - int getNum() { return _num; } - int getType() { return 0; } - int getTypeForMSH() { return 0; } - int getPartition() { return 0; } - - int getNumVertices() const { return _v.size(); } - MVertex* getVertex(int vertex) const { return _v.at(vertex); } - int getSortedVertex(int vertex) const { return _vs.at(vertex); } - - std::list< std::pair<int, Cell*> > getCells() { return _cells; } - int getNumCells() {return _cells.size();} - + + private: + // vertices + std::vector<MVertex*> _v; + // sorted list of all vertices + std::vector<int> _vs; + // list of cells this cell is a combination of + std::list< std::pair<int, Cell*> > _cells; + int _num; + + public: + + CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co=false); + ~CombinedCell() {} + + int getNum() { return _num; } + int getType() { return 0; } + int getTypeForMSH() { return 0; } + int getPartition() { return 0; } + + int getNumVertices() const { return _v.size(); } + MVertex* getVertex(int vertex) const { return _v.at(vertex); } + int getSortedVertex(int vertex) const { return _vs.at(vertex); } + + void getCells(std::list< std::pair<int, Cell*> >& cells) { cells = _cells; } + int getNumCells() {return _cells.size();} + }; - #endif #endif diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp index cd88192b041548c497c53806307439547d7d9018..e2112bf73831fd780e3e27f52658fe3497333f76 100644 --- a/Geo/CellComplex.cpp +++ b/Geo/CellComplex.cpp @@ -47,17 +47,20 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su } -void CellComplex::find_boundary(std::vector<GEntity*>& domain, std::vector<GEntity*>& subdomain){ - +void CellComplex::find_boundary(std::vector<GEntity*>& domain, + std::vector<GEntity*>& 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){ std::list<GFace*> faces = _domain.at(j)->faces(); - for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); it++){ + for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); + it++){ GFace* face = *it; duplicate = false; - for(std::vector<GEntity*>::iterator itb = _boundary.begin(); itb != _boundary.end(); itb++){ + for(std::vector<GEntity*>::iterator itb = _boundary.begin(); + itb != _boundary.end(); itb++){ GEntity* entity = *itb; if(face->tag() == entity->tag()){ _boundary.erase(itb); @@ -71,11 +74,13 @@ void CellComplex::find_boundary(std::vector<GEntity*>& domain, std::vector<GEnti else if(_domain.at(j)->dim() == 2){ std::list<GEdge*> edges = _domain.at(j)->edges(); - for(std::list<GEdge*>::iterator it = edges.begin(); it != edges.end(); it++){ + for(std::list<GEdge*>::iterator it = edges.begin(); it != edges.end(); + it++){ GEdge* edge = *it; duplicate = false; std::vector<GEntity*>::iterator erase; - for(std::vector<GEntity*>::iterator itb = _boundary.begin(); itb != _boundary.end(); itb++){ + for(std::vector<GEntity*>::iterator itb = _boundary.begin(); + itb != _boundary.end(); itb++){ GEntity* entity = *itb; if(edge->tag() == entity->tag()){ _boundary.erase(itb); @@ -88,10 +93,12 @@ void CellComplex::find_boundary(std::vector<GEntity*>& domain, std::vector<GEnti } 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++){ + for(std::list<GVertex*>::iterator it = vertices.begin(); + it != vertices.end(); it++){ GVertex* vertex = *it; duplicate = false; - for(std::vector<GEntity*>::iterator itb = _boundary.begin(); itb != _boundary.end(); itb++){ + for(std::vector<GEntity*>::iterator itb = _boundary.begin(); + itb != _boundary.end(); itb++){ GEntity* entity = *itb; if(vertex->tag() == entity->tag()){ _boundary.erase(itb); @@ -132,10 +139,13 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){ int type = domain.at(j)->getMeshElement(i)->getTypeForMSH(); Cell* cell; // simplex types - if(type == MSH_LIN_2 || type == MSH_TRI_3 || type == MSH_TET_4 || type == MSH_LIN_3 || type == MSH_TRI_6 || - type == MSH_TET_10 || type == MSH_PNT || type == MSH_TRI_9 || type == MSH_TRI_10 || type == MSH_TRI_12 || - type == MSH_TRI_15 || type == MSH_TRI_15I || type == MSH_TRI_21 || type == MSH_LIN_4 || - type == MSH_LIN_5 || type == MSH_LIN_6 || type == MSH_TET_20 || type == MSH_TET_35 || type == MSH_TET_56 + if(type == MSH_LIN_2 || type == MSH_TRI_3 || type == MSH_TET_4 + || type == MSH_LIN_3 || type == MSH_TRI_6 || type == MSH_TET_10 + || type == MSH_PNT || type == MSH_TRI_9 || type == MSH_TRI_10 + || type == MSH_TRI_12 || type == MSH_TRI_15 || type == MSH_TRI_15I + || type == MSH_TRI_21 || type == MSH_LIN_4 || type == MSH_LIN_5 + || type == MSH_LIN_6 || type == MSH_TET_20 || type == MSH_TET_35 + || type == MSH_TET_56 || type == MSH_TET_34 || type == MSH_TET_52 ){ cell = new Cell(domain.at(j)->getMeshElement(i), subdomain, boundary); } @@ -193,10 +203,11 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){ /*else if(type == MSH_LIN_3 || type == MSH_LIN_4 || type == MSH_LIN_5 || type == MSH_LIN_6) newtype = MSH_PNT;*/ } - if(newtype == 0) Msg::Error("Error: mesh element %d not implemented yet! \n", type); - - //printf("dim: %d type: %d, newtype: %d, vertices: %d \n", dim, type, newtype, vertices.size()); - MElement* element = factory.create(newtype, vertices, 0, cell->getPartition()); + if(newtype == 0){ + Msg::Error("Error: mesh element %d not implemented yet! \n", type); } + + MElement* element = factory.create(newtype, vertices, 0, + cell->getPartition()); Cell* newCell = new Cell(element, subdomain, boundary); newCell->setImmune(cell->getImmune()); newCell->setDeleteImage(true); @@ -235,37 +246,45 @@ CellComplex::~CellComplex(){ _ocells[i].clear(); } + for(int i = 0; i < _newcells.size(); i++) delete _newcells.at(i); + _newcells.clear(); } /* - CellComplex::CellComplex(CellComplex* cellComplex){ - * - _domain = cellComplex->getDomain(); - _subdomain = cellComplex->getSubdomain; - _boundary = cellComplex->getBoundary; - _domainVertices = cellComplex->getDomainVertices; - * - for(int i = 0; i < 4; i++){ - _betti[i] = cellComplex->getBetti(i); - _cells[i] = ocells[i]; - _ocells[i] = ocells[i]; - } - * - _dim = cellComplex->getDim(); - } +CellComplex::CellComplex(CellComplex* cellComplex){ + _domain = cellComplex->getDomain(); + _subdomain = cellComplex->getSubdomain(); + _boundary = cellComplex->getBoundary(); + + for(int i = 0; i < 4; i++){ + _betti[i] = cellComplex->getBetti(i); + _ocells[i] = cellComplex->getOcells(i); + } + _dim = cellComplex->getDim(); + restoreComplex(); +} */ +void CellComplex::insertCell(Cell* cell){ + _newcells.push_back(cell); + std::pair<citer, bool> insertInfo = _cells[cell->getDim()].insert(cell); + if(!insertInfo.second) Msg::Debug("Warning: Cell not inserted! \n"); +} void CellComplex::removeCell(Cell* cell, bool other){ - std::map<Cell*, int, Less_Cell > coboundary = cell->getOrientedCoboundary(); - std::map<Cell*, int, Less_Cell > boundary = cell->getOrientedBoundary(); + std::map<Cell*, int, Less_Cell > coboundary; + cell->getCoboundary(coboundary); + std::map<Cell*, int, Less_Cell > boundary; + cell->getBoundary(boundary); - for(std::map<Cell*, int, Less_Cell>::iterator it = coboundary.begin(); it != coboundary.end(); it++){ + for(std::map<Cell*, int, Less_Cell>::iterator it = coboundary.begin(); + it != coboundary.end(); it++){ Cell* cbdCell = (*it).first; cbdCell->removeBoundaryCell(cell, other); } - for(std::map<Cell*, int, Less_Cell>::iterator it = boundary.begin(); it != boundary.end(); it++){ + for(std::map<Cell*, int, Less_Cell>::iterator it = boundary.begin(); + it != boundary.end(); it++){ Cell* bdCell = (*it).first; bdCell->removeCoboundaryCell(cell, other); } @@ -274,13 +293,17 @@ void CellComplex::removeCell(Cell* cell, bool other){ } -void CellComplex::removeCellQset(Cell*& cell, std::set<Cell*, Less_Cell>& Qset){ - Qset.erase(cell); +void CellComplex::removeCellQset(Cell*& cell, + std::set<Cell*, Less_Cell>& Qset){ + Qset.erase(cell); } -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; +void CellComplex::enqueueCells(std::map<Cell*, int, Less_Cell>& cells, + std::queue<Cell*>& Q, + std::set<Cell*, Less_Cell>& Qset){ + for(std::map<Cell*, int, Less_Cell>::iterator cit = cells.begin(); + cit != cells.end(); cit++){ + Cell* cell = (*cit).first; citer it = Qset.find(cell); //citer it2 = _cells[cell->getDim()].find(cell); if(it == Qset.end()){// && it2 != _cells[cell->getDim()].end()){ @@ -300,9 +323,10 @@ int CellComplex::coreduction(Cell* generator, int omitted){ Q.push(generator); Qset.insert(generator); - - std::list<Cell*> bd_s; - std::list<Cell*> cbd_c; + std::map<Cell*, int, Less_Cell > bd_s; + std::map<Cell*, int, Less_Cell > cbd_c; + //std::list<Cell*> bd_s; + //std::list<Cell*> cbd_c; Cell* s; int round = 0; while( !Q.empty() ){ @@ -312,20 +336,22 @@ int CellComplex::coreduction(Cell* generator, int omitted){ s = Q.front(); Q.pop(); removeCellQset(s, Qset); - bd_s = s->getBoundary(); + s->getBoundary(bd_s); - if( bd_s.size() == 1 && inSameDomain(s, bd_s.front()) ){ + if( bd_s.size() == 1 && inSameDomain(s, bd_s.begin()->first) ){ removeCell(s); - cbd_c = bd_s.front()->getCoboundary(); + bd_s.begin()->first->getCoboundary(cbd_c); enqueueCells(cbd_c, Q, Qset); - removeCell(bd_s.front()); - if(bd_s.front()->getDim() == 0 && omitted > 0) _store.at(omitted-1).insert(bd_s.front()); + removeCell(bd_s.begin()->first); + if(bd_s.begin()->first->getDim() == 0 && omitted > 0){ + _store.at(omitted-1).insert(bd_s.begin()->first); + } coreductions++; } else if(bd_s.empty()){ - cbd_c = s->getCoboundary(); + s->getCoboundary(cbd_c); enqueueCells(cbd_c, Q, Qset); } @@ -337,7 +363,8 @@ int CellComplex::coreduction(Cell* generator, int omitted){ int CellComplex::reduction(int dim, int omitted){ if(dim < 1 || dim > 3) return 0; - std::list<Cell*> cbd_c; + //std::list<Cell*> cbd_c; + std::map<Cell*, int, Less_Cell > cbd_c; int count = 0; bool reduced = true; @@ -350,13 +377,15 @@ int CellComplex::reduction(int dim, int omitted){ Cell* cell = *cit; - cbd_c = cell->getCoboundary(); - if( cbd_c.size() == 1 && inSameDomain(cell, cbd_c.front())){ + cell->getCoboundary(cbd_c); + if( cbd_c.size() == 1 && inSameDomain(cell, cbd_c.begin()->first)){ //&& ( (!cell->getImmune() && !cbd_c.front()->getImmune() ) )){ ++cit; - removeCell(cbd_c.front()); + removeCell(cbd_c.begin()->first); removeCell(cell); - if(dim == getDim() && omitted > 0) _store.at(omitted-1).insert(cbd_c.front()); + if(dim == getDim() && omitted > 0){ + _store.at(omitted-1).insert(cbd_c.begin()->first); + } count++; reduced = true; @@ -367,7 +396,7 @@ int CellComplex::reduction(int dim, int omitted){ } //if(!reduced && ignoreCells) { ignoreCells = false; reduced = true;} - + } return count; @@ -611,21 +640,21 @@ int CellComplex::cocombine(int dim){ std::queue<Cell*> Q; std::set<Cell*, Less_Cell> Qset; - std::list<Cell*> cbd_c; + std::map<Cell*, int, Less_Cell> cbd_c; std::map<Cell*, int, Less_Cell > bd_c; int count = 0; for(citer cit = firstCell(dim); cit != lastCell(dim); cit++){ Cell* cell = *cit; - cbd_c = cell->getCoboundary(); + cell->getCoboundary(cbd_c); enqueueCells(cbd_c, Q, Qset); while(Q.size() != 0){ Cell* s = Q.front(); Q.pop(); - bd_c = s->getOrientedBoundary(); + s->getBoundary(bd_c); if(s->getBoundarySize() == 2){ std::map<Cell*, int, Less_Cell>::iterator it = bd_c.begin(); @@ -639,19 +668,19 @@ int CellComplex::cocombine(int dim){ && inSameDomain(s, c1) && inSameDomain(s, c2) && c1->getNumVertices() < getSize(dim) // heuristics for mammoth cell birth control && c2->getNumVertices() < getSize(dim)){ - + removeCell(s); - cbd_c = c1->getCoboundary(); + c1->getCoboundary(cbd_c); enqueueCells(cbd_c, Q, Qset); - cbd_c = c2->getCoboundary(); + c2->getCoboundary(cbd_c); enqueueCells(cbd_c, Q, Qset); - CombinedCell* newCell = new CombinedCell(c1, c2, (or1 != or2), true ); + CombinedCell* newCell = new CombinedCell(c1, c2, + (or1 != or2), true ); removeCell(c1); removeCell(c2); - std::pair<citer, bool> insertInfo = _cells[dim].insert(newCell); - if(!insertInfo.second) Msg::Debug("Warning: Combined cell not inserted! \n"); + insertCell(newCell); cit = firstCell(dim); count++; @@ -678,20 +707,20 @@ int CellComplex::combine(int dim){ std::queue<Cell*> Q; std::set<Cell*, Less_Cell> Qset; std::map<Cell*, int, Less_Cell> cbd_c; - std::list<Cell*> bd_c; + std::map<Cell*, int, Less_Cell> bd_c; int count = 0; for(citer cit = firstCell(dim); cit != lastCell(dim); cit++){ Cell* cell = *cit; - bd_c = cell->getBoundary(); + cell->getBoundary(bd_c); enqueueCells(bd_c, Q, Qset); while(Q.size() != 0){ Cell* s = Q.front(); Q.pop(); - cbd_c = s->getOrientedCoboundary(); + s->getCoboundary(cbd_c); if(s->getCoboundarySize() == 2){ @@ -709,17 +738,16 @@ int CellComplex::combine(int dim){ removeCell(s); - bd_c = c1->getBoundary(); + c1->getBoundary(bd_c); enqueueCells(bd_c, Q, Qset); - bd_c = c2->getBoundary(); + c2->getBoundary(bd_c); enqueueCells(bd_c, Q, Qset); CombinedCell* newCell = new CombinedCell(c1, c2, (or1 != or2) ); removeCell(c1); removeCell(c2); - - std::pair<citer, bool> insertInfo = _cells[dim].insert(newCell); - if(!insertInfo.second) Msg::Debug("Warning: Combined cell not inserted! \n"); + insertCell(newCell); + cit = firstCell(dim); count++; } @@ -752,7 +780,7 @@ int CellComplex::combine(int dim){ // version of combine that doesn't have a que combined = false; for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){ Cell* s = *cit; - cbd_c = s->getOrientedCoboundary(); + cbd_c = s->getCoboundary(); if(s->getCoboundarySize() == 2 && !(*(cbd_c.front().second) == *(cbd_c.back().second)) && inSameDomain(s, cbd_c.front().second) && inSameDomain(s, cbd_c.back().second) @@ -831,8 +859,10 @@ bool CellComplex::checkCoherence(){ for(int i = 0; i < 4; i++){ for(citer cit = firstCell(i); cit != lastCell(i); cit++){ Cell* cell = *cit; - std::map<Cell*, int, Less_Cell> boundary = cell->getOrientedBoundary(); - for(std::map<Cell*, int, Less_Cell>::iterator it = boundary.begin(); it != boundary.end(); it++){ + std::map<Cell*, int, Less_Cell> boundary; + cell->getBoundary(boundary); + for(std::map<Cell*, int, Less_Cell>::iterator it = boundary.begin(); + it != boundary.end(); it++){ Cell* bdCell = (*it).first; int ori = (*it).second; citer cit = _cells[bdCell->getDim()].find(bdCell); @@ -854,8 +884,10 @@ bool CellComplex::checkCoherence(){ } } - std::map<Cell*, int, Less_Cell> coboundary = cell->getOrientedCoboundary(); - for(std::map<Cell*, int, Less_Cell>::iterator it = coboundary.begin(); it != coboundary.end(); it++){ + std::map<Cell*, int, Less_Cell> coboundary; + cell->getCoboundary(coboundary); + for(std::map<Cell*, int, Less_Cell>::iterator it = coboundary.begin(); + it != coboundary.end(); it++){ Cell* cbdCell = (*it).first; int ori = (*it).second; citer cit = _cells[cbdCell->getDim()].find(cbdCell); diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h index 017925888365673ca31c0b2c4782cfd4c7201318..e0cb5d8592df6c8b88980347958d2b7bff6a99fd 100644 --- a/Geo/CellComplex.h +++ b/Geo/CellComplex.h @@ -31,131 +31,141 @@ class Cell; class CellComplex { private: - - // the domain in the model which this cell complex covers - std::vector<GEntity*> _domain; - // a subdomain of the given domain - // used in relative homology computation, may be empty - std::vector<GEntity*> _subdomain; - - // entities on the boundary of the homology computation domain - std::vector<GEntity*> _boundary; - - // sorted containers of unique cells in this cell complex - // one for each dimension - std::set<Cell*, Less_Cell> _cells[4]; - - // temporary store for omitted cells (generators of the highest dimension) - std::vector< std::set<Cell*, Less_Cell> > _store; - - // original cells of this cell complex - std::set<Cell*, Less_Cell> _ocells[4]; - - // Betti numbers of this cell complex (ranks of homology groups) - int _betti[4]; - - int _dim; - - // is the cell complex simplicial - bool _simplicial; - - // does the domain contain entities of different dimensions - bool _multidim; - - // enqueue cells in queue if they are not there already - void enqueueCells(std::list<Cell*>& cells, - std::queue<Cell*>& Q, std::set<Cell*, Less_Cell>& Qset); - // remove cell from the queue set - void removeCellQset(Cell*& cell, std::set<Cell*, Less_Cell>& Qset); - - // for constructor - void insert_cells(bool subdomain, bool boundary); - void find_boundary(std::vector<GEntity*>& domain, std::vector<GEntity*>& subdomain); - - // remove a cell from this cell complex - void removeCell(Cell* cell, bool other=true); - - // queued coreduction presented in Mrozek's paper - int coreduction(Cell* generator, int omitted=0); - - public: - - CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain ); - //CellComplex(CellComplex* cellComplex) - CellComplex(){} - ~CellComplex(); - - //void emptyTrash(); - - // restore this cell complex to its original state - void restoreComplex(); - - // get the number of certain dimensional cells - int getSize(int dim){ return _cells[dim].size(); } - int getOrgSize(int dim){ return _ocells[dim].size(); } - - int getDim() {return _dim; } - - bool simplicial() { return _simplicial; } - - std::set<Cell*, Less_Cell> getCells(int dim){ return _cells[dim]; } - std::set<Cell*, Less_Cell> getOrgCells(int dim){ return _ocells[dim]; } - - // iterator for the cells of same dimension - typedef std::set<Cell*, Less_Cell>::iterator citer; - - // iterators to the first and last cells of certain dimension - citer firstCell(int dim) {return _cells[dim].begin(); } - citer lastCell(int dim) {return _cells[dim].end(); } - citer firstOrgCell(int dim) {return _ocells[dim].begin(); } - citer lastOrgCell(int dim) {return _ocells[dim].end(); } - - - // true if cell complex has given cell - bool hasCell(Cell* cell, bool org=false); - - // check whether two cells both belong to subdomain or if neither one does - bool inSameDomain(Cell* c1, Cell* c2) const { return - ( (!c1->inSubdomain() && !c2->inSubdomain()) || (c1->inSubdomain() && c2->inSubdomain()) ); } - - // reduction of this cell complex - // removes reduction pairs of cell of dimension dim and dim-1 - int reduction(int dim, int omitted=0); + + // the domain in the model which this cell complex covers + std::vector<GEntity*> _domain; + // a subdomain of the given domain + // used in relative homology computation, may be empty + std::vector<GEntity*> _subdomain; + + // entities on the boundary of the homology computation domain + std::vector<GEntity*> _boundary; + + // sorted containers of unique cells in this cell complex + // one for each dimension + std::set<Cell*, Less_Cell> _cells[4]; + + // temporary store for omitted cells (generators of the highest dimension) + std::vector< std::set<Cell*, Less_Cell> > _store; + + // original cells of this cell complex + std::set<Cell*, Less_Cell> _ocells[4]; + + // new cells created during reductions + std::vector<Cell*> _newcells; + + // Betti numbers of this cell complex (ranks of homology groups) + int _betti[4]; + + int _dim; + + // is the cell complex simplicial + bool _simplicial; + + // does the domain contain entities of different dimensions + bool _multidim; + + // enqueue cells in queue if they are not there already + void enqueueCells(std::map<Cell*, int, Less_Cell>& cells, + std::queue<Cell*>& Q, std::set<Cell*, Less_Cell>& Qset); + // remove cell from the queue set + void removeCellQset(Cell*& cell, std::set<Cell*, Less_Cell>& Qset); + + // for constructor + void insert_cells(bool subdomain, bool boundary); + void find_boundary(std::vector<GEntity*>& domain, + std::vector<GEntity*>& subdomain); + + // insert/remove a cell from this cell complex + void removeCell(Cell* cell, bool other=true); + void insertCell(Cell* cell); + + // queued coreduction presented in Mrozek's paper + int coreduction(Cell* generator, int omitted=0); + + public: + + CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain ); + //CellComplex(CellComplex* cellComplex) + ~CellComplex(); + + // restore this cell complex to its original state + void restoreComplex(); - // useful functions for (co)reduction of cell complex - int reduceComplex(); - int coreduceComplex(); - - // remove cells in subdomain from this cell complex - void removeSubdomain(); - - // print the vertices of cells of certain dimension - void printComplex(int dim); - - // Cell combining for reduction and coreduction - int combine(int dim); - int cocombine(int dim); - - // Compute betti numbers of this cell complex - void computeBettiNumbers(); - int getBettiNumber(int i) { if(i > -1 && i < 4) return _betti[i]; else return 0; } - - // check whether all boundary cells of a cell has this cell as coboundary cell and vice versa - // also check whether all (co)boundary cells of a cell belong to this cell complex - bool checkCoherence(); - - // make cells on the domain boundary that are not in the subdomain subdomain cells and vice versa - bool swapSubdomain(); - - int eulerCharacteristic(){ return getSize(0) - getSize(1) + getSize(2) - getSize(3);} - void printEuler(){ printf("Euler characteristic: %d. \n", eulerCharacteristic()); } - - int getNumOmitted() { return _store.size(); }; - std::set<Cell*, Less_Cell> getOmitted(int i) { return _store.at(i); } - - // change roles of boundaries and coboundaries of the cells in this cell complex - // equivalent to transposing boundary operator matrices - void makeDualComplex(); + // get the number of certain dimensional cells + int getSize(int dim){ return _cells[dim].size(); } + int getOrgSize(int dim){ return _ocells[dim].size(); } + + int getDim() {return _dim; } + + bool simplicial() { return _simplicial; } + + std::set<Cell*, Less_Cell> getCells(int dim){ return _cells[dim]; } + std::set<Cell*, Less_Cell> getOrgCells(int dim){ return _ocells[dim]; } + + // iterator for the cells of same dimension + typedef std::set<Cell*, Less_Cell>::iterator citer; + + // iterators to the first and last cells of certain dimension + citer firstCell(int dim) {return _cells[dim].begin(); } + citer lastCell(int dim) {return _cells[dim].end(); } + citer firstOrgCell(int dim) {return _ocells[dim].begin(); } + citer lastOrgCell(int dim) {return _ocells[dim].end(); } + + + // true if cell complex has given cell + bool hasCell(Cell* cell, bool org=false); + + // check whether two cells both belong to subdomain or if neither one does + bool inSameDomain(Cell* c1, Cell* c2) const { + return ( (!c1->inSubdomain() && !c2->inSubdomain()) + || (c1->inSubdomain() && c2->inSubdomain()) ); } + + // reduction of this cell complex + // removes reduction pairs of cell of dimension dim and dim-1 + int reduction(int dim, int omitted=0); + + // useful functions for (co)reduction of cell complex + int reduceComplex(); + int coreduceComplex(); + + // remove cells in subdomain from this cell complex + void removeSubdomain(); + + // print the vertices of cells of certain dimension + void printComplex(int dim); + + // Cell combining for reduction and coreduction + int combine(int dim); + int cocombine(int dim); + + // Compute betti numbers of this cell complex + void computeBettiNumbers(); + int getBettiNumber(int i) { + if(i > -1 && i < 4) return _betti[i]; else return 0; } + + // check whether all boundary cells of a cell has this cell + // as coboundary cell and vice versa + // also check whether all (co)boundary cells of a cell + // belong to this cell complex + bool checkCoherence(); + + // make cells on the domain boundary that are not in the subdomain + // subdomain cells and vice versa + bool swapSubdomain(); + + int eulerCharacteristic(){ + return getSize(0) - getSize(1) + getSize(2) - getSize(3);} + void printEuler(){ + printf("Euler characteristic: %d. \n", eulerCharacteristic()); } + + int getNumOmitted() { return _store.size(); }; + std::set<Cell*, Less_Cell> getOmitted(int i) { return _store.at(i); } + + // change roles of boundaries and coboundaries of the cells in this + // cell complex + // equivalent to transposing boundary operator matrices + void makeDualComplex(); }; #endif diff --git a/Geo/ChainComplex.cpp b/Geo/ChainComplex.cpp index cbfd41bb1897c5d54cb0f17563f4473222007dcd..dde548d1dd9d9fc15c22ac5e55763e8c9e017d12 100644 --- a/Geo/ChainComplex.cpp +++ b/Geo/ChainComplex.cpp @@ -71,27 +71,36 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){ _HMatrix[dim] = create_gmp_matrix_zero(rows, cols); //printMatrix(_HMatrix[dim]); - for( std::set<Cell*, Less_Cell>::iterator cit = cellComplex->firstCell(dim); cit != cellComplex->lastCell(dim); cit++){ + for( std::set<Cell*, Less_Cell>::iterator cit = + cellComplex->firstCell(dim); + cit != cellComplex->lastCell(dim); cit++){ Cell* cell = *cit; if(!cell->inSubdomain()){ - std::map<Cell*, int, Less_Cell> bdCell = cell->getOrientedBoundary(); - for(std::map<Cell*, int, Less_Cell>::iterator it = bdCell.begin(); it != bdCell.end(); it++){ + std::map<Cell*, int, Less_Cell> bdCell; + cell->getBoundary(bdCell); + for(std::map<Cell*, int, Less_Cell>::iterator it = bdCell.begin(); + it != bdCell.end(); it++){ Cell* bdCell = (*it).first; if(!bdCell->inSubdomain()){ int old_elem = 0; //printf("cell1: %d, cell2: %d \n", bdCell->getIndex(), cell->getIndex()); - if(bdCell->getIndex() > (int)gmp_matrix_rows( _HMatrix[dim]) || bdCell->getIndex() < 1 - || cell->getIndex() > (int)gmp_matrix_cols( _HMatrix[dim]) || cell->getIndex() < 1){ + if(bdCell->getIndex() > (int)gmp_matrix_rows( _HMatrix[dim]) + || bdCell->getIndex() < 1 + || cell->getIndex() > (int)gmp_matrix_cols( _HMatrix[dim]) + || cell->getIndex() < 1){ Msg::Debug("Warning: Index out of bound! HMatrix: %d. \n", dim); } else{ - gmp_matrix_get_elem(elem, bdCell->getIndex(), cell->getIndex(), _HMatrix[dim]); + gmp_matrix_get_elem(elem, bdCell->getIndex(), + cell->getIndex(), _HMatrix[dim]); old_elem = mpz_get_si(elem); mpz_set_si(elem, old_elem + (*it).second); if( abs((old_elem + (*it).second)) > 1){ - Msg::Debug("Incidence index: %d! HMatrix: %d.", (old_elem + (*it).second), dim); + Msg::Debug("Incidence index: %d! HMatrix: %d.", + (old_elem + (*it).second), dim); } - gmp_matrix_set_elem(elem, bdCell->getIndex(), cell->getIndex(), _HMatrix[dim]); + gmp_matrix_set_elem(elem, bdCell->getIndex(), + cell->getIndex(), _HMatrix[dim]); } } } @@ -415,15 +424,19 @@ int ChainComplex::getTorsion(int dim, int chainNumber){ } -Chain::Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, CellComplex* cellComplex, GModel* model, std::string name, int torsion){ +Chain::Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, + CellComplex* cellComplex, GModel* model, + std::string name, int torsion){ int i = 0; - for(std::set<Cell*, Less_Cell>::iterator cit = cells.begin(); cit != cells.end(); cit++){ + for(std::set<Cell*, Less_Cell>::iterator cit = cells.begin(); + cit != cells.end(); cit++){ Cell* cell = *cit; _dim = cell->getDim(); if(!cell->inSubdomain() && (int)coeffs.size() > i){ if(coeffs.at(i) != 0){ - std::list< std::pair<int, Cell*> > subCells = cell->getCells(); + std::list< std::pair<int, Cell*> > subCells; + cell->getCells(subCells); for(std::list< std::pair<int, Cell*> >::iterator it = subCells.begin(); it != subCells.end(); it++){ Cell* subCell = (*it).second; int coeff = (*it).first; @@ -441,7 +454,8 @@ Chain::Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, CellComp } -bool Chain::deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell*, int, Less_Cell> &cellsNotInChain){ +bool Chain::deform(std::map<Cell*, int, Less_Cell> &cellsInChain, + std::map<Cell*, int, Less_Cell> &cellsNotInChain){ std::vector<int> cc; std::vector<int> bc; @@ -461,7 +475,9 @@ bool Chain::deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell* if(cc[i]*bc[i] != inout) return false; } - for(citer cit = cellsInChain.begin(); cit != cellsInChain.end(); cit++) removeCell((*cit).first); + for(citer cit = cellsInChain.begin(); cit != cellsInChain.end(); cit++){ + removeCell((*cit).first); + } int n = 1; for(citer cit = cellsNotInChain.begin(); cit != cellsNotInChain.end(); cit++){ @@ -479,18 +495,23 @@ bool Chain::deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell* bool Chain::deformChain(std::pair<Cell*, int> cell, bool bend){ Cell* c1 = cell.first; - std::map<Cell*, int, Less_Cell> c1Cbd = c1->getOrgCbd(); + std::map<Cell*, int, Less_Cell> c1Cbd; + c1->getOrgCbd(c1Cbd); for(citer cit = c1Cbd.begin(); cit != c1Cbd.end(); cit++){ std::map<Cell*, int, Less_Cell> cellsInChain; std::map<Cell*, int, Less_Cell> cellsNotInChain; Cell* c1CbdCell = (*cit).first; - std::map<Cell*, int, Less_Cell> c1CbdBd = c1CbdCell->getOrgBd(); + std::map<Cell*, int, Less_Cell> c1CbdBd; + c1CbdCell->getOrgBd(c1CbdBd); for(citer cit2 = c1CbdBd.begin(); cit2 != c1CbdBd.end(); cit2++){ Cell* c1CbdBdCell = (*cit2).first; int coeff = (*cit2).second; - if( (hasCell(c1CbdBdCell) && getCoeff(c1CbdBdCell) != 0) || c1CbdBdCell->inSubdomain()) cellsInChain.insert(std::make_pair(c1CbdBdCell, coeff)); + if( (hasCell(c1CbdBdCell) && getCoeff(c1CbdBdCell) != 0) + || c1CbdBdCell->inSubdomain()){ + cellsInChain.insert(std::make_pair(c1CbdBdCell, coeff)); + } else cellsNotInChain.insert(std::make_pair(c1CbdBdCell, coeff)); } @@ -504,7 +525,8 @@ bool Chain::deformChain(std::pair<Cell*, int> cell, bool bend){ if(coeff > 1 || coeff < -1) next = true; } - for(citer cit2 = cellsNotInChain.begin(); cit2 != cellsNotInChain.end(); cit2++){ + for(citer cit2 = cellsNotInChain.begin(); cit2 != cellsNotInChain.end(); + cit2++){ Cell* c = (*cit2).first; if(c->inSubdomain()) next = true; } @@ -513,18 +535,24 @@ bool Chain::deformChain(std::pair<Cell*, int> cell, bool bend){ //printf("dim: %d, in chain: %d, not in chain: %d \n", getDim(), cellsInChain.size(), cellsNotInChain.size()); - if( (getDim() == 1 && cellsInChain.size() == 2 && cellsNotInChain.size() == 1) || - (getDim() == 2 && cellsInChain.size() == 3 && cellsNotInChain.size() == 1)){ + if( (getDim() == 1 && cellsInChain.size() == 2 + && cellsNotInChain.size() == 1) || + (getDim() == 2 && cellsInChain.size() == 3 + && cellsNotInChain.size() == 1)){ //printf("straighten \n"); return deform(cellsInChain, cellsNotInChain); } - else if ( (getDim() == 1 && cellsInChain.size() == 1 && cellsNotInChain.size() == 2 && bend) || - (getDim() == 2 && cellsInChain.size() == 2 && cellsNotInChain.size() == 2 && bend)){ + else if ( (getDim() == 1 && cellsInChain.size() == 1 + && cellsNotInChain.size() == 2 && bend) || + (getDim() == 2 && cellsInChain.size() == 2 + && cellsNotInChain.size() == 2 && bend)){ //printf("bend \n"); return deform(cellsInChain, cellsNotInChain); } - else if ((getDim() == 1 && cellsInChain.size() == 3 && cellsNotInChain.size() == 0) || - (getDim() == 2 && cellsInChain.size() == 4 && cellsNotInChain.size() == 0)){ + else if ((getDim() == 1 && cellsInChain.size() == 3 + && cellsNotInChain.size() == 0) || + (getDim() == 2 && cellsInChain.size() == 4 + && cellsNotInChain.size() == 0)){ //printf("remove boundary \n"); return deform(cellsInChain, cellsNotInChain); } @@ -652,9 +680,9 @@ void Chain::createPView(){ _model->setPhysicalName(getName(), getDim(), physicalNum); // only for visualization - PView *chain = new PView(getName(), "ElementData", getGModel(), data, 0, 1); + PView* chain = new PView(getName(), "ElementData", getGModel(), data, 0, 1); } - + return; } diff --git a/Geo/ChainComplex.h b/Geo/ChainComplex.h index 3897b6cc824d2737d05e6d88373992e0fdf575e4..5b85d8a1d867c64bbf055297ebaf5d7d88704a10 100644 --- a/Geo/ChainComplex.h +++ b/Geo/ChainComplex.h @@ -32,190 +32,213 @@ extern "C" { // A class representing a chain complex of a cell complex. // This should only be constructed for a reduced cell complex because of -// dense matrix representations and great computational complexity in its methods. +// dense matrix representations and great computational complexity in +// its methods. class ChainComplex{ - private: - // boundary operator matrices for this chain complex - // h_k: C_k -> C_(k-1) - gmp_matrix* _HMatrix[5]; - - // Basis matrices for the kernels and codomains of the boundary operator matrices - gmp_matrix* _kerH[5]; - gmp_matrix* _codH[5]; - - gmp_matrix* _JMatrix[5]; - gmp_matrix* _QMatrix[5]; - std::vector<long int> _torsion[5]; - - // bases for homology groups - gmp_matrix* _Hbasis[5]; - - int _dim; - CellComplex* _cellComplex; - - // set the matrices - void setHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _HMatrix[dim] = matrix;} - void setKerHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _kerH[dim] = matrix;} - void setCodHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _codH[dim] = matrix;} - void setJMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _JMatrix[dim] = matrix;} - void setQMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _QMatrix[dim] = matrix;} - void setHbasis(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _Hbasis[dim] = matrix;} - - - - public: - - ChainComplex(CellComplex* cellComplex); - - ChainComplex(){ - for(int i = 0; i < 5; i++){ - _HMatrix[i] = create_gmp_matrix_zero(1,1); - _kerH[i] = NULL; - _codH[i] = NULL; - _JMatrix[i] = NULL; - _QMatrix[i] = NULL; - _Hbasis[i] = NULL; - } - _dim = 0; - } - ~ChainComplex(){ - for(int i = 0; i < 5; i++){ - destroy_gmp_matrix(_HMatrix[i]); - destroy_gmp_matrix(_kerH[i]); - destroy_gmp_matrix(_codH[i]); - destroy_gmp_matrix(_JMatrix[i]); - destroy_gmp_matrix(_QMatrix[i]); - destroy_gmp_matrix(_Hbasis[i]); - } - } - - int getDim() { return _dim; } - - // get the boundary operator matrix dim->dim-1 - gmp_matrix* getHMatrix(int dim) { if(dim > -1 && dim < 5) return _HMatrix[dim]; else return NULL;} - gmp_matrix* getKerHMatrix(int dim) { if(dim > -1 && dim < 5) return _kerH[dim]; else return NULL;} - gmp_matrix* getCodHMatrix(int dim) { if(dim > -1 && dim < 5) return _codH[dim]; else return NULL;} - gmp_matrix* getJMatrix(int dim) { if(dim > -1 && dim < 5) return _JMatrix[dim]; else return NULL;} - gmp_matrix* getQMatrix(int dim) { if(dim > -1 && dim < 5) return _QMatrix[dim]; else return NULL;} - gmp_matrix* getHbasis(int dim) { if(dim > -1 && dim < 5) return _Hbasis[dim]; else return NULL;} - - // Compute basis for kernel and codomain of boundary operator matrix of dimension dim (ie. ker(h_dim) and cod(h_dim) ) - void KerCod(int dim); - // Compute matrix representation J for inclusion relation from dim-cells who are boundary of dim+1-cells - // to cycles of dim-cells (ie. j: cod(h_(dim+1)) -> ker(h_dim) ) - void Inclusion(int lowDim, int highDim); - // Compute quotient problem for given inclusion relation j to find representatives of homology groups - // and possible torsion coeffcients - void Quotient(int dim); - - // transpose the boundary operator matrices, these are boundary operator matrices for the dual mesh - void transposeHMatrices() { for(int i = 0; i < 5; i++) gmp_matrix_transp(_HMatrix[i]); } - void transposeHMatrix(int dim) { if(dim > -1 && dim < 5) gmp_matrix_transp(_HMatrix[dim]); } - - // Compute bases for the homology groups of this chain complex - void computeHomology(bool dual=false); - - // get coefficient vector for dim-dimensional chain chainNumber (columns of _Hbasis[dim]) - std::vector<int> getCoeffVector(int dim, int chainNumber); - // torsion coefficient for dim-dimensional chain chainNumber - int getTorsion(int dim, int chainNumber); - // get rank of homology group of dimension dim - int getBasisSize(int dim) { if(dim > -1 && dim < 5) return gmp_matrix_cols(_Hbasis[dim]); else return 0; } - - int printMatrix(gmp_matrix* matrix){ - printf("%d rows and %d columns\n", (int)gmp_matrix_rows(matrix), (int)gmp_matrix_cols(matrix)); - return gmp_matrix_printf(matrix); } - - // debugging aid - void matrixTest(); + private: + // boundary operator matrices for this chain complex + // h_k: C_k -> C_(k-1) + gmp_matrix* _HMatrix[5]; + + // Basis matrices for the kernels and codomains of the boundary operator + // matrices + gmp_matrix* _kerH[5]; + gmp_matrix* _codH[5]; + + gmp_matrix* _JMatrix[5]; + gmp_matrix* _QMatrix[5]; + std::vector<long int> _torsion[5]; + + // bases for homology groups + gmp_matrix* _Hbasis[5]; + + int _dim; + CellComplex* _cellComplex; + + // set the matrices + void setHMatrix(int dim, gmp_matrix* matrix) { + if(dim > -1 && dim < 5) _HMatrix[dim] = matrix;} + void setKerHMatrix(int dim, gmp_matrix* matrix) { + if(dim > -1 && dim < 5) _kerH[dim] = matrix;} + void setCodHMatrix(int dim, gmp_matrix* matrix) { + if(dim > -1 && dim < 5) _codH[dim] = matrix;} + void setJMatrix(int dim, gmp_matrix* matrix) { + if(dim > -1 && dim < 5) _JMatrix[dim] = matrix;} + void setQMatrix(int dim, gmp_matrix* matrix) { + if(dim > -1 && dim < 5) _QMatrix[dim] = matrix;} + void setHbasis(int dim, gmp_matrix* matrix) { + if(dim > -1 && dim < 5) _Hbasis[dim] = matrix;} + + public: + + ChainComplex(CellComplex* cellComplex); + + ChainComplex(){ + for(int i = 0; i < 5; i++){ + _HMatrix[i] = create_gmp_matrix_zero(1,1); + _kerH[i] = NULL; + _codH[i] = NULL; + _JMatrix[i] = NULL; + _QMatrix[i] = NULL; + _Hbasis[i] = NULL; + } + _dim = 0; + } + ~ChainComplex(){ + for(int i = 0; i < 5; i++){ + destroy_gmp_matrix(_HMatrix[i]); + destroy_gmp_matrix(_kerH[i]); + destroy_gmp_matrix(_codH[i]); + destroy_gmp_matrix(_JMatrix[i]); + destroy_gmp_matrix(_QMatrix[i]); + destroy_gmp_matrix(_Hbasis[i]); + } + } + + int getDim() { return _dim; } + + // get the boundary operator matrix dim->dim-1 + gmp_matrix* getHMatrix(int dim) { + if(dim > -1 && dim < 5) return _HMatrix[dim]; else return NULL;} + gmp_matrix* getKerHMatrix(int dim) { + if(dim > -1 && dim < 5) return _kerH[dim]; else return NULL;} + gmp_matrix* getCodHMatrix(int dim) { + if(dim > -1 && dim < 5) return _codH[dim]; else return NULL;} + gmp_matrix* getJMatrix(int dim) { + if(dim > -1 && dim < 5) return _JMatrix[dim]; else return NULL;} + gmp_matrix* getQMatrix(int dim) { + if(dim > -1 && dim < 5) return _QMatrix[dim]; else return NULL;} + gmp_matrix* getHbasis(int dim) { + if(dim > -1 && dim < 5) return _Hbasis[dim]; else return NULL;} + + // Compute basis for kernel and codomain of boundary operator matrix + // of dimension dim (ie. ker(h_dim) and cod(h_dim) ) + void KerCod(int dim); + // Compute matrix representation J for inclusion relation from dim-cells + // who are boundary of dim+1-cells to cycles of dim-cells + // (ie. j: cod(h_(dim+1)) -> ker(h_dim) ) + void Inclusion(int lowDim, int highDim); + // Compute quotient problem for given inclusion relation j to find + //representatives of homology groups and possible torsion coeffcients + void Quotient(int dim); + + // transpose the boundary operator matrices, these are boundary operator + // matrices for the dual mesh + void transposeHMatrices() { + for(int i = 0; i < 5; i++) gmp_matrix_transp(_HMatrix[i]); } + void transposeHMatrix(int dim) { + if(dim > -1 && dim < 5) gmp_matrix_transp(_HMatrix[dim]); } + + // Compute bases for the homology groups of this chain complex + void computeHomology(bool dual=false); + + // get coefficient vector for dim-dimensional chain chainNumber + // (columns of _Hbasis[dim]) + std::vector<int> getCoeffVector(int dim, int chainNumber); + // torsion coefficient for dim-dimensional chain chainNumber + int getTorsion(int dim, int chainNumber); + // get rank of homology group of dimension dim + int getBasisSize(int dim) { + if(dim > -1 && dim < 5) return gmp_matrix_cols(_Hbasis[dim]); + else return 0; } + + int printMatrix(gmp_matrix* matrix){ + printf("%d rows and %d columns\n", + (int)gmp_matrix_rows(matrix), (int)gmp_matrix_cols(matrix)); + return gmp_matrix_printf(matrix); } + + // debugging aid + void matrixTest(); }; // A class representing a chain. // Used to visualize generators of the homology groups. class Chain{ - - private: - // cells and their coefficients in this chain - std::map< Cell*, int, Less_Cell > _cells; - // name of the chain (optional) - std::string _name; - // physical group number of the chain - int _num; - // cell complex this chain belongs to - CellComplex* _cellComplex; - GModel* _model; - - // torsion coefficient - int _torsion; - - int _dim; - - - bool deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell*, int, Less_Cell> &cellsNotInChain); - bool deformChain(std::pair<Cell*, int> cell, bool bend); - - - public: - Chain(){} - Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, CellComplex* cellComplex, GModel* model, - std::string name="Chain", int torsion=0); - Chain(Chain* chain){ - _cells = chain->getCells(); - _torsion = chain->getTorsion(); - _name = chain->getName(); - _cellComplex = chain->getCellComplex(); - _dim = chain->getDim(); - _model = chain->getGModel(); - } - ~Chain(){} - - typedef std::map<Cell*, int, Less_Cell>::iterator citer; - - // remove a cell from this chain - void removeCell(Cell* cell); - - // add a cell to this chain - void addCell(Cell* cell, int coeff); + + private: + // cells and their coefficients in this chain + std::map< Cell*, int, Less_Cell > _cells; + // name of the chain (optional) + std::string _name; + // physical group number of the chain + int _num; + // cell complex this chain belongs to + CellComplex* _cellComplex; + GModel* _model; + + // torsion coefficient + int _torsion; + + int _dim; + + bool deform(std::map<Cell*, int, Less_Cell> &cellsInChain, + std::map<Cell*, int, Less_Cell> &cellsNotInChain); + bool deformChain(std::pair<Cell*, int> cell, bool bend); + + + public: + Chain(){} + Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, + CellComplex* cellComplex, GModel* model, + std::string name="Chain", int torsion=0); + Chain(Chain* chain){ + _cells = chain->getCells(); + _torsion = chain->getTorsion(); + _name = chain->getName(); + _cellComplex = chain->getCellComplex(); + _dim = chain->getDim(); + _model = chain->getGModel(); + } + ~Chain(){} + + typedef std::map<Cell*, int, Less_Cell>::iterator citer; + + // remove a cell from this chain + void removeCell(Cell* cell); + + // add a cell to this chain + void addCell(Cell* cell, int coeff); + + bool hasCell(Cell* c); + Cell* findCell(Cell* c); + int getCoeff(Cell* c); + + + int getTorsion() {return _torsion;} + int getDim() {return _dim;} + CellComplex* getCellComplex() {return _cellComplex;} + GModel* getGModel() {return _model;} + std::map<Cell*, int, Less_Cell> getCells() {return _cells;} + + // erase cells from the chain with zero coefficient + void eraseNullCells(); + + void deImmuneCells(); + + // number of cells in this chain + int getSize() { return _cells.size();} + + // get/set chain name + std::string getName() { return _name; } + void setName(std::string name) { _name=name; } + // get/set physical group number + int getNum() { return _num; } + void setNum(int num) { _num=num; } + + // make local deformations to the chain to make it smoother and smaller + // (for primary complex chains only, not for dual chains represented + // by primary cells (yet).) + void smoothenChain(); + + // append this chain to a MSH ASCII file as $ElementData + // for debugging only + int writeChainMSH(const std::string &name); - bool hasCell(Cell* c); - Cell* findCell(Cell* c); - int getCoeff(Cell* c); - - - int getTorsion() {return _torsion;} - int getDim() {return _dim;} - CellComplex* getCellComplex() {return _cellComplex;} - GModel* getGModel() {return _model;} - std::map<Cell*, int, Less_Cell> getCells() {return _cells;} - - // erase cells from the chain with zero coefficient - void eraseNullCells(); - - void deImmuneCells(); - - // number of cells in this chain - int getSize() { return _cells.size();} - - // get/set chain name - std::string getName() { return _name; } - void setName(std::string name) { _name=name; } - // get/set physical group number - int getNum() { return _num; } - void setNum(int num) { _num=num; } - - // make local deformations to the chain to make it smoother and smaller - // (for primary complex chains only, not for dual chains represented by primary cells (yet).) - void smoothenChain(); - - // append this chain to a MSH ASCII file as $ElementData - // for debugging only - int writeChainMSH(const std::string &name); - - // create a PView of this chain. - void createPView(); - + // create a PView of this chain. + void createPView(); + }; - + #endif #endif diff --git a/Geo/Homology.cpp b/Geo/Homology.cpp index 1a5344f3ea95c33466c064feb59943c8873bf325..7736b9ee8ce0751a21db3a37e36df46aa4372f82 100644 --- a/Geo/Homology.cpp +++ b/Geo/Homology.cpp @@ -74,16 +74,16 @@ Homology::Homology(GModel* model, std::vector<int> physicalDomain, std::vector<i _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0)); } - Homology::~Homology(){ - delete _cellComplex; - for(int i = 0; i < 4; i++) { - for(int j = 0; j < _generators[i].size(); j++){ - Chain* chain = _generators[i].at(j); - //_model->deletePhysicalGroup(chain->getDim(), chain->getNum()); - delete chain; - } - } - } +Homology::~Homology(){ + delete _cellComplex; + for(int i = 0; i < 4; i++) { + for(int j = 0; j < _generators[i].size(); j++){ + Chain* chain = _generators[i].at(j); + //_model->deletePhysicalGroup(chain->getDim(), chain->getNum()); + delete chain; + } + } +} void Homology::findGenerators(std::string fileName){ diff --git a/Geo/Homology.h b/Geo/Homology.h index 0443ba40fdcf4f486572dc36440350953100b8b0..07e1bcd8428301452681a31120b3f8280a4c3613 100644 --- a/Geo/Homology.h +++ b/Geo/Homology.h @@ -15,52 +15,55 @@ #if defined(HAVE_KBIPACK) template <class TTypeA, class TTypeB> -bool convert(const TTypeA& input, TTypeB& output ){ - std::stringstream stream; - stream << input; - stream >> output; - return stream.good(); + bool convert(const TTypeA& input, TTypeB& output ){ + std::stringstream stream; + stream << input; + stream >> output; + return stream.good(); } class Homology { - private: - - // base cell complex and the model of the homology computation - CellComplex* _cellComplex; - GModel* _model; - - // domain and the relative subdomain of the homology computation - std::vector<int> _domain; - std::vector<int> _subdomain; + private: + + // base cell complex and the model of the homology computation + CellComplex* _cellComplex; + GModel* _model; - // generator chains - std::vector<Chain*> _generators[4]; - - public: - - Homology(GModel* model, std::vector<int> physicalDomain, std::vector<int> physicalSubdomain); - ~Homology(); - - // Find the generators/duals of homology spaces, or just compute the ranks of homology spaces - void findGenerators(std::string fileName); - void findDualGenerators(std::string fileName); - void computeBettiNumbers(); - - bool swapSubdomain() { return _cellComplex->swapSubdomain(); } - - // Restore the cell complex to its original state before cell reductions - void restoreHomology(); - - // Create a string describing the generator - std::string getDomainString(); + // domain and the relative subdomain of the homology computation + std::vector<int> _domain; + std::vector<int> _subdomain; + + // generator chains + std::vector<Chain*> _generators[4]; - // create PViews of the generators and save the chain mesh elements to the mesh of the model - void createPViews(); - // write the generators to a file - bool writeGeneratorsMSH(std::string fileName, bool binary=false); + public: + + Homology(GModel* model, std::vector<int> physicalDomain, + std::vector<int> physicalSubdomain); + ~Homology(); + + // Find the generators/duals of homology spaces, + // or just compute the ranks of homology spaces + void findGenerators(std::string fileName); + void findDualGenerators(std::string fileName); + void computeBettiNumbers(); + + bool swapSubdomain() { return _cellComplex->swapSubdomain(); } + + // Restore the cell complex to its original state before cell reductions + void restoreHomology(); + // Create a string describing the generator + std::string getDomainString(); + + // create PViews of the generators and save the chain mesh elements + // to the mesh of the model + void createPViews(); + // write the generators to a file + bool writeGeneratorsMSH(std::string fileName, bool binary=false); + }; #endif diff --git a/utils/api_demos/mainHomology.cpp b/utils/api_demos/mainHomology.cpp index acf2812edc22ede0319feb38dbe26fd36df83e89..cba560a26e69485ebc62ed51518f14738f788c5a 100644 --- a/utils/api_demos/mainHomology.cpp +++ b/utils/api_demos/mainHomology.cpp @@ -29,19 +29,19 @@ int main(int argc, char **argv) std::vector<int> domain; std::vector<int> subdomain; - Homology* homology = new Homology(m, domain, subdomain); - std::string fileName = "homology_generators.msh"; + Homology* homology1 = new Homology(m, domain, subdomain); + std::string fileName = "homology.msh"; homology->findGenerators(fileName); - homology->restoreHomology(); + delete homology1; - Homology* homology = new Homology(m, domain, subdomain); - fileName = "homology_dualgenerators.msh"; + Homology* homology2 = new Homology(m, domain, subdomain); + fileName = "homology.msh"; homology->findDualGenerators(fileName); - homology->restoreHomology(); + delete homology2; - Homology* homology = new Homology(m, domain, subdomain); + Homology* homology3 = new Homology(m, domain, subdomain); homology->computeBettiNumbers(); - delete homology; + delete homology3; delete m; GmshFinalize();