diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp
index a0fe39fb5f37c85d9353fa7c1abec5847da6af01..3338006ed7ac58cfa35cf3255fa228502a2efd83 100644
--- a/Geo/CellComplex.cpp
+++ b/Geo/CellComplex.cpp
@@ -169,8 +169,7 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){
       else if(type == MSH_QUA_4 || type == MSH_QUA_8 || type == MSH_QUA_9){
         cell = new CQuadrangle(vertices, tag, subdomain, boundary);
         _simplicial = false;
-      }
-      /*
+      }/* FIXME: reduction doesn't work for these      
       else if(type == MSH_HEX_8 || type == MSH_HEX_27 || type == MSH_HEX_20){
         cell = new CHexahedron(vertices, tag, subdomain, boundary);
         _simplicial = false;
@@ -215,7 +214,8 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){
           delete newCell;
           Cell* oldCell = *(insertInfo.first);
           if(!subdomain && !boundary){
-            int ori = cell->kappa(oldCell);
+            //int ori = cell->kappa(oldCell);
+            int ori = cell->getFacetOri(oldCell);
             oldCell->addCoboundaryCell( ori, cell );
             oldCell->addOrgCbdCell( ori, cell );
             cell->addBoundaryCell( ori, oldCell);
@@ -223,7 +223,8 @@ void CellComplex::insert_cells(bool subdomain, bool boundary){
           }
         }
         else if(!subdomain && !boundary) {
-          int ori = cell->kappa(newCell);
+          //int ori = cell->kappa(newCell);
+          int ori = cell->getFacetOri(vertices);
           cell->addBoundaryCell( ori, newCell );
           cell->addOrgBdCell( ori, newCell );
           newCell->addCoboundaryCell( ori, cell);
@@ -256,7 +257,7 @@ int Simplex::kappa(Cell* tau) const{
   return value;  
 }
 */
-
+/*
 int Cell::kappa(Cell* tau) const{
   for(int i=0; i < tau->getNumVertices(); i++){
     if( !(this->hasVertex(tau->getVertex(i)->getNum())) ) return 0;
@@ -306,8 +307,7 @@ int OneSimplex::kappa(Cell* tau) const{
   if(tau->getVertex(0) == this->getVertex(0)) return -1;
   else return 1;
     
-}
-
+}*/
 
 void CellComplex::removeCell(Cell* cell, bool other){
   
diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h
index da55e8a68afdacf0c31cbcb3f66f966a04ccb635..c5a901e6c7c8382ddde06eb8748a43d0ce74f54c 100644
--- a/Geo/CellComplex.h
+++ b/Geo/CellComplex.h
@@ -99,7 +99,7 @@ class Cell
    virtual void setPartition(int num){}
    virtual void setImmune(bool immune) { _immune = immune; };
    virtual bool getImmune() const { return _immune; };
-   
+
    // get the number of vertices this cell has
    virtual int getNumVertices() const = 0;
    virtual MVertex* getVertex(int vertex) const = 0; //{return _vertices.at(vertex);}
@@ -295,7 +295,10 @@ class Cell
    
    virtual int getNumFacets() const { return 0; }
    virtual void getFacetVertices(const int num, std::vector<MVertex*> &v) const {};
-   
+   // get boundary cell orientation
+   virtual int getFacetOri(Cell* cell) { std::vector<MVertex*> v = cell->getVertexVector(); return getFacetOri(v); } 
+   virtual int getFacetOri(std::vector<MVertex*> &v) { return 0; }   
+
    virtual bool isCombined() { return _combined; }
    virtual std::list< std::pair<int, Cell*> > getCells() {  std::list< std::pair<int, Cell*> >cells; cells.push_back( std::make_pair(1, this)); return cells; }
    virtual int getNumCells() {return 1;}
@@ -326,7 +329,7 @@ class Cell
    }
    
    // checks whether lower dimensional simplex tau is on the boundary of this cell
-   virtual int kappa(Cell* tau) const;
+   //virtual int kappa(Cell* tau) const;
    
    virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false,  int num=0, int elementary=1, int physical=1, int parentNum=0) {}
 };
