diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp
index 02a7c12836dfee280ec786c7b23009521823e175..892fc24c667f1169656bd9f764d670802775495e 100644
--- a/Geo/CellComplex.cpp
+++ b/Geo/CellComplex.cpp
@@ -12,6 +12,8 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su
   _domain = domain;
   _subdomain = subdomain;
   
+  _dim = 0;
+  
   // determine mesh entities on boundary of the domain
   bool duplicate = false;
   for(unsigned int j=0; j < _domain.size(); j++){
@@ -101,7 +103,9 @@ CellComplex::CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> su
       cell->setTag(tag);
       tag++;
     }
-    _originalCells[i] = _cells[i];
+    //_originalCells[i] = _cells[i];
+    _betti[i] = 0;
+    if(getSize(i) > _dim) _dim = i;
   }
   
 }
@@ -270,7 +274,7 @@ int Quadrangle::kappa(Cell* tau) const{
   return value;
 }
 
-
+/*
 std::set<Cell*, Less_Cell>::iterator CellComplex::findCell(int dim, std::vector<int>& vertices, bool original){
   Cell* cell;
   
@@ -299,7 +303,7 @@ std::set<Cell*, Less_Cell>::iterator CellComplex::findCell(int dim, int vertex,
   delete cell;
   return cit;
 }
-
+*/
 
 void CellComplex::removeCell(Cell* cell){
   
@@ -335,7 +339,7 @@ void CellComplex::enqueueCells(std::list<Cell*>& cells, std::queue<Cell*>& Q, st
   }
 }
 
