From 61a9dafb349ae154ec5c22d474ea4ea2c6e843ca Mon Sep 17 00:00:00 2001 From: Matti Pellika <matti.pellikka@tut.fi> Date: Fri, 15 Jan 2010 11:12:55 +0000 Subject: [PATCH] Code cleanup, increased verbosity. --- Geo/CMakeLists.txt | 2 +- Geo/CellComplex.cpp | 252 +++++++++++------------- Geo/CellComplex.h | 447 +++++-------------------------------------- Geo/ChainComplex.cpp | 79 +++++++- Geo/ChainComplex.h | 80 +------- Geo/Homology.cpp | 124 ++++++++++-- Geo/Homology.h | 73 +------ tutorial/t10.geo | 5 +- 8 files changed, 354 insertions(+), 708 deletions(-) diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt index 89e0c22ee7..a004d0e60a 100644 --- a/Geo/CMakeLists.txt +++ b/Geo/CMakeLists.txt @@ -31,7 +31,7 @@ set(SRC MLine.cpp MTriangle.cpp MQuadrangle.cpp MTetrahedron.cpp MHexahedron.cpp MPrism.cpp MPyramid.cpp MElementCut.cpp MZone.cpp MZoneBoundary.cpp - CellComplex.cpp ChainComplex.cpp Homology.cpp + Cell.cpp CellComplex.cpp ChainComplex.cpp Homology.cpp ) file(GLOB HDR RELATIVE ${CMAKE_SOURCE_DIR}/Geo *.h) diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp index 7162aefca0..6e67fe2e6a 100644 --- a/Geo/CellComplex.cpp +++ b/Geo/CellComplex.cpp @@ -18,7 +18,7 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su _dim = 0; _simplicial = true; - // find boundary elements + // find boundary entities find_boundary(domain, subdomain); // insert cells into cell complex @@ -182,7 +182,7 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){ cell = new CPyramid(vertices, tag, subdomain, boundary); _simplicial = false; }*/ - else printf("Error: mesh element %d not implemented yet! \n", type); + else Msg::Error("Error: mesh element %d not implemented yet! \n", type); tag++; //if(domain.at(j)->getMeshElement(i)->getNum() == 8196) cell->setImmune(true); //else @@ -203,7 +203,7 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){ if(dim == 3){ if(vertices.size() == 3) newCell = new TwoSimplex(vertices, tag, subdomain, boundary); else if(vertices.size() == 4) newCell = new CQuadrangle(vertices, tag, subdomain, boundary); - else printf("Error: invalid face! \n"); + else Msg::Debug("Error: invalid face! \n"); } else if(dim == 2) newCell = new OneSimplex(vertices, tag, subdomain, boundary); else if(dim == 1) newCell = new ZeroSimplex(vertices, tag, subdomain, boundary); @@ -236,98 +236,54 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){ } +CellComplex::~CellComplex(){ + for(int i = 0; i < 4; i++){ + _cells[i].clear(); + + for(citer cit = _ocells[i].begin(); cit != _ocells[i].end(); cit++){ + Cell* cell = *cit; + delete cell; + } + _ocells[i].clear(); + + } + //emptyTrash(); + } + + /* + 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(); + } + */ + void CellComplex::insertCell(Cell* cell){ _ecells.insert(cell); } -/* -int Simplex::kappa(Cell* tau) const{ - for(int i=0; i < tau->getNumVertices(); i++){ - if( !(this->hasVertex(tau->getVertex(i)->getNum())) ) return 0; - } - - if(this->getDim() - tau->getDim() != 1) return 0; - - int value=1; - for(int i=0; i < tau->getNumVertices(); i++){ - if(this->getSortedVertex(i) != tau->getSortedVertex(i)) return value; - value = value*-1; - } - - return value; -} -*/ -/* -int Cell::kappa(Cell* tau) const{ - for(int i=0; i < tau->getNumVertices(); i++){ - if( !(this->hasVertex(tau->getVertex(i)->getNum())) ) return 0; - } - - if(this->getDim() - tau->getDim() != 1) return 0; - - int value=1; - - for(int i = 0; i < this->getNumFacets(); i++){ - std::vector<MVertex*> vTau = tau->getVertexVector(); - std::vector<MVertex*> v; - this->getFacetVertices(i, v); - value = -1; - - if(v.size() != vTau.size()) printf("Error: invalid facet!"); - - do { - value = value*-1; - if(v == vTau) return value; - } - while (std::next_permutation(vTau.begin(), vTau.end()) ); - - vTau = tau->getVertexVector(); - value = -1; - do { - value = value*-1; - if(v == vTau) return value; - } - while (std::prev_permutation(vTau.begin(), vTau.end()) ); - - - } - - return 0; -} - - -int OneSimplex::kappa(Cell* tau) const{ - - for(int i=0; i < tau->getNumVertices(); i++){ - if( !(this->hasVertex(tau->getVertex(i)->getNum())) ) return 0; - } - - if(tau->getDim() != 0) return 0; - - if(tau->getVertex(0) == this->getVertex(0)) return -1; - else return 1; - -}*/ - 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::list<Cell*> boundary = cell->getBoundary(); - //std::list<Cell*> coboundary = cell->getCoboundary(); for(std::map<Cell*, int, Less_Cell>::iterator it = coboundary.begin(); it != coboundary.end(); it++){ - //for(std::list<Cell*>::iterator it = coboundary.begin(); it != coboundary.end(); it++){ Cell* cbdCell = (*it).first; - //Cell* cbdCell = *it; cbdCell->removeBoundaryCell(cell, other); - } - + } for(std::map<Cell*, int, Less_Cell>::iterator it = boundary.begin(); it != boundary.end(); it++){ - //for(std::list<Cell*>::iterator it = boundary.begin(); it != boundary.end(); it++){ Cell* bdCell = (*it).first; - //Cell* bdCell = *it; bdCell->removeCoboundaryCell(cell, other); } @@ -527,7 +483,7 @@ int CellComplex::reduceComplex(){ double t1 = Cpu(); - printf("Cell complex before reduction: %d volumes, %d faces, %d edges and %d vertices.\n", + Msg::Debug("Cell complex before reduction: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); int count = 0; @@ -535,23 +491,15 @@ int CellComplex::reduceComplex(){ int omitted = 0; _store.clear(); - //if(omit > getDim()) omit = getDim(); - - CellComplex::removeSubdomain(); - //std::set<Cell*, Less_Cell> generatorCells; + removeSubdomain(); while (getSize(getDim()) != 0){ citer cit = firstCell(getDim()); - Cell* cell = *cit; - //generatorCells.insert(cell); removeCell(cell); - //makeDualComplex(); - //coreduction(cell); - //makeDualComplex(); omitted++; std::set< Cell*, Less_Cell > omittedCells; _store.push_back(omittedCells); @@ -561,17 +509,9 @@ int CellComplex::reduceComplex(){ } - /* - for(citer cit = generatorCells.begin(); cit != generatorCells.end(); cit++){ - Cell* cell = *cit; - cell->clearBoundary(); - cell->clearCoboundary(); - _cells[cell->getDim()].insert(cell); - }*/ - double t2 = Cpu(); - printf("Cell complex after reduction: %d volumes, %d faces, %d edges and %d vertices (%g s).\n", + Msg::Debug("Cell complex after reduction: %d volumes, %d faces, %d edges and %d vertices (%g s).\n", getSize(3), getSize(2), getSize(1), getSize(0), t2 - t1); /* @@ -611,7 +551,7 @@ void CellComplex::removeSubdomain(){ int CellComplex::coreduceComplex(){ - printf("Cell complex before coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", + Msg::Debug("Cell complex before coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); int count = 0; @@ -631,18 +571,18 @@ int CellComplex::coreduceComplex(){ int omitted = 0; _store.clear(); - //std::set<Cell*, Less_Cell> generatorCells; while (getSize(0) != 0){ citer cit = firstCell(0); Cell* cell = *cit; - //generatorCells.insert(cell); + removeCell(cell, false); std::set< Cell*, Less_Cell > omittedCells; omitted++; _store.push_back(omittedCells); _store.at(omitted-1).insert(cell); coreduction(cell, omitted); - } + } + /* for(citer cit = generatorCells.begin(); cit != generatorCells.end(); cit++){ Cell* cell = *cit; @@ -653,7 +593,7 @@ int CellComplex::coreduceComplex(){ */ - printf("Cell complex after coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", + Msg::Debug("Cell complex after coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); return omitted; @@ -663,7 +603,7 @@ void CellComplex::computeBettiNumbers(){ for(int i = 0; i < 4; i++){ _betti[i] = 0; - printf("Betti number computation process: step %d of 4 \n", i+1); + Msg::Debug("Betti number computation process: step %d of 4 \n", i+1); while (getSize(i) != 0){ citer cit = firstCell(i); @@ -677,7 +617,7 @@ void CellComplex::computeBettiNumbers(){ coreduction(cell); } } - printf("Cell complex Betti numbers: \nH0 = %d \nH1 = %d \nH2 = %d \nH3 = %d \n", + Msg::Debug("Cell complex Betti numbers: \nH0 = %d \nH1 = %d \nH2 = %d \nH3 = %d \n", getBettiNumber(0), getBettiNumber(1), getBettiNumber(2), getBettiNumber(3)); return; @@ -687,7 +627,7 @@ void CellComplex::computeBettiNumbers(){ int CellComplex::cocombine(int dim){ double t1 = Cpu(); - printf("Cell complex before cocombining: %d volumes, %d faces, %d edges and %d vertices.\n", + Msg::Debug("Cell complex before cocombining: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); if(dim < 0 || dim > 2) return 0; @@ -735,7 +675,7 @@ int CellComplex::cocombine(int dim){ removeCell(c1); removeCell(c2); std::pair<citer, bool> insertInfo = _cells[dim].insert(newCell); - if(!insertInfo.second) printf("Warning: Combined cell not inserted! \n"); + if(!insertInfo.second) Msg::Debug("Warning: Combined cell not inserted! \n"); cit = firstCell(dim); count++; @@ -746,7 +686,7 @@ int CellComplex::cocombine(int dim){ } } double t2 = Cpu(); - printf("Cell complex after cocombining: %d volumes, %d faces, %d edges and %d vertices (%g s).\n", + Msg::Debug("Cell complex after cocombining: %d volumes, %d faces, %d edges and %d vertices (%g s).\n", getSize(3), getSize(2), getSize(1), getSize(0), t2-t1); return count; @@ -754,7 +694,7 @@ int CellComplex::cocombine(int dim){ int CellComplex::combine(int dim){ double t1 = Cpu(); - printf("Cell complex before combining: %d volumes, %d faces, %d edges and %d vertices.\n", + Msg::Debug("Cell complex before combining: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); if(dim < 1 || dim > 3) return 0; @@ -802,7 +742,7 @@ int CellComplex::combine(int dim){ removeCell(c1); removeCell(c2); std::pair<citer, bool> insertInfo = _cells[dim].insert(newCell); - if(!insertInfo.second) printf("Warning: Combined cell not inserted! \n"); + if(!insertInfo.second) Msg::Debug("Warning: Combined cell not inserted! \n"); cit = firstCell(dim); count++; } @@ -812,7 +752,7 @@ int CellComplex::combine(int dim){ } } double t2 = Cpu(); - printf("Cell complex after combining: %d volumes, %d faces, %d edges and %d vertices (%g s).\n", + Msg::Debug("Cell complex after combining: %d volumes, %d faces, %d edges and %d vertices (%g s).\n", getSize(3), getSize(2), getSize(1), getSize(0), t2 - t1); @@ -820,7 +760,7 @@ int CellComplex::combine(int dim){ } /* -int CellComplex::combine(int dim){ +int CellComplex::combine(int dim){ // version of combine that doesn't have a queue double t1 = Cpu(); printf("Cell complex before combining: %d volumes, %d faces, %d edges and %d vertices.\n", getSize(3), getSize(2), getSize(1), getSize(0)); @@ -900,22 +840,17 @@ void CellComplex::swapSubdomain(){ int CellComplex::writeComplexMSH(const std::string &name){ - FILE *fp = fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); - printf("Unable to open file."); + Msg::Debug("Unable to open file."); return 0; - } - - + } fprintf(fp, "$MeshFormat\n2.1 0 8\n$EndMeshFormat\n"); - fprintf(fp, "$Nodes\n"); - fprintf(fp, "%d\n", (int)_domainVertices.size()); for(std::set<MVertex*, Less_MVertex>::iterator vit = _domainVertices.begin(); vit != _domainVertices.end(); vit++){ @@ -1073,14 +1008,14 @@ bool CellComplex::checkCoherence(){ int ori = (*it).second; citer cit = _cells[bdCell->getDim()].find(bdCell); if(cit == lastCell(bdCell->getDim())){ - printf("Warning! Boundary cell not in cell complex! Boundary removed. \n"); + Msg::Debug("Warning! Boundary cell not in cell complex! Boundary removed. \n"); //printf(" "); cell->printCell(); //printf(" "); bdCell->printCell(); cell->removeBoundaryCell(bdCell); coherent = false; } if(!bdCell->hasCoboundary(cell)){ - printf("Warning! Incoherent boundary/coboundary pair! Fixed. \n"); + Msg::Debug("Warning! Incoherent boundary/coboundary pair! Fixed. \n"); //printf(" "); cell->printCell(); //printf(" "); cell->printBoundary(); //printf(" "); bdCell->printCell(); @@ -1096,14 +1031,14 @@ bool CellComplex::checkCoherence(){ int ori = (*it).second; citer cit = _cells[cbdCell->getDim()].find(cbdCell); if(cit == lastCell(cbdCell->getDim())){ - printf("Warning! Coboundary cell not in cell complex! Coboundary removed. \n"); + Msg::Debug("Warning! Coboundary cell not in cell complex! Coboundary removed. \n"); //printf(" "); cell->printCell(); //printf(" "); cbdCell->printCell(); cell->removeCoboundaryCell(cbdCell); coherent = false; } if(!cbdCell->hasBoundary(cell)){ - printf("Warning! Incoherent coboundary/boundary pair! Fixed. \n"); + Msg::Debug("Warning! Incoherent coboundary/boundary pair! Fixed. \n"); //printf(" "); cell->printCell(); //printf(" "); cell->printCoboundary(); //printf(" "); cbdCell->printCell(); @@ -1119,24 +1054,55 @@ bool CellComplex::checkCoherence(){ return coherent; } + void CellComplex::emptyTrash(){ + for(std::list<Cell*>::iterator cit = _trash.begin(); cit != _trash.end(); cit++){ + Cell* cell = *cit; + delete cell; + } + _trash.clear(); + } + + void CellComplex::restoreComplex(){ + for(int i = 0; i < 4; i++){ + _betti[i] = 0; + _cells[i] = _ocells[i]; + for(citer cit = firstCell(i); cit != lastCell(i); cit++){ + Cell* cell = *cit; + cell->restoreCell(); + } + } + _store.clear(); + _ecells.clear(); + _trash.clear(); + } + + bool CellComplex::hasCell(Cell* cell, bool org){ + if(!org){ + citer cit = _cells[cell->getDim()].find(cell); + if( cit == lastCell(cell->getDim()) ) return false; + else return true; + } + else{ + citer cit = _ocells[cell->getDim()].find(cell); + if( cit == lastOrgCell(cell->getDim()) ) return false; + else return true; + } + } + + void CellComplex::makeDualComplex(){ + std::set<Cell*, Less_Cell> temp = _cells[0]; + _cells[0] = _cells[3]; + _cells[3] = temp; + temp = _cells[1]; + _cells[1] = _cells[2]; + _cells[2] = temp; + + for(int i = 0; i < 4; i++){ + for(citer cit = firstCell(i); cit != lastCell(i); cit++){ + Cell* cell = *cit; + cell->makeDualCell(); + } + } + } -bool Less_Cell::operator()(const Cell* c1, const Cell* c2) const { - - //cells with fever vertices first - - if(c1->getNumVertices() != c2->getNumVertices()){ - return (c1->getNumVertices() < c2->getNumVertices()); - } - - - - //"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; - else if (c1->getSortedVertex(i) > c2->getSortedVertex(i)) return false; - } - - return false; -} #endif diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h index 92ac46b194..3ae5943c43 100644 --- a/Geo/CellComplex.h +++ b/Geo/CellComplex.h @@ -109,16 +109,7 @@ class Cell virtual std::vector<MVertex*> getVertexVector() const = 0; // restores the cell information to its original state before reduction - virtual void restoreCell(){ - _boundary = _obd; - _coboundary = _ocbd; - _bdSize = _boundary.size(); - _cbdSize = _coboundary.size(); - _combined = false; - _index = 0; - _immune = false; - - } + virtual void restoreCell(); // true if this cell has given vertex virtual bool hasVertex(int vertex) const = 0; @@ -126,165 +117,43 @@ class Cell // (co)boundary cell iterator typedef std::map<Cell*, int, Less_Cell>::iterator biter; - //virtual int getBoundarySize() { return _bdSize; } - //virtual int getCoboundarySize() { return _cbdSize; } 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() { - std::list<Cell*> boundary; - for( biter it= _boundary.begin(); it != _boundary.end();it++){ - Cell* cell = (*it).first; - boundary.push_back(cell); - } - return boundary; - } + virtual std::list< Cell* > getBoundary(); virtual std::map<Cell*, int, Less_Cell > getOrientedCoboundary() { return _coboundary; } - virtual std::list< 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; - } - - virtual bool addBoundaryCell(int orientation, Cell* cell) { - _bdSize++; - biter it = _boundary.find(cell); - if(it != _boundary.end()){ - (*it).second = (*it).second + orientation; - if((*it).second == 0) { - _boundary.erase(it); _bdSize--; - (*it).first->removeCoboundaryCell(this,false); - return false; - } - return true; - } - _boundary.insert( std::make_pair(cell, orientation ) ); - return true; - } - - virtual bool addCoboundaryCell(int orientation, Cell* cell) { - _cbdSize++; - biter it = _coboundary.find(cell); - if(it != _coboundary.end()){ - (*it).second = (*it).second + orientation; - if((*it).second == 0) { - _coboundary.erase(it); _cbdSize--; - (*it).first->removeBoundaryCell(this,false); - return false; - } - return true; - } - _coboundary.insert( std::make_pair(cell, orientation ) ); - return true; - } - - virtual int removeBoundaryCell(Cell* cell, bool other=true) { - biter it = _boundary.find(cell); - if(it != _boundary.end()){ - _boundary.erase(it); - if(other) (*it).first->removeCoboundaryCell(this, false); - _bdSize--; - return (*it).second; - } - - return 0; - } + virtual std::list< Cell* > getCoboundary(); + // add (co)boundary cell + virtual bool addBoundaryCell(int orientation, Cell* cell); + virtual bool addCoboundaryCell(int orientation, Cell* cell); - virtual int removeCoboundaryCell(Cell* cell, bool other=true) { - biter it = _coboundary.find(cell); - if(it != _coboundary.end()){ - _coboundary.erase(it); - if(other) (*it).first->removeBoundaryCell(this, false); - _cbdSize--; - return (*it).second; - } - return 0; - } - - // true if has given cell on (original) boundary - virtual bool hasBoundary(Cell* cell, bool org=false){ - if(!org){ - biter it = _boundary.find(cell); - if(it != _boundary.end()) return true; - return false; - } - else{ - biter it = _obd.find(cell); - if(it != _obd.end()) return true; - return false; - } - } - - // true if has given cell on (original) boundary - virtual bool hasCoboundary(Cell* cell, bool org=false){ - if(!org){ - biter it = _coboundary.find(cell); - if(it != _coboundary.end()) return true; - return false; - } - else{ - biter it = _ocbd.find(cell); - if(it != _ocbd.end()) return true; - return false; - } - } + // 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(){ - std::map<Cell*, int, Less_Cell > temp = _boundary; - _boundary = _coboundary; - _coboundary = temp; - _dim = 3-_dim; - - } + virtual void makeDualCell(); - virtual void printBoundary() { - for(biter it = _boundary.begin(); it != _boundary.end(); it++){ - printf("Boundary cell orientation: %d ", (*it).second); - Cell* cell2 = (*it).first; - cell2->printCell(); - } - if(_boundary.empty()) printf("Cell boundary is empty. \n"); - } - virtual void printCoboundary() { - for(biter it = _coboundary.begin(); it != _coboundary.end(); it++){ - printf("Coboundary cell orientation: %d, ", (*it).second); - Cell* cell2 = (*it).first; - cell2->printCell(); - if(_coboundary.empty()) printf("Cell coboundary is empty. \n"); - } - } + 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() { - for(biter it = _obd.begin(); it != _obd.end(); it++){ - printf("Boundary cell orientation: %d ", (*it).second); - Cell* cell2 = (*it).first; - cell2->printCell(); - } - if(_obd.empty()) printf("Cell boundary is empty. \n"); - } - virtual void printOrgCbd() { - for(biter it = _ocbd.begin(); it != _ocbd.end(); it++){ - printf("Coboundary cell orientation: %d, ", (*it).second); - Cell* cell2 = (*it).first; - cell2->printCell(); - if(_ocbd.empty()) printf("Cell coboundary is empty. \n"); - } - } - + virtual void printOrgBd(); + virtual void printOrgCbd(); virtual bool inSubdomain() const { return _inSubdomain; } //virtual void setInSubdomain(bool subdomain) { _inSubdomain = subdomain; } @@ -297,15 +166,16 @@ class Cell virtual int getNumFacets() const { return 0; } virtual void getFacetVertices(const int num, std::vector<MVertex*> &v) const {}; + // get boundary cell orientation virtual int getFacetOri(Cell* cell) { std::vector<MVertex*> v = cell->getVertexVector(); return getFacetOri(v); } virtual int getFacetOri(std::vector<MVertex*> &v) { return 0; } + // 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;} - - + bool operator==(const Cell& c2){ if(this->getNumVertices() != c2.getNumVertices()){ return false; @@ -330,21 +200,16 @@ class Cell return false; } - // checks whether lower dimensional simplex tau is on the boundary of this cell - //virtual int kappa(Cell* tau) const; - - virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, int num=0, int elementary=1, int physical=1, int parentNum=0) {} + //virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, int num=0, int elementary=1, int physical=1, int parentNum=0) {} }; // Simplicial cell type. class Simplex : public Cell -{ - +{ public: Simplex() : Cell() {} - ~Simplex(){} - + ~Simplex(){} }; // Zero simplex cell type. @@ -385,9 +250,7 @@ class OneSimplex : public Simplex, public MLine private: // sorted list of vertices int _vs[2]; - public: - - + public: OneSimplex(std::vector<MVertex*> v, int tag=0, bool subdomain=false, bool boundary=false, int num=0, int part=0) : MLine(v, num, part){ _tag = tag; @@ -427,8 +290,6 @@ class OneSimplex : public Simplex, public MLine else if(v[0] == _v[1]) return 1; else return 0; } - - //int kappa(Cell* tau) const; void printCell() const { printf("Cell dimension: %d, Vertices: %d %d, in subdomain: %d \n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _inSubdomain); } @@ -798,105 +659,8 @@ class CombinedCell : public Cell{ public: - CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co=false) : Cell(){ - - // use "smaller" cell as c2 - if(c1->getNumVertices() < c2->getNumVertices()){ - Cell* temp = c1; - c1 = c2; - c2 = temp; - } - - _index = c1->getIndex(); - _tag = c1->getTag(); - _dim = c1->getDim(); - _num = c1->getNum(); - _inSubdomain = c1->inSubdomain(); - _onDomainBoundary = c1->onDomainBoundary(); - _combined = true; - - _v.reserve(c1->getNumVertices() + c2->getNumVertices()); - _vs.reserve(c1->getNumVertices() + c2->getNumVertices()); - - - _v = c1->getVertexVector(); - for(int i = 0; i < c2->getNumVertices(); 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()); - 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++){ - 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(); - - 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++){ - Cell* cell = (*it).first; - if(!orMatch) (*it).second = -1*(*it).second; - int ori = (*it).second; - cell->removeCoboundaryCell(c2); - if(co){ - 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); } - } - else{ - if(this->addBoundaryCell(ori, cell)) cell->addCoboundaryCell(ori, this); - } - } - - // coboundary cells - std::map<Cell*, int, Less_Cell > c1Coboundary = c1->getOrientedCoboundary(); - std::map<Cell*, int, Less_Cell > c2Coboundary = c2->getOrientedCoboundary(); - - 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++){ - Cell* cell = (*it).first; - if(!orMatch) (*it).second = -1*(*it).second; - int ori = (*it).second; - cell->removeBoundaryCell(c2); - if(!co){ - 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); } - } - else { - if(this->addCoboundaryCell(ori, cell)) cell->addBoundaryCell(ori, this); - } - } - - } - - ~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; - } - } + CombinedCell(Cell* c1, Cell* c2, bool orMatch, bool co=false); + ~CombinedCell(); int getNum() { return _num; } int getNumVertices() const { return _v.size(); } @@ -904,27 +668,10 @@ class CombinedCell : public Cell{ int getSortedVertex(int vertex) const { return _vs.at(vertex); } std::vector<MVertex*> getVertexVector() const { return _v; } - //int kappa(Cell* tau) const { return 0; } - // true if this cell has given vertex - bool hasVertex(int vertex) const { - //std::vector<int>::iterator it = std::find(_vs.begin(), _vs.end(), vertex); - //if (it == _vs.end()) return false; - //else return true; - for(unsigned int i = 0; i < _v.size(); i++){ - if(_v.at(i)->getNum() == vertex) return true; - } - return false; - } + bool hasVertex(int vertex) const; - virtual void printCell() const { - printf("Cell dimension: %d, ", getDim() ); - printf("Vertices: "); - for(int i = 0; i < this->getNumVertices(); i++){ - printf("%d ", this->getSortedVertex(i)); - } - printf(", in subdomain: %d\n", _inSubdomain); - } + virtual void printCell() const; std::list< std::pair<int, Cell*> > getCells() { return _cells; } int getNumCells() {return _cells.size();} @@ -952,8 +699,7 @@ class CellComplex std::set<Cell*, Less_Cell> _cells[4]; // storage for cell pointers to delete them - std::list<Cell*> _trash; - + std::list<Cell*> _trash; std::vector< std::set<Cell*, Less_Cell> > _store; std::set<Cell*, Less_Cell> _ecells; @@ -969,11 +715,6 @@ class CellComplex // Is the cell complex simplicial bool _simplicial; - public: - // iterator for the cells of same dimension - typedef std::set<Cell*, Less_Cell>::iterator citer; - - private: // 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); @@ -987,76 +728,21 @@ class CellComplex // remove a cell from this cell complex void removeCell(Cell* cell, bool other=true); - public: - void insertCell(Cell* cell); - // reduction of this cell complex - // removes reduction pairs of cell of dimension dim and dim-1 - int reduction(int dim, int omitted=0); - private: // queued coreduction presented in Mrozek's paper int coreduction(Cell* generator, int omitted=0); - public: - /* - 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( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain ); + //CellComplex(CellComplex* cellComplex) CellComplex(){} - ~CellComplex(){ - for(int i = 0; i < 4; i++){ - _cells[i].clear(); - - for(citer cit = _ocells[i].begin(); cit != _ocells[i].end(); cit++){ - Cell* cell = *cit; - delete cell; - } - _ocells[i].clear(); - - } - //emptyTrash(); - } + ~CellComplex(); - - void emptyTrash(){ - for(std::list<Cell*>::iterator cit = _trash.begin(); cit != _trash.end(); cit++){ - Cell* cell = *cit; - delete cell; - } - _trash.clear(); - } + void emptyTrash(); // restore this cell complex to its original state - void restoreComplex(){ - for(int i = 0; i < 4; i++){ - _betti[i] = 0; - _cells[i] = _ocells[i]; - for(citer cit = firstCell(i); cit != lastCell(i); cit++){ - Cell* cell = *cit; - cell->restoreCell(); - } - } - _store.clear(); - _ecells.clear(); - _trash.clear(); - } + void restoreComplex(); // get the number of certain dimensional cells int getSize(int dim){ return _cells[dim].size(); } @@ -1069,6 +755,9 @@ class CellComplex 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(); } @@ -1077,49 +766,36 @@ class CellComplex // true if cell complex has given cell - bool hasCell(Cell* cell, bool org=false){ - if(!org){ - citer cit = _cells[cell->getDim()].find(cell); - if( cit == lastCell(cell->getDim()) ) return false; - else return true; - } - else{ - citer cit = _ocells[cell->getDim()].find(cell); - if( cit == lastOrgCell(cell->getDim()) ) return false; - else return true; - } - } - - - // kappa for two cells of this cell complex - // implementation will vary depending on cell type - //inline int kappa(Cell* sigma, Cell* tau) const { return sigma->kappa(tau); } - + 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()) ); } - + void insertCell(Cell* cell); + + // 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); - // write this cell complex in 2.1 MSH ASCII format + // write this cell complex in 2.0 MSH ASCII format + // for debugging only int writeComplexMSH(const std::string &name); // Cell combining for reduction and coreduction int combine(int dim); int cocombine(int dim); - void computeBettiNumbers(); int getBettiNumber(int i) { if(i > -1 && i < 4) return _betti[i]; else return 0; } @@ -1127,36 +803,15 @@ class CellComplex // also check whether all (co)boundary cells of a cell belong to this cell complex bool checkCoherence(); - int eulerCharacteristic(){ - return getSize(0) - getSize(1) + getSize(2) - getSize(3); - } + 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); } - + 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(){ - std::set<Cell*, Less_Cell> temp = _cells[0]; - _cells[0] = _cells[3]; - _cells[3] = temp; - temp = _cells[1]; - _cells[1] = _cells[2]; - _cells[2] = temp; - - for(int i = 0; i < 4; i++){ - for(citer cit = firstCell(i); cit != lastCell(i); cit++){ - Cell* cell = *cit; - cell->makeDualCell(); - } - } - } - - - - + void makeDualComplex(); }; #endif diff --git a/Geo/ChainComplex.cpp b/Geo/ChainComplex.cpp index 172fe594e7..7509908513 100644 --- a/Geo/ChainComplex.cpp +++ b/Geo/ChainComplex.cpp @@ -82,17 +82,15 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){ //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){ - printf("Warning: Index out of bound! HMatrix: %d. \n", dim); + Msg::Debug("Warning: Index out of bound! HMatrix: %d. \n", dim); } else{ 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( (old_elem + (*it).second) > 1 || (old_elem + (*it).second) < -1 ){ - printf("Warning: Invalid incidence index: %d! HMatrix: %d.", (old_elem + (*it).second), dim); - printf(" Set to %d. \n", (old_elem + (*it).second) % 2); - mpz_set_si(elem, (old_elem + (*it).second) % 2); - }*/ + if( abs((old_elem + (*it).second)) > 1){ + Msg::Debug("Incidence index: %d! HMatrix: %d.", (old_elem + (*it).second), dim); + } gmp_matrix_set_elem(elem, bdCell->getIndex(), cell->getIndex(), _HMatrix[dim]); } } @@ -291,7 +289,7 @@ void ChainComplex::computeHomology(bool dual){ //KerCod(highDim); } - printf("Homology computation process: step %d of 4 \n", i+1); + Msg::Debug("Homology computation process: step %d of 4 \n", i+1); KerCod(highDim); @@ -560,7 +558,7 @@ void Chain::smoothenChain(){ eraseNullCells(); double t2 = Cpu(); - printf("Smoothened a %d-chain from %d cells to %d cells (%g s).\n", getDim(), start, getSize(), t2-t1); + Msg::Debug("Smoothened a %d-chain from %d cells to %d cells (%g s).\n", getDim(), start, getSize(), t2-t1); return; } @@ -574,8 +572,8 @@ int Chain::writeChainMSH(const std::string &name){ FILE *fp = fopen(name.c_str(), "a"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); - printf("Unable to open file."); - return 0; + Msg::Debug("Unable to open file."); + return 0; } fprintf(fp, "\n$ElementData\n"); @@ -674,4 +672,65 @@ void Chain::createPView(){ } +void Chain::removeCell(Cell* cell) { + citer it = _cells.find(cell); + if(it != _cells.end()){ + (*it).second = 0; + } + return; +} + +void Chain::addCell(Cell* cell, int coeff) { + std::pair<citer,bool> insert = _cells.insert( std::make_pair( cell, coeff)); + if(!insert.second && (*insert.first).second == 0) (*insert.first).second = coeff; + else if (!insert.second && (*insert.first).second != 0) Msg::Debug("Error: invalid chain smoothening add! \n"); + + if(!_cellComplex->hasCell(cell)){ + _cellComplex->insertCell(cell); + } + return; +} + +bool Chain::hasCell(Cell* c){ + citer it = _cells.find(c); + if(it != _cells.end() && (*it).second != 0) return true; + return false; +} +Cell* Chain::findCell(Cell* c){ + citer it = _cells.find(c); + if(it != _cells.end() && (*it).second != 0) return (*it).first; + return NULL; +} +int Chain::getCoeff(Cell* c){ + citer it = _cells.find(c); + if(it != _cells.end()) return (*it).second; + return 0; +} + +void Chain::eraseNullCells(){ + for(citer cit = _cells.begin(); cit != _cells.end(); cit++){ + if( (*cit).second == 0){ + //cit++; + //_cells.erase(--cit); + _cells.erase(cit); + ++cit; + } + } + for(citer cit = _cells.begin(); cit != _cells.end(); cit++){ + if( (*cit).second == 0){ + _cells.erase(cit); + cit = _cells.begin(); + } + } + return; +} + + +void Chain::deImmuneCells(){ + for(citer cit = _cells.begin(); cit != _cells.end(); cit++){ + Cell* cell = (*cit).first; + cell->setImmune(false); + } +} + #endif diff --git a/Geo/ChainComplex.h b/Geo/ChainComplex.h index 3a474b3a2c..3897b6cc82 100644 --- a/Geo/ChainComplex.h +++ b/Geo/ChainComplex.h @@ -115,7 +115,7 @@ class ChainComplex{ // Compute bases for the homology groups of this chain complex void computeHomology(bool dual=false); - // get coefficient vector for dim-dimensional chain chainNumber + // 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); @@ -171,48 +171,15 @@ class Chain{ typedef std::map<Cell*, int, Less_Cell>::iterator citer; - // get i:th cell of this chain - //Cell* getCell(int i) { return _cells.at(i).first; } - // get coeffcient of i:th cell of this chain - //int getCoeff(int i) { return _cells.at(i).second; } - - // remove a cell from this chain - void removeCell(Cell* cell) { - citer it = _cells.find(cell); - if(it != _cells.end()){ - (*it).second = 0; - } - return; - } + void removeCell(Cell* cell); // add a cell to this chain - void addCell(Cell* cell, int coeff) { - std::pair<citer,bool> insert = _cells.insert( std::make_pair( cell, coeff)); - if(!insert.second && (*insert.first).second == 0) (*insert.first).second = coeff; - else if (!insert.second && (*insert.first).second != 0) printf("Error: invalid chain smoothening add! \n"); - - if(!_cellComplex->hasCell(cell)){ - _cellComplex->insertCell(cell); - } - return; - } + void addCell(Cell* cell, int coeff); - bool hasCell(Cell* c){ - citer it = _cells.find(c); - if(it != _cells.end() && (*it).second != 0) return true; - return false; - } - Cell* findCell(Cell* c){ - citer it = _cells.find(c); - if(it != _cells.end() && (*it).second != 0) return (*it).first; - return NULL; - } - int getCoeff(Cell* c){ - citer it = _cells.find(c); - if(it != _cells.end()) return (*it).second; - return 0; - } + bool hasCell(Cell* c); + Cell* findCell(Cell* c); + int getCoeff(Cell* c); int getTorsion() {return _torsion;} @@ -222,40 +189,12 @@ class Chain{ std::map<Cell*, int, Less_Cell> getCells() {return _cells;} // erase cells from the chain with zero coefficient - void eraseNullCells(){ - for(citer cit = _cells.begin(); cit != _cells.end(); cit++){ - if( (*cit).second == 0){ - //cit++; - //_cells.erase(--cit); - _cells.erase(cit); - ++cit; - } - } - for(citer cit = _cells.begin(); cit != _cells.end(); cit++){ - if( (*cit).second == 0){ - _cells.erase(cit); - cit = _cells.begin(); - } - } - return; - } + void eraseNullCells(); - - void deImmuneCells(){ - for(citer cit = _cells.begin(); cit != _cells.end(); cit++){ - Cell* cell = (*cit).first; - cell->setImmune(false); - } - } + void deImmuneCells(); // number of cells in this chain - int getSize() { - //eraseNullCells(); - return _cells.size(); - } - int getNumCells() { - return _cells.size(); - } + int getSize() { return _cells.size();} // get/set chain name std::string getName() { return _name; } @@ -269,6 +208,7 @@ class Chain{ 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. diff --git a/Geo/Homology.cpp b/Geo/Homology.cpp index 9d83783a41..7b0a96c0ab 100644 --- a/Geo/Homology.cpp +++ b/Geo/Homology.cpp @@ -19,6 +19,8 @@ Homology::Homology(GModel* model, std::vector<int> physicalDomain, std::vector<i _subdomain = physicalSubdomain; Msg::Info("Creating a Cell Complex..."); + Msg::StatusBar(1, false, "Cell Complex..."); + Msg::StatusBar(2, false, ""); double t1 = Cpu(); std::map<int, std::vector<GEntity*> > groups[4]; @@ -68,13 +70,25 @@ Homology::Homology(GModel* model, std::vector<int> physicalDomain, std::vector<i Msg::Info("Cell Complex complete (%g s).", t2 - t1); Msg::Info("%d volumes, %d faces, %d edges and %d vertices.", _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0)); + Msg::StatusBar(2, false, "%d V, %d F, %d E, %d V.", + _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; + } + } + } void Homology::findGenerators(std::string fileName){ - Msg::Info("Reducing Cell Complex..."); + Msg::Info("Reducing the Cell Complex..."); + Msg::StatusBar(1, false, "Reducing..."); double t1 = Cpu(); //_cellComplex->printEuler(); int omitted = _cellComplex->reduceComplex(); @@ -98,10 +112,12 @@ void Homology::findGenerators(std::string fileName){ Msg::Info("Cell Complex reduction complete (%g s).", t2 - t1); Msg::Info("%d volumes, %d faces, %d edges and %d vertices.", _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0)); - + Msg::StatusBar(2, false, "%d V, %d F, %d E, %d N.", + _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0)); //for(int i = 0; i < 4; i++) { printf("Dim %d: \n", i); _cellComplex->printComplex(i); } - Msg::Info("Computing homology groups..."); + Msg::Info("Computing homology spaces..."); + Msg::StatusBar(1, false, "Computing..."); t1 = Cpu(); ChainComplex* chains = new ChainComplex(_cellComplex); chains->computeHomology(); @@ -149,19 +165,22 @@ void Homology::findGenerators(std::string fileName){ createPViews(); if(fileName != "") writeGeneratorsMSH(fileName); - Msg::Info("Ranks of homology groups for primal cell complex:"); + Msg::Info("Ranks of homology spaces for primal cell complex:"); Msg::Info("H0 = %d", HRank[0]); Msg::Info("H1 = %d", HRank[1]); Msg::Info("H2 = %d", HRank[2]); Msg::Info("H3 = %d", HRank[3]); - if(omitted != 0) Msg::Info("The computation of generators in %d highest dimensions was omitted.", omitted); + if(omitted != 0) Msg::Info("The computation of generators in the highest dimension was omitted."); delete chains; - printf("H0 = %d \n", HRank[0]); - printf("H1 = %d \n", HRank[1]); - printf("H2 = %d \n", HRank[2]); - printf("H3 = %d \n", HRank[3]); + Msg::Debug("H0 = %d \n", HRank[0]); + Msg::Debug("H1 = %d \n", HRank[1]); + Msg::Debug("H2 = %d \n", HRank[2]); + Msg::Debug("H3 = %d \n", HRank[3]); + + Msg::StatusBar(1, false, "Homology"); + Msg::StatusBar(2, false, "H0: %d, H1: %d, H2: %d, H3: %d.", HRank[0], HRank[1], HRank[2], HRank[3]); return; } @@ -171,6 +190,7 @@ void Homology::findDualGenerators(std::string fileName){ //for(int i = 0; i < 4; i++) { printf("Dim %d: \n", i); _cellComplex->printComplex(i); } Msg::Info("Reducing Cell Complex..."); + Msg::StatusBar(1, false, "Reducing..."); double t1 = Cpu(); int omitted = _cellComplex->coreduceComplex(); //_cellComplex->emptyTrash(); @@ -199,12 +219,14 @@ void Homology::findDualGenerators(std::string fileName){ Msg::Info("Cell Complex reduction complete (%g s).", t2 - t1); Msg::Info("%d volumes, %d faces, %d edges and %d vertices.", _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0)); - + Msg::StatusBar(2, false, "%d V, %d F, %d E, %d N.", + _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0)); - _cellComplex->writeComplexMSH(fileName); + //_cellComplex->writeComplexMSH(fileName); - Msg::Info("Computing homology groups..."); + Msg::Info("Computing homology spaces..."); + Msg::StatusBar(1, false, "Computing..."); t1 = Cpu(); ChainComplex* chains = new ChainComplex(_cellComplex); chains->transposeHMatrices(); @@ -255,7 +277,7 @@ void Homology::findDualGenerators(std::string fileName){ createPViews(); if(fileName != "") writeGeneratorsMSH(fileName); - Msg::Info("Ranks of homology groups for dual cell complex:"); + Msg::Info("Ranks of homology spaces for dual cell complex:"); Msg::Info("H0* = %d", HRank[0]); Msg::Info("H1* = %d", HRank[1]); Msg::Info("H2* = %d", HRank[2]); @@ -264,10 +286,13 @@ void Homology::findDualGenerators(std::string fileName){ delete chains; - printf("H0* = %d \n", HRank[0]); - printf("H1* = %d \n", HRank[1]); - printf("H2* = %d \n", HRank[2]); - printf("H3* = %d \n", HRank[3]); + Msg::Debug("H0* = %d \n", HRank[0]); + Msg::Debug("H1* = %d \n", HRank[1]); + Msg::Debug("H2* = %d \n", HRank[2]); + Msg::Debug("H3* = %d \n", HRank[3]); + + Msg::StatusBar(1, false, "Homology"); + Msg::StatusBar(2, false, "H0*: %d, H1*: %d, H2*: %d, H3*: %d.", HRank[0], HRank[1], HRank[2], HRank[3]); return; } @@ -275,6 +300,7 @@ void Homology::findDualGenerators(std::string fileName){ void Homology::computeBettiNumbers(){ Msg::Info("Running coreduction..."); + Msg::StatusBar(1, false, "Computing..."); double t1 = Cpu(); _cellComplex->computeBettiNumbers(); double t2 = Cpu(); @@ -285,7 +311,69 @@ void Homology::computeBettiNumbers(){ Msg::Info("H2 = %d", _cellComplex->getBettiNumber(2)); Msg::Info("H3 = %d", _cellComplex->getBettiNumber(3)); + Msg::StatusBar(1, false, "Homology"); + Msg::StatusBar(2, false, "H0: %d, H1: %d, H2: %d, H3: %d.", _cellComplex->getBettiNumber(0), _cellComplex->getBettiNumber(1), _cellComplex->getBettiNumber(2), _cellComplex->getBettiNumber(3)); + return; } + + void Homology::restoreHomology() { + _cellComplex->restoreComplex(); + for(int i = 0; i < 4; i++) _generators[i].clear(); + } + + std::string Homology::getDomainString() { + std::string domainString = "({"; + for(unsigned int i = 0; i < _domain.size(); i++){ + std::string temp = ""; + convert(_domain.at(i),temp); + domainString += temp; + if (_domain.size()-1 > i){ + domainString += ", "; + } + } + domainString += "}"; + + if(!_subdomain.empty()){ + domainString += ", {"; + + for(unsigned int i = 0; i < _subdomain.size(); i++){ + std::string temp = ""; + convert(_subdomain.at(i),temp); + domainString += temp; + if (_subdomain.size()-1 > i){ + domainString += ", "; + } + } + domainString += "}"; + + } + domainString += ") "; + return domainString; + } + + void Homology::createPViews(){ + for(int i = 0; i < 4; i++){ + for(int j = 0; j < _generators[i].size(); j++){ + Chain* chain = _generators[i].at(j); + chain->createPView(); + } + } + } + + bool Homology::writeGeneratorsMSH(std::string fileName, bool binary){ + if(!_model->writeMSH(fileName, 2.0, binary)) return false; + /* + for(int i = 0; i < 4; i++){ + for(int j = 0; j < _generators[i].size(); j++){ + Chain* chain = _generators[i].at(j); + if(!chain->writeChainMSH(fileName)) return false; + } + }*/ + Msg::Info("Wrote homology computation results to %s.", fileName.c_str()); + Msg::Debug("Wrote homology computation results to %s. \n", fileName.c_str()); + + return true; + } #endif diff --git a/Geo/Homology.h b/Geo/Homology.h index 99af3629f1..fbc47be58c 100644 --- a/Geo/Homology.h +++ b/Geo/Homology.h @@ -41,16 +41,7 @@ class Homology public: Homology(GModel* model, std::vector<int> physicalDomain, std::vector<int> physicalSubdomain); - ~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(); // Find the generators/duals of homology spaces, or just compute the ranks of homology spaces void findGenerators(std::string fileName); @@ -61,67 +52,15 @@ class Homology //void swapSubdomain() { _cellComplex->swapSubdomain(); } // Restore the cell complex to its original state before cell reductions - void restoreHomology() { - _cellComplex->restoreComplex(); - for(int i = 0; i < 4; i++) _generators[i].clear(); - } + void restoreHomology(); // Create a string describing the generator - std::string getDomainString() { - std::string domainString = "({"; - for(unsigned int i = 0; i < _domain.size(); i++){ - std::string temp = ""; - convert(_domain.at(i),temp); - domainString += temp; - if (_domain.size()-1 > i){ - domainString += ", "; - } - } - domainString += "}"; - - if(!_subdomain.empty()){ - domainString += ", {"; - - for(unsigned int i = 0; i < _subdomain.size(); i++){ - std::string temp = ""; - convert(_subdomain.at(i),temp); - domainString += temp; - if (_subdomain.size()-1 > i){ - domainString += ", "; - } - } - domainString += "}"; - - } - domainString += ") "; - return domainString; - } - - // create PViews of the generators - void createPViews(){ - for(int i = 0; i < 4; i++){ - for(int j = 0; j < _generators[i].size(); j++){ - Chain* chain = _generators[i].at(j); - chain->createPView(); - } - } - } + 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){ - if(!_model->writeMSH(fileName, 2.0, binary)) return false; - /* - for(int i = 0; i < 4; i++){ - for(int j = 0; j < _generators[i].size(); j++){ - Chain* chain = _generators[i].at(j); - if(!chain->writeChainMSH(fileName)) return false; - } - }*/ - Msg::Info("Wrote homology computation results to %s.", fileName.c_str()); - printf("Wrote homology computation results to %s. \n", fileName.c_str()); - - return true; - } + bool writeGeneratorsMSH(std::string fileName, bool binary=false); }; diff --git a/tutorial/t10.geo b/tutorial/t10.geo index 464d688417..a97eb68816 100644 --- a/tutorial/t10.geo +++ b/tutorial/t10.geo @@ -133,9 +133,9 @@ Mesh 3; // Save the generator chains to t10_hom.msh. HomGen("t10_hom.msh") = {{69}, {70, 71, 72, 73}}; -// Find the corresponding cuts. +// Find the corresponding thin cuts. // Save the cut chains to t10_hom.msh. -HomCut("t10_hom.msh") = {{69}, {70, 71, 72, 73}}; +HomGen("t10_hom.msh") = {{69}, {75}}; // Only find and print the ranks of the relative homology spaces (Betti numbers). HomRank {{69},{70, 71, 72, 73}}; @@ -143,6 +143,5 @@ HomRank {{69},{70, 71, 72, 73}}; // More examples (uncomment): // HomGen("t10_homgen.msh_1") = {{69}, {}}; // HomGen("t10_homgen.msh_2") = {{69}, {74}}; -// HomGen("t10_homgen.msh_3") = {{69}, {75}}; -- GitLab