@@ -416,8 +419,14 @@ class OneSimplex : public Simplex, public MLine
      v.resize(1);
      v[0] = _v[num];
    }
-   
-   int kappa(Cell* tau) const;
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 1) return 0;
+     else if(v[0] == _v[0]) return -1;
+     else if(v[0] == _v[1]) return 1;
+     else return 0;
+   }
+
+   //int kappa(Cell* tau) const;
    
    void printCell() const { printf("Cell dimension: %d, Vertices: %d %d, in subdomain: %d \n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _inSubdomain); }
    
@@ -466,7 +475,15 @@ class TwoSimplex : public Simplex, public MTriangle
    void getFacetVertices(const int num, std::vector<MVertex*> &v) const {
      MTriangle::getEdgeVertices(num, v);
    }
-   
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 2) return 0;
+     MEdge facet = MEdge(v[0], v[1]);
+     int ithFacet = 0;
+     int sign = 0;
+     MTriangle::getEdgeInfo(facet, ithFacet, sign);
+     return sign;
+   }    
+
    void printCell() const { printf("Cell dimension: %d, Vertices: %d %d %d, in subdomain: %d\n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _v[2]->getNum(), _inSubdomain); }
 };
 
@@ -514,6 +531,14 @@ class CQuadrangle : public Cell, public MQuadrangle
    void getFacetVertices(const int num, std::vector<MVertex*> &v) const {
      MQuadrangle::getEdgeVertices(num, v);
    }
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 2) return 0;
+     MEdge facet = MEdge(v[0], v[1]);
+     int ithFacet = 0;
+     int sign = 0;
+     MQuadrangle::getEdgeInfo(facet, ithFacet, sign);
+     return sign;
+   }  
    
    void printCell() const { printf("Cell dimension: %d, Vertices: %d %d %d %d, in subdomain: %d\n", 
                                     getDim(), _v[0]->getNum(), _v[1]->getNum(), _v[2]->getNum(), 
@@ -562,7 +587,16 @@ class ThreeSimplex : public Simplex, public MTetrahedron
    void getFacetVertices(const int num, std::vector<MVertex*> &v) const {
      MTetrahedron::getFaceVertices(num, v);
    }
-   
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 3) return 0;
+     MFace facet = MFace(v);
+     int ithFacet = 0;
+     int sign = 0;
+     int rot = 0;
+     MTetrahedron::getFaceInfo(facet, ithFacet, sign, rot);
+     return sign;
+   }
+
    virtual void printCell() const { printf("Cell dimension: %d, Vertices: %d %d %d %d, in subdomain: %d \n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _v[2]->getNum(), _v[3]->getNum(), _inSubdomain); }
 };
 
@@ -612,6 +646,15 @@ class CHexahedron : public Cell, public MHexahedron
    void getFacetVertices(const int num, std::vector<MVertex*> &v) const {
      MHexahedron::getFaceVertices(num, v);
    }
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 4) return 0;
+     MFace facet = MFace(v);
+     int ithFacet = 0;
+     int sign = 0;
+     int rot = 0;
+     MHexahedron::getFaceInfo(facet, ithFacet, sign, rot);
+     return sign;
+   }
    
    virtual void printCell() const { printf("Cell dimension: %d, Vertices: %d %d %d %d %d %d %d %d, in subdomain: %d \n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _v[2]->getNum(), _v[3]->getNum(), _v[4]->getNum(), _v[5]->getNum(), _v[6]->getNum(), _v[7]->getNum(), _inSubdomain); }
 };
@@ -661,6 +704,15 @@ class CPrism : public Cell, public MPrism
    void getFacetVertices(const int num, std::vector<MVertex*> &v) const {
      MPrism::getFaceVertices(num, v);
    }
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 4 && v.size() != 3) return 0;
+     MFace facet = MFace(v);
+     int ithFacet = 0;
+     int sign = 0;
+     int rot = 0;
+     MPrism::getFaceInfo(facet, ithFacet, sign, rot);
+     return sign;
+   }
    
    virtual void printCell() const { printf("Cell dimension: %d, Vertices: %d %d %d %d %d %d, in subdomain: %d \n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _v[2]->getNum(), _v[3]->getNum(), _v[4]->getNum(), _v[5]->getNum(),  _inSubdomain); }
 };
@@ -709,6 +761,15 @@ class CPyramid : public Cell, public MPyramid
    void getFacetVertices(const int num, std::vector<MVertex*> &v) const {
      MPyramid::getFaceVertices(num, v);
    }
+   int getFacetOri(std::vector<MVertex*> &v){
+     if(v.size() != 4 && v.size() != 3) return 0;
+     MFace facet = MFace(v);
+     int ithFacet = 0;
+     int sign = 0;
+     int rot = 0;
+     MPyramid::getFaceInfo(facet, ithFacet, sign, rot);
+     return sign;
+   }
    
    virtual void printCell() const { printf("Cell dimension: %d, Vertices: %d %d %d %d %d, in subdomain: %d \n", getDim(), _v[0]->getNum(), _v[1]->getNum(), _v[2]->getNum(), _v[3]->getNum(), _v[4]->getNum(), _inSubdomain); }
 };