-int CellComplex::coreductionMrozek(Cell* generator){
+int CellComplex::coreduction(Cell* generator){
   
   int coreductions = 0;
   
@@ -344,10 +348,9 @@ int CellComplex::coreductionMrozek(Cell* generator){
   
   Q.push(generator);
   Qset.insert(generator);
-  //removeCell(generator);
+  
   
   std::list<Cell*> bd_s;
-  //std::list< std::pair<int, Cell*> >bd_s;
   std::list<Cell*> cbd_c;
   Cell* s;
   int round = 0;
@@ -377,7 +380,7 @@ int CellComplex::coreductionMrozek(Cell* generator){
   //printf("Coreduction: %d loops with %d coreductions\n", round, coreductions);
   return coreductions;
 }
-
+/*
 int CellComplex::coreduction(int dim){
   
   if(dim < 0 || dim > 2) return 0;
@@ -405,6 +408,51 @@ int CellComplex::coreduction(int dim){
   return count;
     
 }
+*/
+/* 
+int CellComplex::reduction(Cell* generator){
+
+  int count = 0;
+  
+  std::queue<Cell*> Q;
+  std::set<Cell*, Less_Cell> Qset;
+  
+  Q.push(generator);
+  Qset.insert(generator);
+  
+  
+  std::list<Cell*> cbd_s;
+  std::list<Cell*> bd_c;
+  Cell* s;
+  int round = 0;
+  while( !Q.empty() ){
+    round++;
+    //printf("%d ", round);
+    
+    s = Q.front();
+    Q.pop();
+    removeCellQset(s, Qset);
+
+    cbd_s = s->getCoboundary();
+    if( cbd_s.size() == 1 && inSameDomain(s, cbd_s.front()) ){
+      removeCell(s);
+      bd_c = cbd_s.front()->getBoundary();
+      enqueueCells(bd_c, Q, Qset);
+      removeCell(cbd_s.front());
+      count++;
+    }
+    else if(cbd_s.empty()){
+      bd_c = s->getBoundary();
+      enqueueCells(bd_c, Q, Qset);
+    }
+    
+    
+  }
+  
+  return count;
+}
+*/
+
 
 int CellComplex::reduction(int dim){
   if(dim < 1 || dim > 3) return 0;
@@ -431,18 +479,58 @@ int CellComplex::reduction(int dim){
 }
 
  
-void CellComplex::reduceComplex(){
+void CellComplex::reduceComplex(bool omitHighdim){
   printf("Cell complex before reduction: %d volumes, %d faces, %d edges and %d vertices.\n",
          getSize(3), getSize(2), getSize(1), getSize(0));
-  reduction(3);
-  reduction(2);
-  reduction(1);
+
+  
+  //reduction(3);
+  //reduction(2);
+  //reduction(1);
+  
+  
+  
+  int count = 0;
+  for(int i = 3; i > 0; i--) count = count + reduction(i);
+  
+  
+  
+  if(count == 0 && omitHighdim){
+    
+    removeSubdomain();
+    std::set<Cell*, Less_Cell> generatorCells;
+    
+    while (getSize(getDim()) != 0){
+      citer cit = firstCell(getDim());
+      Cell* cell = *cit;
+      generatorCells.insert(cell);
+      removeCell(cell);
+      reduction(3);
+      reduction(2);
+      reduction(1);
+             
+     }
+    
+    
+    for(citer cit = generatorCells.begin(); cit != generatorCells.end(); cit++){
+      Cell* cell = *cit;
+      cell->clearBoundary();
+      cell->clearCoboundary();
+      _cells[getDim()].insert(cell);
+    }
+    
+    
+  }
+  
+  
   printf("Cell complex after reduction: %d volumes, %d faces, %d edges and %d vertices.\n",
          getSize(3), getSize(2), getSize(1), getSize(0));
 }
 
+/*
 void CellComplex::coreduceComplex(int generatorDim){
 
+  
   std::set<Cell*, Less_Cell> generatorCells[4];
   
   printf("Cell complex before coreduction: %d volumes, %d faces, %d edges and %d vertices.\n",
@@ -456,31 +544,194 @@ void CellComplex::coreduceComplex(int generatorDim){
         cell = *cit;
         cit++;
       }
-      generatorCells[i].insert(cell);
+      if(!cell->inSubdomain()) generatorCells[i].insert(cell);
       removeCell(cell);
 
-      //coreduction(0);
-      //coreduction(1);
-      //coreduction(2);
-      coreductionMrozek(cell);
+      coreduction(cell);
     }
     if(generatorDim == i) break;
     
   }
-  /*
+  
   for(int i = 0; i < 4; i++){
     for(citer cit = generatorCells[i].begin(); cit != generatorCells[i].end(); cit++){
       Cell* cell = *cit;
-      if(!cell->inSubdomain()) _cells[i].insert(cell); 
+      _cells[i].insert(cell); 
     }
   }
+  
+  printf("Cell complex after coreduction: %d volumes, %d faces, %d edges and %d vertices.\n",
+         getSize(3), getSize(2), getSize(1), getSize(0));
+  
+  return;
+}
+*/
+void CellComplex::removeSubdomain(){
+  
+  for(int i = 0; i < 4; i++){
+    for(citer cit = firstCell(i); cit != lastCell(i); cit++){
+      Cell* cell = *cit;
+      if(cell->inSubdomain()) {
+        removeCell(cell);
+        cit = firstCell(i);
+      }
+    }
+        
+  }
+  return;
+}
+
+/*
+int CellComplex::coreduction(int dim){
+  
+  int count = 0;
+  
+  std::queue<Cell*> Q;
+  std::set<Cell*, Less_Cell> Qset;
+  
+  std::list<Cell*> bd_s;
+  std::list<Cell*> cbd_c;
+  
+  for(citer cit = firstCell(dim); cit != lastCell(dim); cit++){
+    
+    Cell* cell = *cit;
+    cbd_c = cell->getCoboundary();
+    enqueueCells(cbd_c, Q, Qset);
+    
+    int round = 0;
+    while( !Q.empty() ){
+      round++;
+      //printf("%d ", round);
+      
+      Cell* s = Q.front();
+      Q.pop();
+      
+      bd_s = s->getBoundary();
+      
+      if( bd_s.size() == 1 && inSameDomain(s, bd_s.front()) ){
+        removeCell(s);
+        cbd_c = bd_s.front()->getCoboundary();
+        enqueueCells(cbd_c, Q, Qset);
+        removeCell(bd_s.front());
+        cit = firstCell(dim);
+        count++;
+      }
+      else if(bd_s.empty()){
+        cbd_c = s->getCoboundary();
+        enqueueCells(cbd_c, Q, Qset);
+      }
+      
+      removeCellQset(s, Qset);
+      
+    }
+    
+    
+  }
+  return count;
+}
+*/
+void CellComplex::coreduceComplex(bool omitLowdim){
+
+  printf("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;
+  
+  removeSubdomain();
+  
+  
+  for(int dim = 0; dim < 4; dim++){
+    citer cit = firstCell(dim);
+    if(cit != lastCell(dim)){
+      Cell* cell = *cit;
+      count = count + coreduction(cell);
+    }
+  } 
+  
+  if(count == 0 && omitLowdim){
+    std::set<Cell*, Less_Cell> generatorCells;
+    
+    while (getSize(0) != 0){
+      citer cit = firstCell(0);
+      Cell* cell = *cit;
+      generatorCells.insert(cell);
+      removeCell(cell);
+      coreduction(cell);
+    }
+    
+    for(citer cit = generatorCells.begin(); cit != generatorCells.end(); cit++){
+      Cell* cell = *cit;
+      cell->clearBoundary();
+      cell->clearCoboundary();
+      _cells[0].insert(cell);
+    }
+    
+    
+  }
+  /*
+  std::set<Cell*, Less_Cell> generatorCells;
+  
+  while (getSize(0) != 0){
+    citer cit = firstCell(0);
+    Cell* cell = *cit;
+    while(!cell->inSubdomain() && cit != lastCell(0)){
+      cell = *cit;
+      cit++;
+    }
+    if(!cell->inSubdomain()) generatorCells.insert(cell);
+    removeCell(cell);
+    
+    coreduction(cell);
+  }
   */
+    
+  
   printf("Cell complex after coreduction: %d volumes, %d faces, %d edges and %d vertices.\n",
          getSize(3), getSize(2), getSize(1), getSize(0));
   
   return;
 }
 
+void CellComplex::computeBettiNumbers(){
+  
+  /*
+  removeSubdomain();
+  
+  int count = 0;
+  for(int dim = 0; dim < 4; dim++){
+    citer cit = firstCell(dim);
+    if(cit != lastCell(dim)){
+      Cell* cell = *cit;
+      count = count + coreduction(cell);
+    }
+  }
+  */
+  for(int i = 0; i < 4; i++){
+    printf("Betti number computation process: step %d of 4 \n", i+1);
+    
+            
+    while (getSize(i) != 0){
+     
+      citer cit = firstCell(i);
+      Cell* cell = *cit;
+      while(!cell->inSubdomain() && cit != lastCell(i)){
+        cell = *cit;
+        cit++;
+      }
+      if(!cell->inSubdomain()) _betti[i] = _betti[i] + 1;
+      removeCell(cell);
+      
+      coreduction(cell);
+    }
+    
+  }
+  printf("Cell complex Betti numbers: \n b0 = %d \n b1 = %d \n b2 = %d \n b3 = %d \n",
+         getBettiNumber(0), getBettiNumber(1), getBettiNumber(2), getBettiNumber(3));
+  
+  return;
+}
+
+
 
 void CellComplex::replaceCells(Cell* c1, Cell* c2, Cell* newCell, bool orMatch, bool co){
 
@@ -551,7 +802,7 @@ int CellComplex::cocombine(int dim){
   printf("Cell complex before cocombining: %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;
+  if(dim < 0 || dim > 2) return 0;
   
   std::queue<Cell*> Q;
   std::set<Cell*, Less_Cell> Qset;
@@ -662,7 +913,7 @@ int CellComplex::combine(int dim){
   return count;
 }
 
-
+/*
 void CellComplex::repairComplex(int i){
   
   printf("Cell complex before repair: %d volumes, %d faces, %d edges and %d vertices.\n",
@@ -695,7 +946,8 @@ void CellComplex::repairComplex(int i){
   
   return;
 }
-
+*/
+ 
 void CellComplex::swapSubdomain(){
   
   for(int i = 0; i < 4; i++){
@@ -828,3 +1080,12 @@ void CellComplex::printComplex(int dim){
 
 
   
+DualCellComplex::DualCellComplex(CellComplex* cellComplex){
+  
+  for(int i = 0; i < 4; i++){
+    _cells[i] = cellComplex->getCells(i);
+  }
+  
+  
+  
+}
diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h
index 9ab40aadf53569055f1cfae0350fc2344a4f847f..5eec690c5ac830d2c988829a3f7a4257f16a0800 100644
--- a/Geo/CellComplex.h
+++ b/Geo/CellComplex.h
@@ -116,7 +116,18 @@ class Cell
        if(*cell2 == *cell) { _coboundary.erase(it); break; }
      }
    }
-      
+   
+   virtual void clearBoundary() { _boundary.clear(); }
+   virtual void clearCoboundary() { _coboundary.clear(); }
+   
+   virtual void makeDualCell(){ 
+     std::list< std::pair<int, Cell*> > temp = _boundary;
+     _boundary = _coboundary;
+     _coboundary = temp;
+     _dim = 3-_dim;
+     
+   }
+   
    virtual void printBoundary() {  
      for(std::list< std::pair<int, Cell*> >::iterator it = _boundary.begin(); it != _boundary.end(); it++){
        printf("Boundary cell orientation: %d ", (*it).first);
@@ -215,7 +226,7 @@ class ZeroSimplex : public Simplex
    }
    ~ZeroSimplex(){}
    
-   int getDim() const { return 0; }
+   //int getDim() const { return 0; }
    int getNumVertices() const { return 1; }
    int getVertex(int vertex) const {return _v; }
    int getSortedVertex(int vertex) const {return _v; }
@@ -268,7 +279,7 @@ class OneSimplex : public Simplex
    
    ~OneSimplex(){}
    
-   int getDim() const { return 1; }
+   //int getDim() const { return 1; }
    int getNumVertices() const { return 2; }
    int getNumFacets() const {  return 2; }
    int getVertex(int vertex) const {return _v[vertex]; }
@@ -335,7 +346,7 @@ class TwoSimplex : public Simplex
    
    ~TwoSimplex(){}
    
-   int getDim() const { return 2; }
+   //int getDim() const { return 2; }
    int getNumVertices() const { return 3; }
    int getNumFacets() const { return 3; }
    int getVertex(int vertex) const {return _v[vertex]; }
@@ -405,7 +416,7 @@ class ThreeSimplex : public Simplex
    
    ~ThreeSimplex(){}
    
-   int getDim() const { return 3; }
+   //int getDim() const { return 3; }
    int getNumVertices() const { return 4; }
    int getNumFacets() const { return 4; }
    int getVertex(int vertex) const {return _v[vertex]; }
@@ -466,7 +477,7 @@ class Quadrangle : public Cell
    }
    ~Quadrangle(){}
    
-   int getDim() const { return 2; }
+   //int getDim() const { return 2; }
    int getNumVertices() const { return 4; }
    int getNumFacets() const { return 4; }
    int getVertex(int vertex) const {return _v[vertex]; }
@@ -650,7 +661,7 @@ class CombinedCell : public Cell{
 // A class representing a cell complex made out of a finite element mesh.
 class CellComplex
 {
- private:
+ protected:
    
    // the domain in the model which this cell complex covers
    std::vector<GEntity*> _domain;
@@ -666,7 +677,12 @@ class CellComplex
    // one for each dimension
    std::set<Cell*, Less_Cell>  _cells[4];
    
-   std::set<Cell*, Less_Cell>  _originalCells[4];
+   //std::set<Cell*, Less_Cell>  _originalCells[4];
+   
+   // Betti numbers of this cell complex (ranks of homology groups)
+   int _betti[4];
+   
+   int _dim;
    
   public:
    // iterator for the cells of same dimension
@@ -692,13 +708,40 @@ class CellComplex
        _cells[cell->getDim()].insert(cell);
      }
    }
+   /*
+   CellComplex(CellComplex* cellComplex){
+     
+     _domain = cellComplex->_domain;
+     _subdomain = cellComplex->_subdomain;
+     _boundary = cellComplex->_boundary;
+     _domainVertices = cellComplex->_domainVertices;
+     
+     for(int i = 0; i < 4; i++){
+       _betti[i] = cellComplex->_betti[i];
+       
+       for(citer cit = cellComplex->_cells[i].begin(); cit != cellComplex->_cells[i].end(); cit++){
+         Cell* cell = *cit;
+         if(i == 0) _cells[i].insert(new ZeroSimplex(*cell));
+         
+       }
+       
+       _originalCells[i] = _cells[i];
+     }
+     
+     _dim = cellComplex->_dim;
+     
+   }*/
+   
    CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain );
+   CellComplex(){}
    virtual ~CellComplex(){}
-   
+
    
    // get the number of certain dimensional cells
    virtual int getSize(int dim){ return _cells[dim].size(); }
    
+   virtual int getDim() {return _dim; } 
+   
    virtual std::set<Cell*, Less_Cell> getCells(int dim){ return _cells[dim]; }
       
    // iterators to the first and last cells of certain dimension
@@ -706,8 +749,8 @@ class CellComplex
    virtual citer lastCell(int dim) {return _cells[dim].end(); }
   
    // find a cell in this cell complex
-   virtual std::set<Cell*, Less_Cell>::iterator findCell(int dim, std::vector<int>& vertices, bool original=false);
-   virtual std::set<Cell*, Less_Cell>::iterator findCell(int dim, int vertex, int dummy=0);
+   //virtual std::set<Cell*, Less_Cell>::iterator findCell(int dim, std::vector<int>& vertices, bool original=false);
+   //virtual std::set<Cell*, Less_Cell>::iterator findCell(int dim, int vertex, int dummy=0);
    
    // kappa for two cells of this cell complex
    // implementation will vary depending on cell type
@@ -726,27 +769,33 @@ class CellComplex
    
    // coreduction of this cell complex
    // removes corection pairs of cells of dimension dim and dim+1
-   virtual int coreduction(int dim);
+   //virtual int coreduction(int dim);
+   //virtual int coreduction();
    
    // stores removed cells
    
    // reduction of this cell complex
    // removes reduction pairs of cell of dimension dim and dim-1
    virtual int reduction(int dim);
+   //virtual int reduction(Cell* generator);
    
    // useful functions for (co)reduction of cell complex
-   virtual void reduceComplex();
-   // coreduction up to generators of dimension generatorDim
-   virtual void coreduceComplex(int generatorDim=3);
+   virtual void reduceComplex(bool omitHighdim = false);
+   virtual void coreduceComplex(bool omitlowDim = false);
+   
+   //virtual void coreduceComplex(int generatorDim);
+   //virtual void coreduceComplex();
    
    // queued coreduction presented in Mrozek's paper
    // slower, but produces cleaner result
-   virtual int coreductionMrozek(Cell* generator);
+   virtual int coreduction(Cell* generator);
       
    // add every volume, face and edge its missing boundary cells
-   virtual void repairComplex(int i=3);
+   //virtual void repairComplex(int i=3);
    // change non-subdomain cells to be in subdomain, subdomain cells to not to be in subdomain
    virtual void swapSubdomain();
+   virtual void removeSubdomain();
+   
    
    // print the vertices of cells of certain dimension
    virtual void printComplex(int dim);
@@ -757,6 +806,36 @@ class CellComplex
    virtual int combine(int dim);
    virtual int cocombine(int dim);
    
+   virtual void computeBettiNumbers();
+   virtual int getBettiNumber(int i) { if(i > -1 && i < 4) return _betti[i]; else return 0; }
+   
+   virtual 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();
+       }
+     }
+   }
+   
+};
+
+
+class DualCellComplex : public CellComplex
+{
+   
+  public:
+   
+   DualCellComplex(CellComplex* cellComplex);
+   ~DualCellComplex(){}
+   
 };
 
 #endif
diff --git a/Geo/ChainComplex.cpp b/Geo/ChainComplex.cpp
index 88d02b75d2b2d90fd9c8d92a75e978465d114229..365599a63012258e51505a4e7c7f1d9fab807292 100644
--- a/Geo/ChainComplex.cpp
+++ b/Geo/ChainComplex.cpp
@@ -11,17 +11,21 @@
 
 ChainComplex::ChainComplex(CellComplex* cellComplex){
   
-  _dim = 0;
-  _HMatrix[0] = NULL;
-  _kerH[0] = NULL;
-  _codH[0] = NULL;
-  _JMatrix[0] = NULL;
-  _QMatrix[0] = NULL;
-  _Hbasis[0] = NULL;
-  
-  for(int dim = 1; dim < 4; dim++){
+  _dim = cellComplex->getDim();
+  _cellComplex = cellComplex;
+  
+  _HMatrix[4] = NULL;
+  _kerH[4] = NULL;
+  _codH[4] = NULL;
+  _JMatrix[4] = NULL;
+  _QMatrix[4] = NULL;
+  _Hbasis[4] = NULL;
+  
+    
+  for(int dim = 0; dim < 4; dim++){
     unsigned int cols = cellComplex->getSize(dim);
-    unsigned int rows =  cellComplex->getSize(dim-1);
+    unsigned int rows = 0;
+    if(dim > 0) rows = cellComplex->getSize(dim-1);
   
     
     int index = 1;
@@ -36,17 +40,18 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){
       }
     }
     index = 1;
-    for(std::set<Cell*, Less_Cell>::iterator cit = cellComplex->firstCell(dim-1); cit != cellComplex->lastCell(dim-1); cit++){
-      Cell* cell = *cit;
-      cell->setIndex(index);
-      index++;
-      if(cell->inSubdomain()){
-        index--;
-        rows--;
+    if(dim > 0){
+      for(std::set<Cell*, Less_Cell>::iterator cit = cellComplex->firstCell(dim-1); cit != cellComplex->lastCell(dim-1); cit++){
+        Cell* cell = *cit;
+        cell->setIndex(index);
+        index++;
+        if(cell->inSubdomain()){
+          index--;
+          rows--;
+        }
       }
     }
     
-    
     if( cols == 0 ){
       //_HMatrix[dim] = create_gmp_matrix_zero(rows, 1);
       _HMatrix[dim] = NULL;
@@ -62,6 +67,7 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){
       mpz_init(elem);
       
       _HMatrix[dim] = create_gmp_matrix_zero(rows, cols);
+      //printMatrix(_HMatrix[dim]);
       for( std::set<Cell*, Less_Cell>::iterator cit = cellComplex->firstCell(dim); cit != cellComplex->lastCell(dim); cit++){
         Cell* cell = *cit;
         if(!cell->inSubdomain()){
@@ -70,6 +76,7 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){
             Cell* bdCell = (*it).second;
             if(!bdCell->inSubdomain()){
               int old_elem = 0;
+              //printf("kaka1: %d, kaka2: %d \n", bdCell->getIndex(), cell->getIndex());
               gmp_matrix_get_elem(elem, bdCell->getIndex(), cell->getIndex(), _HMatrix[dim]);
               old_elem = mpz_get_si(elem);
               mpz_set_si(elem, old_elem + (*it).first);
@@ -126,8 +133,6 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){
     _QMatrix[dim] = NULL;
     _Hbasis[dim] = NULL; 
     
-    if(cellComplex->getSize(dim) != 0) _dim = dim;
-    
   }
   
   return;
@@ -254,7 +259,7 @@ void ChainComplex::Inclusion(int lowDim, int highDim){
 
 void ChainComplex::Quotient(int dim){
   
-  if(dim < 0 || dim > 3 || _JMatrix[dim] == NULL) return;
+  if(dim < 0 || dim > 4 || _JMatrix[dim] == NULL) return;
   
   gmp_matrix* JMatrix = copy_gmp_matrix(_JMatrix[dim], 1, 1,
                                         gmp_matrix_rows(_JMatrix[dim]), gmp_matrix_cols(_JMatrix[dim]));
@@ -297,35 +302,43 @@ void ChainComplex::computeHomology(bool dual){
   
   int lowDim = 0;
   int highDim = 0;
+  int setDim = 0;
+  
   
-  for(int i=0; i < 4; i++){
+  for(int i=-1; i < 4; i++){
     
     if(dual){
       lowDim = getDim()+1-i; 
       highDim = getDim()+1-(i+1);
+      setDim = highDim;
       //KerCod(lowDim);
     }
     else{
       lowDim = i;
       highDim = i+1;
+      setDim = lowDim;
       //KerCod(highDim);
     }
     
-    printf("Homology computation process: step %d of 4 \n", i+1 );
+    printf("Homology computation process: step %d of 4 \n", i+1);
     
     KerCod(highDim);
     
     // 1) no edges, but zero cells
-    if(lowDim == 0 &&  gmp_matrix_cols(getHMatrix(lowDim)) > 0 && getHMatrix(highDim) == NULL) {
-      setHbasis( lowDim, create_gmp_matrix_identity(gmp_matrix_cols(getHMatrix(lowDim))) );
-    }    
+    if(lowDim == 0 && !dual &&  gmp_matrix_cols(getHMatrix(lowDim)) > 0 && getHMatrix(highDim) == NULL) {
+      setHbasis( setDim, create_gmp_matrix_identity(gmp_matrix_cols(getHMatrix(lowDim))) );
+    }
+    else if(highDim == 0 && dual &&  gmp_matrix_rows(getHMatrix(highDim)) > 0 && getHMatrix(lowDim) == NULL) {
+      setHbasis( setDim, create_gmp_matrix_identity(gmp_matrix_rows(getHMatrix(highDim))) );
+    }
+    
     // 2) this dimension is empty
     else if(getHMatrix(lowDim) == NULL && getHMatrix(highDim) == NULL){
-      setHbasis(lowDim, NULL);
+      setHbasis(setDim, NULL);
     }
     // 3) No higher dimension cells -> none of the cycles are boundaries
     else if(getHMatrix(highDim) == NULL){
-      setHbasis( lowDim, copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
+      setHbasis( setDim, copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
                                          gmp_matrix_rows(getKerHMatrix(lowDim)), 
                                          gmp_matrix_cols(getKerHMatrix(lowDim))) );
     }
@@ -344,19 +357,19 @@ void ChainComplex::computeHomology(bool dual){
       Quotient(lowDim);
       
       if(getCodHMatrix(highDim) == NULL){
-        setHbasis(lowDim, copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
+        setHbasis(setDim, copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1,
                                           gmp_matrix_rows(getKerHMatrix(lowDim)), 
                                           gmp_matrix_cols(getKerHMatrix(lowDim))) );
       }  
       else if(getJMatrix(lowDim) == NULL || getQMatrix(lowDim) == NULL){
-        setHbasis(lowDim, NULL);
+        setHbasis(setDim, NULL);
       } 
       else{
-        setHbasis(lowDim, copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1, 
+        setHbasis(setDim, copy_gmp_matrix(getKerHMatrix(lowDim), 1, 1, 
                                           gmp_matrix_rows(getKerHMatrix(lowDim)), 
                                           gmp_matrix_cols(getKerHMatrix(lowDim))) );
         
-        gmp_matrix_right_mult(getHbasis(lowDim), getQMatrix(lowDim));
+        gmp_matrix_right_mult(getHbasis(setDim), getQMatrix(lowDim));
       } 
       
     } 
@@ -401,7 +414,7 @@ std::vector<int> ChainComplex::getCoeffVector(int dim, int chainNumber){
   
   std::vector<int> coeffVector;
   
-  if(dim < 0 || dim > 3) return coeffVector;
+  if(dim < 0 || dim > 4) return coeffVector;
   if(_Hbasis[dim] == NULL || gmp_matrix_cols(_Hbasis[dim]) < chainNumber) return coeffVector;
   
   int rows = gmp_matrix_rows(_Hbasis[dim]);
@@ -435,6 +448,7 @@ Chain::Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, CellComp
       if(coeffs.at(i) != 0) _cells.push_back( std::make_pair(cell, coeffs.at(i)) );
       i++;
     }
+    
   }
   
   _name = name;
diff --git a/Geo/ChainComplex.h b/Geo/ChainComplex.h
index adc5450660cee15d46c820ecc57e583997d06164..b8a5e2ec577dde443fd530dd2c68492dd33e94fa 100644
--- a/Geo/ChainComplex.h
+++ b/Geo/ChainComplex.h
@@ -36,28 +36,29 @@ class ChainComplex{
   private:
    // boundary operator matrices for this chain complex
    // h_k: C_k -> C_(k-1)
-   gmp_matrix* _HMatrix[4];
+   gmp_matrix* _HMatrix[5];
    
    // Basis matrices for the kernels and codomains of the boundary operator matrices
-   gmp_matrix* _kerH[4];
-   gmp_matrix* _codH[4];
+   gmp_matrix* _kerH[5];
+   gmp_matrix* _codH[5];
    
-   gmp_matrix* _JMatrix[4];
-   gmp_matrix* _QMatrix[4];
-   std::vector<long int> _torsion[4];
+   gmp_matrix* _JMatrix[5];
+   gmp_matrix* _QMatrix[5];
+   std::vector<long int> _torsion[5];
    
    // bases for homology groups
-   gmp_matrix* _Hbasis[4];
+   gmp_matrix* _Hbasis[5];
    
    int _dim;
+   CellComplex* _cellComplex;
    
    // set the matrices
-   virtual void setHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 4) _HMatrix[dim] = matrix;}
-   virtual void setKerHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 4)  _kerH[dim] = matrix;}
-   virtual void setCodHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 4)  _codH[dim] = matrix;}
-   virtual void setJMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 4)  _JMatrix[dim] = matrix;}
-   virtual void setQMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 4)  _QMatrix[dim] = matrix;}
-   virtual void setHbasis(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 4) _Hbasis[dim] = matrix;}
+   virtual void setHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _HMatrix[dim] = matrix;}
+   virtual void setKerHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5)  _kerH[dim] = matrix;}
+   virtual void setCodHMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5)  _codH[dim] = matrix;}
+   virtual void setJMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5)  _JMatrix[dim] = matrix;}
+   virtual void setQMatrix(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5)  _QMatrix[dim] = matrix;}
+   virtual void setHbasis(int dim, gmp_matrix* matrix) { if(dim > -1 && dim < 5) _Hbasis[dim] = matrix;}
    
    
    
