// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. // // Contributed by Matti Pellikka. #include "Homology.h" #include "ChainComplex.h" #include "OS.h" #if defined(HAVE_KBIPACK) Homology::Homology(GModel* model, std::vector<int> physicalDomain, std::vector<int> physicalSubdomain){ _model = model; _combine = true; _omit = 1; Msg::Info("Creating a Cell Complex..."); double t1 = Cpu(); std::map<int, std::vector<GEntity*> > groups[4]; model->getPhysicalGroups(groups); std::map<int, std::vector<GEntity*> >::iterator it; std::vector<GEntity*> domainEntities; std::vector<GEntity*> subdomainEntities; for(unsigned int i = 0; i < physicalDomain.size(); i++){ for(int j = 0; j < 4; j++){ it = groups[j].find(physicalDomain.at(i)); if(it != groups[j].end()){ std::vector<GEntity*> physicalGroup = (*it).second; for(unsigned int k = 0; k < physicalGroup.size(); k++){ domainEntities.push_back(physicalGroup.at(k)); } } } } for(unsigned int i = 0; i < physicalSubdomain.size(); i++){ for(int j = 0; j < 4; j++){ it = groups[j].find(physicalSubdomain.at(i)); if(it != groups[j].end()){ std::vector<GEntity*> physicalGroup = (*it).second; for(unsigned int k = 0; k < physicalGroup.size(); k++){ subdomainEntities.push_back(physicalGroup.at(k)); } } } } if(domainEntities.empty()) Msg::Warning("Domain is empty."); if(subdomainEntities.empty()) Msg::Info("Subdomain is empty."); _cellComplex = new CellComplex(domainEntities, subdomainEntities); if(_cellComplex->getSize(0) == 0){ Msg::Error("Cell Complex is empty!"); Msg::Error("Check the domain & the mesh."); return; } double t2 = Cpu(); 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)); } void Homology::findGenerators(std::string fileName){ Msg::Info("Reducing Cell Complex..."); double t1 = Cpu(); int omitted = _cellComplex->reduceComplex(_omit); if(getCombine()){ _cellComplex->combine(3); _cellComplex->reduction(2); _cellComplex->combine(2); _cellComplex->reduction(1); _cellComplex->combine(1); } _cellComplex->checkCoherence(); double t2 = Cpu(); 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)); //for(int i = 0; i < 4; i++) { printf("Dim %d: \n", i); _cellComplex->printComplex(i); } _cellComplex->writeComplexMSH(fileName); Msg::Info("Computing homology groups..."); t1 = Cpu(); ChainComplex* chains = new ChainComplex(_cellComplex); chains->computeHomology(); t2 = Cpu(); Msg::Info("Homology Computation complete (%g s).", t2 - t1); int HRank[4]; for(int j = 0; j < 4; j++){ HRank[j] = 0; for(int i = 1; i <= chains->getBasisSize(j); i++){ std::string generator; std::string dimension; convert(i, generator); convert(j, dimension); std::string name = dimension + "D Generator " + generator; Chain* chain = new Chain(_cellComplex->getCells(j), chains->getCoeffVector(j,i), _cellComplex, name, chains->getTorsion(j,i)); chain->writeChainMSH(fileName); if(chain->getSize() != 0) { HRank[j] = HRank[j] + 1; if(chain->getTorsion() != 1) Msg::Warning("%dD Generator %d has torsion coefficient %d!", j, i, chain->getTorsion()); } delete chain; } } Msg::Info("Ranks of homology groups 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("Computation of generators in %d highest dimensions was omitted.", _omit); Msg::Info("Wrote results to %s.", fileName.c_str()); 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]); return; } void Homology::findThickCuts(std::string fileName){ //for(int i = 0; i < 4; i++) { printf("Dim %d: \n", i); _cellComplex->printComplex(i); } Msg::Info("Reducing Cell Complex..."); double t1 = Cpu(); int omitted = _cellComplex->coreduceComplex(_omit); /* _cellComplex->makeDualComplex(); int omitted = _cellComplex->reduceComplex(_omit); if(getCombine()){ _cellComplex->combine(3); _cellComplex->combine(2); _cellComplex->combine(1); } _cellComplex->makeDualComplex(); */ if(getCombine()){ _cellComplex->cocombine(0); _cellComplex->cocombine(1); _cellComplex->cocombine(2); } _cellComplex->checkCoherence(); double t2 = Cpu(); 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)); _cellComplex->writeComplexMSH(fileName); Msg::Info("Computing homology groups..."); t1 = Cpu(); ChainComplex* chains = new ChainComplex(_cellComplex); chains->transposeHMatrices(); chains->computeHomology(true); t2 = Cpu(); Msg::Info("Homology Computation complete (%g s).", t2- t1); int dim = _cellComplex->getDim(); int HRank[4]; for(int i = 0; i < 4; i++) HRank[i] = 0; for(int j = 3; j > -1; j--){ for(int i = 1; i <= chains->getBasisSize(j); i++){ std::string generator; std::string dimension; convert(i, generator); convert(dim-j, dimension); std::string name = dimension + "D Thick cut " + generator; Chain* chain = new Chain(_cellComplex->getCells(j), chains->getCoeffVector(j,i), _cellComplex, name, chains->getTorsion(j,i)); chain->writeChainMSH(fileName); if(chain->getSize() != 0){ HRank[dim-j] = HRank[dim-j] + 1; if(chain->getTorsion() != 1) Msg::Warning("%dD Thick cut %d has torsion coefficient %d!", j, i, chain->getTorsion()); } delete chain; } } Msg::Info("Ranks of homology groups for dual 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("Computation of %d highest dimension thick cuts was omitted.", _omit); Msg::Info("Wrote results to %s.", fileName.c_str()); 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]); return; } #endif