@@ -841,7 +902,7 @@ class CombinedCell : public Cell{
    int getSortedVertex(int vertex) const { return _vs.at(vertex); }
    std::vector<MVertex*> getVertexVector() const { return _v; }
    
-   int kappa(Cell* tau) const { return 0; }
+   //int kappa(Cell* tau) const { return 0; }
    
    // true if this cell has given vertex
    bool hasVertex(int vertex) const {
@@ -1030,7 +1091,7 @@ class CellComplex
 
    // kappa for two cells of this cell complex
    // implementation will vary depending on cell type
-   inline int kappa(Cell* sigma, Cell* tau) const { return sigma->kappa(tau); }
+   //inline int kappa(Cell* sigma, Cell* tau) const { return sigma->kappa(tau); }
    
    
    // check whether two cells both belong to subdomain or if neither one does
diff --git a/Geo/ChainComplex.cpp b/Geo/ChainComplex.cpp
index 53d0dce5e9e8f5552505669f1b02442270dc9097..42ee1ee0d18d8afc2e958b70e43a18ce03fe119f 100644
--- a/Geo/ChainComplex.cpp
+++ b/Geo/ChainComplex.cpp
@@ -471,7 +471,6 @@ Chain::Chain(std::set<Cell*, Less_Cell> cells, std::vector<int> coeffs, CellComp
           int coeff = (*it).first;
           _cells.insert( std::make_pair(subCell, coeffs.at(i)*coeff));
         }
-        //_cells.push_back( std::make_pair(cell, coeffs.at(i)) );
       }
       i++;
     }
@@ -497,27 +496,23 @@ bool Chain::deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell*
       cc.push_back(getCoeff(c));
       bc.push_back((*cit).second);
     }
+    removeCell(c);
   }
-  
-  // FIXME: orientations don't get right on 2-chains with bending or subdomain cells (disabled for now).
-  
-  bool flip = false;
-  if(cc[0] != bc[0]) flip = true; 
+  if(cc.empty()) return false;
+  int inout = cc[0]*bc[0];
   for(int i = 0; i < cc.size(); i++){
     //printf("cc: %d, bc: %d \n", cc.at(i), bc.at(i));
-    if(flip && cc[i] == bc[i]) return false;
-    if(!flip && cc[i] != bc[i]) return false; 
+    if(cc[i]*bc[i] != inout) printf("Error: Chain smoothening orientation mismatch! \n");
   }
   
-  for(citer cit = cellsInChain.begin(); cit != cellsInChain.end(); cit++) removeCell((*cit).first);
+  //for(citer cit = cellsInChain.begin(); cit != cellsInChain.end(); cit++) removeCell((*cit).first);
   
   int n = 1;
   for(citer cit = cellsNotInChain.begin(); cit != cellsNotInChain.end(); cit++){
     Cell* c = (*cit).first;
     if(n == 2) c->setImmune(true);
     else c->setImmune(false);
-    int coeff = -1*(*cit).second;
-    if(flip) coeff = coeff*-1;
+    int coeff = -1*inout*(*cit).second;
     addCell(c, coeff);
     //c->printCell();
     n++;
@@ -527,17 +522,17 @@ bool Chain::deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell*
   return true;
 }
 