@@ -66,7 +67,7 @@ class ChainComplex{
    ChainComplex(CellComplex* cellComplex);
       
    ChainComplex(){
-     for(int i = 0; i < 4; i++){
+     for(int i = 0; i < 5; i++){
        _HMatrix[i] = create_gmp_matrix_zero(1,1);
        _kerH[i] = NULL;
        _codH[i] = NULL;
@@ -81,12 +82,12 @@ class ChainComplex{
    virtual int getDim() { return _dim; }
    
    // get the boundary operator matrix dim->dim-1
-   virtual gmp_matrix* getHMatrix(int dim) { if(dim > -1 && dim < 4) return _HMatrix[dim]; else return NULL;}
-   virtual gmp_matrix* getKerHMatrix(int dim) { if(dim > -1 && dim < 4) return _kerH[dim]; else return NULL;}
-   virtual gmp_matrix* getCodHMatrix(int dim) { if(dim > -1 && dim < 4) return _codH[dim]; else return NULL;}
-   virtual gmp_matrix* getJMatrix(int dim) { if(dim > -1 && dim < 4) return _JMatrix[dim]; else return NULL;}
-   virtual gmp_matrix* getQMatrix(int dim) { if(dim > -1 && dim < 4) return _QMatrix[dim]; else return NULL;}
-   virtual gmp_matrix* getHbasis(int dim) { if(dim > -1 && dim < 4) return _Hbasis[dim]; else return NULL;}
+   virtual gmp_matrix* getHMatrix(int dim) { if(dim > -1 && dim < 5) return _HMatrix[dim]; else return NULL;}
+   virtual gmp_matrix* getKerHMatrix(int dim) { if(dim > -1 && dim < 5) return _kerH[dim]; else return NULL;}
+   virtual gmp_matrix* getCodHMatrix(int dim) { if(dim > -1 && dim < 5) return _codH[dim]; else return NULL;}
+   virtual gmp_matrix* getJMatrix(int dim) { if(dim > -1 && dim < 5) return _JMatrix[dim]; else return NULL;}
+   virtual gmp_matrix* getQMatrix(int dim) { if(dim > -1 && dim < 5) return _QMatrix[dim]; else return NULL;}
+   virtual gmp_matrix* getHbasis(int dim) { if(dim > -1 && dim < 5) return _Hbasis[dim]; else return NULL;}
    
    // Compute basis for kernel and codomain of boundary operator matrix of dimension dim (ie. ker(h_dim) and cod(h_dim) )
    virtual void KerCod(int dim);
@@ -98,14 +99,14 @@ class ChainComplex{
    virtual void Quotient(int dim);
    
    // transpose the boundary operator matrices, these are boundary operator matrices for the dual mesh
-   virtual void transposeHMatrices() { for(int i = 0; i < 4; i++) gmp_matrix_transp(_HMatrix[i]); }
-   virtual void transposeHMatrix(int dim) { if(dim > -1 && dim < 4) gmp_matrix_transp(_HMatrix[dim]); }
+   virtual void transposeHMatrices() { for(int i = 0; i < 5; i++) gmp_matrix_transp(_HMatrix[i]); }
+   virtual void transposeHMatrix(int dim) { if(dim > -1 && dim < 5) gmp_matrix_transp(_HMatrix[dim]); }
    
    // Compute bases for the homology groups of this chain complex 
    virtual void computeHomology(bool dual=false);
    
    virtual std::vector<int> getCoeffVector(int dim, int chainNumber);
-   virtual int getBasisSize(int dim) {  if(dim > -1 && dim < 4) return gmp_matrix_cols(_Hbasis[dim]); else return 0; } 
+   virtual int getBasisSize(int dim) {  if(dim > -1 && dim < 5) return gmp_matrix_cols(_Hbasis[dim]); else return 0; } 
    
    virtual int printMatrix(gmp_matrix* matrix){ 
      printf("%d rows and %d columns\n", gmp_matrix_rows(matrix), gmp_matrix_cols(matrix)); 
diff --git a/utils/misc/celldriver.cpp b/utils/misc/celldriver.cpp
index 5bc4920a9ad710ffbfdcad3786a084cd8ef9e92e..4fe82d739b793405b77af7a7f45865dcbde804a7 100755
--- a/utils/misc/celldriver.cpp
+++ b/utils/misc/celldriver.cpp
@@ -66,7 +66,7 @@ int main(int argc, char **argv)
          complex->getSize(3), complex->getSize(2), complex->getSize(1), complex->getSize(0));  
   
   // reduce the complex in order to ease homology computation
-  complex->reduceComplex();
+  complex->reduceComplex(true);
   
   // perform series of cell combinatios in order to further ease homology computation
   complex->combine(3);
@@ -104,9 +104,10 @@ int main(int argc, char **argv)
   CellComplex* complex2 = new CellComplex(domain, subdomain);
   
   // reduce the complex by coreduction, this removes all vertices, hence 0 as an argument 
-  complex2->coreduceComplex(0);
+  complex2->coreduceComplex(true);
   
   // perform series of "dual complex" cell combinations in order to ease homology computation
+  complex2->cocombine(0);
   complex2->cocombine(1);
   complex2->cocombine(2);
   
@@ -127,10 +128,10 @@ int main(int argc, char **argv)
       std::string generator;
       std::string dimension;
       convert(i, generator);
-      convert(3-(j-1), dimension);
+      convert(3-j, dimension);
 
       std::string name = dimension + "D Dual cut " + generator;
-      Chain* chain = new Chain(complex2->getCells(j-1), dualChains->getCoeffVector(j,i), complex2, name);
+      Chain* chain = new Chain(complex2->getCells(j), dualChains->getCoeffVector(j,i), complex2, name);
                 chain->writeChainMSH("chains.msh");
       delete chain;
     }