Newer
Older
// 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"
Homology::Homology(GModel* model, std::vector<int> physicalDomain, std::vector<int> physicalSubdomain){
_model = model;
_combine = true;
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++){
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){
if(getCombine()){
_cellComplex->combine(3);
_cellComplex->combine(2);
_cellComplex->combine(1);
}
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...");
ChainComplex* chains = new ChainComplex(_cellComplex);
chains->computeHomology();
t2 = Cpu();
Msg::Info("Homology Computation complete (%g s).", t2 - t1);
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));
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());
}
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); }
/*
_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);
}
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...");
ChainComplex* chains = new ChainComplex(_cellComplex);
chains->transposeHMatrices();
chains->computeHomology(true);
t2 = Cpu();
Msg::Info("Homology Computation complete (%g s).", t2- t1);
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);
Chain* chain = new Chain(_cellComplex->getCells(j), chains->getCoeffVector(j,i), _cellComplex, name, chains->getTorsion(j,i));
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());
}
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;