-bool Chain::deformChain(std::pair<Cell*, int> cell, bool straighten, bool bend){
+bool Chain::deformChain(std::pair<Cell*, int> cell, bool bend){
   
   Cell* c1 = cell.first;
-  
   std::map<Cell*, int, Less_Cell> c1Cbd = c1->getOrgCbd();
   for(citer cit = c1Cbd.begin(); cit != c1Cbd.end(); cit++){
     
     std::map<Cell*, int, Less_Cell> cellsInChain;
     std::map<Cell*, int, Less_Cell> cellsNotInChain;
-    
     Cell* c1CbdCell = (*cit).first;
+    //c1CbdCell->printCell();
+    //c1CbdCell->printOrgBd();
     std::map<Cell*, int, Less_Cell> c1CbdBd = c1CbdCell->getOrgBd();
     for(citer cit2 = c1CbdBd.begin(); cit2 != c1CbdBd.end(); cit2++){
       Cell* c1CbdBdCell = (*cit2).first;
@@ -552,7 +547,7 @@ bool Chain::deformChain(std::pair<Cell*, int> cell, bool straighten, bool bend){
       Cell* c = (*cit2).first;
       int coeff = getCoeff(c);
       if(c->getImmune()) next = true;
-      if(/* FIXME: bend && */c->inSubdomain()) next = true;
+      if(c->inSubdomain()) bend = false;
       if(coeff > 1 || coeff < -1) next = true; 
     }
     
@@ -563,18 +558,19 @@ bool Chain::deformChain(std::pair<Cell*, int> cell, bool straighten, bool bend){
     
     if(next) continue;
     
+    if(getDim() != 2) bend = false;
+    
     //printf("dim: %d, in chain: %d, not in chain: %d \n", getDim(), cellsInChain.size(), cellsNotInChain.size());
     
-    if( (getDim() == 1 && cellsInChain.size() == 2 && cellsNotInChain.size() == 1 && straighten) ||
-        (getDim() == 2 && cellsInChain.size() == 3 && cellsNotInChain.size() == 1 && straighten)){
+    if( (getDim() == 1 && cellsInChain.size() == 2 && cellsNotInChain.size() == 1) ||
+        (getDim() == 2 && cellsInChain.size() == 3 && cellsNotInChain.size() == 1)){
       //printf("straighten \n");
       return deform(cellsInChain, cellsNotInChain);
     }
     else if ( (getDim() == 1 && cellsInChain.size() == 1 && cellsNotInChain.size() == 2 && bend) ||
               (getDim() == 2 && cellsInChain.size() == 2 && cellsNotInChain.size() == 2 && bend)){
       //printf("bend \n");
-      //FIXME: return deform(cellsInChain, cellsNotInChain);
-      return false;
+      return deform(cellsInChain, cellsNotInChain);
     }
     else if ((getDim() == 1 && cellsInChain.size() == 3 && cellsNotInChain.size() == 0) ||
              (getDim() == 2 && cellsInChain.size() == 4 && cellsNotInChain.size() == 0)){
@@ -587,6 +583,7 @@ bool Chain::deformChain(std::pair<Cell*, int> cell, bool straighten, bool bend){
 }
 
 void Chain::smoothenChain(){
+
   if(!_cellComplex->simplicial()) return;
   
   int start = getSize();
@@ -596,8 +593,8 @@ void Chain::smoothenChain(){
   for(int i = 0; i < 20; i++){
     int size = getSize();
     for(citer cit = _cells.begin(); cit != _cells.end(); cit++){
-      if(!deformChain(*cit, true, false) && getDim() == 2) deformChain(*cit, false, true);
-      deformChain(*cit, false, false);
+      deformChain(*cit, true);
+      deformChain(*cit, false);
     }
     deImmuneCells();
     eraseNullCells();
@@ -607,7 +604,7 @@ void Chain::smoothenChain(){
   }
   
   deImmuneCells();
-  for(citer cit = _cells.begin(); cit != _cells.end(); cit++) deformChain(*cit, true, false);
+  for(citer cit = _cells.begin(); cit != _cells.end(); cit++) deformChain(*cit, false);
   
   eraseNullCells();
   double t2 = Cpu();
diff --git a/Geo/ChainComplex.h b/Geo/ChainComplex.h
index 1b34844e577d62f2f60feaf900f918c5ba38a17a..3a474b3a2ca0a4463419f37a143030031b819980 100644
--- a/Geo/ChainComplex.h
+++ b/Geo/ChainComplex.h
@@ -152,7 +152,7 @@ class Chain{
    
    
    bool deform(std::map<Cell*, int, Less_Cell> &cellsInChain, std::map<Cell*, int, Less_Cell> &cellsNotInChain);
-   bool deformChain(std::pair<Cell*, int> cell, bool straighten, bool bend);   
+   bool deformChain(std::pair<Cell*, int> cell, bool bend);
    
    
   public:
diff --git a/Geo/MHexahedron.cpp b/Geo/MHexahedron.cpp
index 8c53b9438c6ceac03466a2461b54c74f52b9577c..88adfc2c08038ed596dd4b2fc8757e841a3556a7 100644
--- a/Geo/MHexahedron.cpp
+++ b/Geo/MHexahedron.cpp
@@ -26,3 +26,38 @@ void MHexahedron::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
   *npts = getNGQHPts(pOrder);
   *pts = getGQHPts(pOrder);
 }
+
+void MHexahedron::getFaceInfo (const MFace & face, int &ithFace, int &sign, int &rot)const{
+  for (ithFace=0;ithFace<6;ithFace++){
+    MVertex *v0 = _v[faces_hexa(ithFace,0)];
+    MVertex *v1 = _v[faces_hexa(ithFace,1)];
+    MVertex *v2 = _v[faces_hexa(ithFace,2)];
+    MVertex *v3 = _v[faces_hexa(ithFace,3)];
+
+    if (v0 == face.getVertex(0) && v1 == face.getVertex(1) && v2 == face.getVertex(2) && v3 == face.getVertex(3)){
+      sign = 1; rot = 0; return;
+    }
+    if (v0 == face.getVertex(1) && v1 == face.getVertex(2) && v3 == face.getVertex(3) && v2 == face.getVertex(0)){
+      sign = 1; rot = 1; return;
+    }
+    if (v0 == face.getVertex(2) && v3 == face.getVertex(3)  && v1 == face.getVertex(0) && v2 == face.getVertex(1)){
+      sign = 1; rot = 2; return;
+    }
+    if (v0 == face.getVertex(3) && v3 == face.getVertex(0)  && v1 == face.getVertex(1) && v2 == face.getVertex(2)){
+      sign = 1; rot = 3; return;
+    }
+    if (v0 == face.getVertex(0) && v1 == face.getVertex(3) && v2 == face.getVertex(2) && v3 == face.getVertex(1)){
+      sign = -1; rot = 0; return;
+    }
+    if (v0 == face.getVertex(3) && v1 == face.getVertex(2) && v2 == face.getVertex(1) && v3 == face.getVertex(0)){
+      sign = -1; rot = 1; return;
+    }
+    if (v0 == face.getVertex(2) && v1 == face.getVertex(1) && v2 == face.getVertex(0) && v3 == face.getVertex(3)){
+      sign = -1; rot = 2; return;
+    }
+    if (v0 == face.getVertex(1) && v1 == face.getVertex(0) && v2 == face.getVertex(3) && v3 == face.getVertex(2)){
+      sign = -1; rot = 3; return;
+    }
+  }
+  throw;
+}
diff --git a/Geo/MHexahedron.h b/Geo/MHexahedron.h
index 350a23e23bcea6aebbbca4afc10174c8552f5d07..6be76e7c8e01b9931aa552b05d1fdda79b563d27 100644
--- a/Geo/MHexahedron.h
+++ b/Geo/MHexahedron.h
@@ -92,6 +92,7 @@ class MHexahedron : public MElement {
                  _v[faces_hexa(num, 2)],
                  _v[faces_hexa(num, 3)]);
   }
+  virtual void getFaceInfo (const MFace & face, int &ithFace, int &sign, int &rot)const; 
   virtual int getNumFacesRep(){ return 12; }
   virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
   {