Newer
Older
// Gmsh - Copyright (C) 1997-2010 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 <matti.pellikka@tut.fi>.
Homology::Homology(GModel* model, std::vector<int> physicalDomain,
std::vector<int> physicalSubdomain)
{
_model = model;
_domain = physicalDomain;
_subdomain = physicalSubdomain;
Msg::StatusBar(1, false, "Cell Complex...");
Msg::StatusBar(2, false, "");
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);
_cellComplex->getSize(3), _cellComplex->getSize(2),
_cellComplex->getSize(1), _cellComplex->getSize(0));
_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 the Cell Complex...");
Msg::StatusBar(1, false, "Reducing...");
int omitted = _cellComplex->reduceComplex();
_cellComplex->combine(3);
_cellComplex->reduction(2);
_cellComplex->combine(2);
_cellComplex->reduction(1);
_cellComplex->combine(1);
double t2 = Cpu();
Msg::Info("Cell Complex reduction complete (%g s).", t2 - t1);
_cellComplex->getSize(3), _cellComplex->getSize(2),
_cellComplex->getSize(1), _cellComplex->getSize(0));
_cellComplex->getSize(3), _cellComplex->getSize(2),
_cellComplex->getSize(1), _cellComplex->getSize(0));
Msg::Info("Computing homology spaces...");
Msg::StatusBar(1, false, "Computing...");
ChainComplex* chains = new ChainComplex(_cellComplex);
chains->computeHomology();
t2 = Cpu();
Msg::Info("Homology Computation complete (%g s).", t2 - t1);
std::string name = "H" + dimension + getDomainString() + generator;
Chain* chain = new Chain(_cellComplex->getCells(j),
chains->getCoeffVector(j,i),
_cellComplex, _model, name,
chains->getTorsion(j,i));
int start = chain->getSize();
t2 = Cpu();
Msg::Info("Smoothened H%d %d from %d cells to %d cells (%g s).",
if(chain->getTorsion() != 1){
Msg::Warning("H%d %d has torsion coefficient %d!",
j, i, chain->getTorsion());
}
if(j == _cellComplex->getDim() && _cellComplex->getNumOmitted() > 0){
for(int i = 0; i < _cellComplex->getNumOmitted(); i++){
std::string generator;
convert(i+1, generator);
std::string name = "H" + dimension + getDomainString() + generator;
Chain* chain = new Chain(_cellComplex->getOmitted(i), coeffs,
_cellComplex, _model, name, 1);
if(fileName != "") writeGeneratorsMSH(fileName);
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 the highest dimension was omitted.");
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]);
void Homology::findDualGenerators(std::string fileName)
{
int omitted = _cellComplex->coreduceComplex();
_cellComplex->cocombine(0);
_cellComplex->coreduction(1);
_cellComplex->cocombine(1);
_cellComplex->coreduction(2);
_cellComplex->cocombine(2);
_cellComplex->coreduction(3);
double t2 = Cpu();
Msg::Info("Cell Complex reduction complete (%g s).", t2 - t1);
_cellComplex->getSize(3), _cellComplex->getSize(2),
_cellComplex->getSize(1), _cellComplex->getSize(0));
_cellComplex->getSize(3), _cellComplex->getSize(2),
_cellComplex->getSize(1), _cellComplex->getSize(0));
Msg::Info("Computing homology spaces...");
Msg::StatusBar(1, false, "Computing...");
ChainComplex* chains = new ChainComplex(_cellComplex);
chains->transposeHMatrices();
chains->computeHomology(true);
t2 = Cpu();
Msg::Info("Homology Computation complete (%g s).", t2- t1);
std::string name = "H" + dimension + "*" + getDomainString() + generator;
Chain* chain = new Chain(_cellComplex->getCells(j),
chains->getCoeffVector(j,i), _cellComplex,
_model, name, chains->getTorsion(j,i));
_generators[dim-j].push_back(chain);
if(chain->getTorsion() != 1){
Msg::Warning("H%d* %d has torsion coefficient %d!",
dim-j, i, chain->getTorsion());
}
if(j == 0 && _cellComplex->getNumOmitted() > 0){
for(int i = 0; i < _cellComplex->getNumOmitted(); i++){
std::string generator;
convert(i+1, generator);
std::string name
= "H" + dimension + "*" + getDomainString() + generator;
Chain* chain = new Chain(_cellComplex->getOmitted(i), coeffs,
_cellComplex, _model, name, 1);
_generators[dim-j].push_back(chain);
if(chain->getSize() != 0) HRank[dim-j] = HRank[dim-j] + 1;
}
}
if(fileName != "") writeGeneratorsMSH(fileName);
Msg::Info("Ranks of homology spaces for the 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("The computation of %d highest dimension dual generators was omitted.", omitted);
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;
void Homology::computeBettiNumbers()
{
double t1 = Cpu();
_cellComplex->computeBettiNumbers();
double t2 = Cpu();
Msg::Info("Betti number computation complete (%g s).", t2- t1);
Msg::Info("H0 = %d", _cellComplex->getBettiNumber(0));
Msg::Info("H1 = %d", _cellComplex->getBettiNumber(1));
Msg::Info("H2 = %d", _cellComplex->getBettiNumber(2));
Msg::Info("H3 = %d", _cellComplex->getBettiNumber(3));
Msg::StatusBar(2, false, "H0: %d, H1: %d, H2: %d, H3: %d.",
_cellComplex->getBettiNumber(0),
_cellComplex->getBettiNumber(1),
_cellComplex->getBettiNumber(2),
_cellComplex->getBettiNumber(3));
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;
Msg::Info("Wrote homology computation results to %s.", fileName.c_str());
Msg::Debug("Wrote homology computation results to %s. \n",
fileName.c_str());