Skip to content
Snippets Groups Projects
Homology.cpp 6.9 KiB
Newer Older
Matti Pellika's avatar
Matti Pellika committed
// 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"
Matti Pellika's avatar
 
Matti Pellika committed
#include "OS.h"
Matti Pellika's avatar
Matti Pellika committed

Matti Pellika's avatar
 
Matti Pellika committed
#if defined(HAVE_KBIPACK)
Matti Pellika's avatar
Matti Pellika committed
Homology::Homology(GModel* model, std::vector<int> physicalDomain, std::vector<int> physicalSubdomain){
  
  _model = model;
Matti Pellika's avatar
 
Matti Pellika committed
  _omit = 1;
Matti Pellika's avatar
Matti Pellika committed
  
  Msg::Info("Creating a Cell Complex...");
Matti Pellika's avatar
 
Matti Pellika committed
  double t1 = Cpu();
Matti Pellika's avatar
Matti Pellika committed
  
  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++){
Matti Pellika's avatar
Matti Pellika committed
    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++){
Matti Pellika's avatar
Matti Pellika committed
          domainEntities.push_back(physicalGroup.at(k));
        }
      }
    }
  }
  for(unsigned int i = 0; i < physicalSubdomain.size(); i++){           
Matti Pellika's avatar
Matti Pellika committed
    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++){
Matti Pellika's avatar
Matti Pellika committed
          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;
  }
Matti Pellika's avatar
 
Matti Pellika committed
  double t2 = Cpu();
  Msg::Info("Cell Complex complete (%g s).", t2 - t1);
Matti Pellika's avatar
Matti Pellika committed
  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){
  
Matti Pellika's avatar
 
Matti Pellika committed
  
  
Matti Pellika's avatar
Matti Pellika committed
  Msg::Info("Reducing Cell Complex...");
Matti Pellika's avatar
 
Matti Pellika committed
  double t1 = Cpu();
Matti Pellika's avatar
 
Matti Pellika committed
  int omitted = _cellComplex->reduceComplex(_omit);
Matti Pellika's avatar
 
Matti Pellika committed
  
  if(getCombine()){
    _cellComplex->combine(3);
Matti Pellika's avatar
 
Matti Pellika committed
    _cellComplex->reduction(2);
Matti Pellika's avatar
 
Matti Pellika committed
    _cellComplex->reduction(1);
Matti Pellika's avatar
 
Matti Pellika committed
  _cellComplex->checkCoherence();
  
Matti Pellika's avatar
 
Matti Pellika committed
  double t2 = Cpu();
  Msg::Info("Cell Complex reduction complete (%g s).", t2 - t1);
Matti Pellika's avatar
Matti Pellika committed
  Msg::Info("%d volumes, %d faces, %d edges and %d vertices.",
            _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0));

Matti Pellika's avatar
 
Matti Pellika committed
  //for(int i = 0; i < 4; i++) { printf("Dim %d: \n", i); _cellComplex->printComplex(i); }
  
Matti Pellika's avatar
Matti Pellika committed
  _cellComplex->writeComplexMSH(fileName);
  
  Msg::Info("Computing homology groups...");
Matti Pellika's avatar
 
Matti Pellika committed
  t1 = Cpu();
Matti Pellika's avatar
Matti Pellika committed
  ChainComplex* chains = new ChainComplex(_cellComplex);
  chains->computeHomology();
Matti Pellika's avatar
 
Matti Pellika committed
  t2 = Cpu();
  Msg::Info("Homology Computation complete (%g s).", t2 - t1);
Matti Pellika's avatar
 
Matti Pellika committed
  int HRank[4];
Matti Pellika's avatar
Matti Pellika committed
  for(int j = 0; j < 4; j++){
Matti Pellika's avatar
 
Matti Pellika committed
    HRank[j] = 0;
Matti Pellika's avatar
Matti Pellika committed
    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;
Matti Pellika's avatar
 
Matti Pellika committed
      Chain* chain = new Chain(_cellComplex->getCells(j), chains->getCoeffVector(j,i), _cellComplex, name, chains->getTorsion(j,i));
Matti Pellika's avatar
Matti Pellika committed
      chain->writeChainMSH(fileName);
Matti Pellika's avatar
 
Matti Pellika committed
      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());
      }
Matti Pellika's avatar
Matti Pellika committed
      delete chain;
    }
  }
Matti Pellika's avatar
 
Matti Pellika committed
  
  Msg::Info("Ranks of homology groups for primal cell complex:");
Matti Pellika's avatar
 
Matti Pellika committed
  Msg::Info("H0 = %d", HRank[0]);
  Msg::Info("H1 = %d", HRank[1]);
  Msg::Info("H2 = %d", HRank[2]);
  Msg::Info("H3 = %d", HRank[3]);
Matti Pellika's avatar
 
Matti Pellika committed
  if(omitted != 0) Msg::Info("Computation of generators in %d highest dimensions was omitted.", _omit);
Matti Pellika's avatar
 
Matti Pellika committed
  
Matti Pellika's avatar
Matti Pellika committed
  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]);
  
Matti Pellika's avatar
Matti Pellika committed
  return;
}

void Homology::findThickCuts(std::string fileName){
  
Matti Pellika's avatar
 
Matti Pellika committed
  //for(int i = 0; i < 4; i++) { printf("Dim %d: \n", i); _cellComplex->printComplex(i); }
  
Matti Pellika's avatar
Matti Pellika committed
  Msg::Info("Reducing Cell Complex...");
Matti Pellika's avatar
 
Matti Pellika committed
  double t1 = Cpu();
Matti Pellika's avatar
 
Matti Pellika committed
  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);
  }
Matti Pellika's avatar
 
Matti Pellika committed
  _cellComplex->checkCoherence();
Matti Pellika's avatar
 
Matti Pellika committed
  double t2 = Cpu();
  Msg::Info("Cell Complex reduction complete (%g s).", t2 - t1);
Matti Pellika's avatar
Matti Pellika committed
  Msg::Info("%d volumes, %d faces, %d edges and %d vertices.",
            _cellComplex->getSize(3), _cellComplex->getSize(2), _cellComplex->getSize(1), _cellComplex->getSize(0));
 
Matti Pellika's avatar
Matti Pellika committed
  _cellComplex->writeComplexMSH(fileName);
  
  Msg::Info("Computing homology groups...");
Matti Pellika's avatar
 
Matti Pellika committed
  t1 = Cpu();
Matti Pellika's avatar
Matti Pellika committed
  ChainComplex* chains = new ChainComplex(_cellComplex);
  chains->transposeHMatrices();
  chains->computeHomology(true);
Matti Pellika's avatar
 
Matti Pellika committed
  t2 = Cpu();
  Msg::Info("Homology Computation complete (%g s).", t2- t1);
Matti Pellika's avatar
Matti Pellika committed
  
Matti Pellika's avatar
 
Matti Pellika committed
  int dim = _cellComplex->getDim();
Matti Pellika's avatar
 
Matti Pellika committed
  
  int HRank[4];
Matti Pellika's avatar
 
Matti Pellika committed
  for(int i = 0; i < 4; i++) HRank[i] = 0;
Matti Pellika's avatar
Matti Pellika committed
  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);
Matti Pellika's avatar
 
Matti Pellika committed
      convert(dim-j, dimension);
Matti Pellika's avatar
Matti Pellika committed
      
Matti Pellika's avatar
 
Matti Pellika committed
      std::string name = dimension + "D Thick cut " + generator;
Matti Pellika's avatar
 
Matti Pellika committed
      Chain* chain = new Chain(_cellComplex->getCells(j), chains->getCoeffVector(j,i), _cellComplex, name, chains->getTorsion(j,i));
Matti Pellika's avatar
Matti Pellika committed
      chain->writeChainMSH(fileName);
Matti Pellika's avatar
 
Matti Pellika committed
      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());
      }
Matti Pellika's avatar
Matti Pellika committed
      delete chain;
            
    }
  }
Matti Pellika's avatar
 
Matti Pellika committed
  Msg::Info("Ranks of homology groups for dual cell complex:");
Matti Pellika's avatar
 
Matti Pellika committed
  Msg::Info("H0 = %d", HRank[0]);
  Msg::Info("H1 = %d", HRank[1]);
  Msg::Info("H2 = %d", HRank[2]);
  Msg::Info("H3 = %d", HRank[3]);
Matti Pellika's avatar
 
Matti Pellika committed
  if(omitted != 0) Msg::Info("Computation of %d highest dimension thick cuts was omitted.", _omit);
Matti Pellika's avatar
 
Matti Pellika committed
  
Matti Pellika's avatar
Matti Pellika committed
  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;
Matti Pellika's avatar
Matti Pellika committed
}
Matti Pellika's avatar
 
Matti Pellika committed
#endif