diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index b9967b6b092c36d99c32b0295558328dbbf46d5b..f849a8b18788c4116ae815c57400397b2a3d8857 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -85,11 +85,12 @@ void PrintUsage(const char *name)
   Msg::Direct("  -check                Perform various consistency checks on mesh");
 #if defined(HAVE_FLTK)
   Msg::Direct("Post-processing options:");
-  Msg::Direct("  -noview               Hide all views on startup");
   Msg::Direct("  -link int             Select link mode between views (0, 1, 2, 3, 4)");
   Msg::Direct("  -combine              Combine views having identical names into multi-time-step views");
   Msg::Direct("Display options:");    
   Msg::Direct("  -nodb                 Disable double buffering");
+  Msg::Direct("  -noview               Hide all views on startup");
+  Msg::Direct("  -nomesh               Hide all meshes on startup");
   Msg::Direct("  -fontsize int         Specify the font size for the GUI");
   Msg::Direct("  -theme string         Specify FLTK GUI theme");
   Msg::Direct("  -display string       Specify display");
@@ -580,6 +581,15 @@ void GetOptions(int argc, char *argv[])
         opt_view_visible(0, GMSH_SET, 0);
         i++;
       }
+      else if(!strcmp(argv[i] + 1, "nomesh")) {
+        opt_mesh_points(0, GMSH_SET, 0.);
+        opt_mesh_lines(0, GMSH_SET, 0.);
+        opt_mesh_surfaces_edges(0, GMSH_SET, 0.);
+        opt_mesh_surfaces_faces(0, GMSH_SET, 0.);
+        opt_mesh_volumes_edges(0, GMSH_SET, 0.);
+        opt_mesh_volumes_faces(0, GMSH_SET, 0.);
+        i++;
+      }
       else if(!strcmp(argv[i] + 1, "link")) {
         i++;
         if(argv[i])
diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp
index c53b3f4ce755602087c7323b887ed1df726489a4..ec953370ddfbe53a44266035258c38de870e5d4d 100644
--- a/Geo/GFace.cpp
+++ b/Geo/GFace.cpp
@@ -1182,16 +1182,6 @@ void GFace::moveToValidRange(SPoint2 &pt) const
   }
 }
 
-void GFace::addTriangle(MTriangle *t) {
-  triangles.push_back(t); 
-}
-void GFace::addQuadrangle(MQuadrangle *q) {
-  quadrangles.push_back(q); 
-}
-void GFace::addPolygon(MPolygon *p) {
-  polygons.push_back(p); 
-}
-
 #include "Bindings.h"
 
 void GFace::registerBindings(binding *b)
diff --git a/Geo/GFace.h b/Geo/GFace.h
index 9f71f5981bc8b25c8af1df17f67a699954bb70ff..00aee5a100a99577dff8b6b3ceae1d0dc568a4bf 100644
--- a/Geo/GFace.h
+++ b/Geo/GFace.h
@@ -299,9 +299,9 @@ class GFace : public GEntity
   std::vector<MQuadrangle*> quadrangles;
   std::vector<MPolygon*> polygons;
 
-  void addTriangle(MTriangle *t);
-  void addQuadrangle(MQuadrangle *q);
-  void addPolygon(MPolygon *p);
+  void addTriangle(MTriangle *t){ triangles.push_back(t); }
+  void addQuadrangle(MQuadrangle *q){ quadrangles.push_back(q); }
+  void addPolygon(MPolygon *p){ polygons.push_back(p); }
 
   // an array with additional vertices that are supposed to exist
   // in the final mesh of the model face. This can be used for 
diff --git a/Numeric/DivideAndConquer.h b/Numeric/DivideAndConquer.h
index 843b2a0e22ef424e2265c0e49bb889121d623f32..e59e05e5e64192f4cdf849cc39753f8898468bdd 100644
--- a/Numeric/DivideAndConquer.h
+++ b/Numeric/DivideAndConquer.h
@@ -5,6 +5,7 @@
 
 #ifndef _DIVIDE_AND_CONQUER_H_
 #define _DIVIDE_AND_CONQUER_H_
+
 #include <vector>
 #include <algorithm>
 #include "fullMatrix.h"
diff --git a/Numeric/Gauss.h b/Numeric/Gauss.h
index 6be921404359def80fcfc4479cfc6ef8ebcefd2e..06ee437403d7b3a14af093f00022a090bc32ca94 100644
--- a/Numeric/Gauss.h
+++ b/Numeric/Gauss.h
@@ -5,8 +5,8 @@
 
 #ifndef _GAUSS_H_
 #define _GAUSS_H_
-#include "fullMatrix.h"
 
+#include "fullMatrix.h"
 
 struct IntPt{
   double pt[3];
@@ -36,7 +36,9 @@ IntPt *getGQPriPts(int order);
 int getNGQHPts(int order);
 IntPt *getGQHPts(int order);
 
-//For now this class is only for bindings but maybe the interface is cleaner (it does not add new types) and it can replace the other interface
+//For now this class is only for bindings but maybe the interface is
+//cleaner (it does not add new types) and it can replace the other
+//interface
 class gaussIntegration {
   public:
   static void getTriangle(int order, fullMatrix<double> &pts, fullMatrix<double> &weights);
diff --git a/Numeric/cartesian.h b/Numeric/cartesian.h
index 68b82937b739fc9535a0a92cc8b658f2d297b881..09c6bc6904a051588221bde2599d9077615a1e8f 100644
--- a/Numeric/cartesian.h
+++ b/Numeric/cartesian.h
@@ -1,3 +1,8 @@
+// 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>.
+
 #ifndef _CARTESIAN_H_
 #define _CARTESIAN_H_
 
@@ -7,6 +12,7 @@
 #include <stdio.h>
 #include "SVector3.h"
 #include "SPoint3.h"
+#include "GmshMessage.h"
 
 // A cartesian grid that encompasses an oriented 3-D box, with values
 // stored at vertices:
@@ -24,7 +30,7 @@
 //   The (i,j) cell has nodes (i,j), (i+1,j), (i+1,j+1) and (i,j+1)
 template <class scalar>
 class cartesianBox {
- private:  
+ private:
   // number of subdivisions along the xi-, eta- and zeta-axis
   int _Nxi, _Neta, _Nzeta;  
   // origin of the grid and spacing along xi, eta and zeta
@@ -34,16 +40,91 @@ class cartesianBox {
   // set of active cells; the value stored for cell (i,j,k) is the
   // linear index (i + _Nxi * j + _Nxi *_Neta * k)
   std::set<int> _activeCells;
-  // map of stored nodal values, index by the linear index
-  // (i + (_Nxi+1) * j + (_Nxi+1) * (_Neta+1) * k)
-  typename std::map<int, scalar> _nodalValues;
-  // mapping from linear node index to unique node tags
-  std::map<int, int> _nodeTags;
+  // map of stored nodal values, index by the linear index (i +
+  // (_Nxi+1) * j + (_Nxi+1) * (_Neta+1) * k). Along with the value is
+  // stored a node tag (used for global numbering of the nodes across
+  // the grid levels)
+  typename std::map<int, std::pair<scalar, int> > _nodalValues;
   // level of the box (coarset box has highest level; finest box has
   // level==1)
   int _level;
   // pointer to a finer (refined by 2) level box (if any)
   cartesianBox<scalar> *_childBox;
+  int _getNumNodes()
+  {
+    int n = 0;
+    for(valIter it = _nodalValues.begin(); it != _nodalValues.end(); it++)
+      if(it->second.second > 0) n++;
+    if(_childBox) n += _childBox->_getNumNodes();
+    return n;
+  }
+  void _printNodes(FILE *f)
+  {
+    for (valIter it = _nodalValues.begin(); it != _nodalValues.end(); ++it){
+      if(it->second.second > 0){
+        SPoint3 p = getNodeCoordinates(it->first);
+        fprintf(f, "%d %g %g %g\n", it->second.second, p.x(), p.y(), p.z());
+      }
+    }
+    if(_childBox) _childBox->_printNodes(f);
+  }
+  int _getNumElements(bool simplex)
+  {
+    int coeff = simplex ? 6 : 1;
+    int n = _activeCells.size() * coeff;
+    if(_childBox) n += _childBox->_getNumElements(simplex);
+    return n;
+  }
+  void _printElements(FILE *f, bool simplex, int startingNum=1)
+  {
+    int num = startingNum;
+    for(cellIter it = _activeCells.begin(); it != _activeCells.end(); ++it){
+      int i, j, k;
+      getCellIJK(*it, i, j, k);
+      if(!simplex){
+        fprintf(f, "%d 5 3 1 1 1", num++);
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i, j, k))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i + 1, j, k))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i + 1, j + 1, k))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i, j + 1, k))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i, j, k + 1))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i + 1, j, k + 1))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i + 1, j + 1, k + 1))));
+        fprintf(f, " %d", std::abs(getNodeTag(getNodeIndex(i, j + 1, k + 1))));
+        fprintf(f, "\n");
+      }
+      else{
+        int idx[6][4] = { 
+          {getNodeIndex(i, j + 1, k),     getNodeIndex(i, j + 1, k + 1),
+           getNodeIndex(i + 1, j, k + 1), getNodeIndex(i + 1, j + 1, k + 1)},
+          {getNodeIndex(i, j + 1, k),     getNodeIndex(i + 1, j + 1, k + 1),
+           getNodeIndex(i + 1, j, k + 1), getNodeIndex(i + 1, j + 1, k)},
+          {getNodeIndex(i, j + 1, k),     getNodeIndex(i, j, k + 1),
+           getNodeIndex(i + 1, j, k + 1), getNodeIndex(i, j + 1, k + 1)},
+          {getNodeIndex(i, j + 1, k),     getNodeIndex(i + 1, j + 1, k),
+           getNodeIndex(i + 1, j, k + 1), getNodeIndex(i + 1, j, k)},
+          {getNodeIndex(i, j + 1, k),     getNodeIndex(i + 1, j, k),
+           getNodeIndex(i + 1, j, k + 1), getNodeIndex(i, j, k)},
+          {getNodeIndex(i, j + 1, k),     getNodeIndex(i, j, k),
+           getNodeIndex(i + 1, j, k + 1), getNodeIndex(i, j, k + 1)}
+        };
+        for(int ii = 0; ii < 6; ii++){
+          fprintf(f, "%d 4 3 1 1 1 %d %d %d %d\n", num++,
+                  std::abs(getNodeTag(idx[ii][0])), std::abs(getNodeTag(idx[ii][1])),
+                  std::abs(getNodeTag(idx[ii][2])), std::abs(getNodeTag(idx[ii][3])));
+        }
+      }
+    }
+    if(_childBox) _childBox->_printElements(f, simplex, num);
+  }
+  void _printValues(FILE *f)
+  {
+    for(valIter it = _nodalValues.begin(); it != _nodalValues.end(); ++it){
+      if(it->second.second > 0)
+        fprintf(f, "%d %g\n", it->second.second, it->second.first);
+    }
+    if(_childBox) _childBox->_printValues(f);
+  }
  public:
   cartesianBox(double X, double Y, double Z, 
                const SVector3 &dxi, const SVector3 &deta, const SVector3 &dzeta, 
@@ -69,21 +150,20 @@ class cartesianBox {
   typedef std::set<int>::const_iterator cellIter;
   cellIter activeCellsBegin(){ return _activeCells.begin(); }
   cellIter activeCellsEnd(){ return _activeCells.end(); }
-  typedef typename std::map<int, scalar>::iterator valIter;
+  typedef typename std::map<int, std::pair<scalar, int> >::iterator valIter;
   valIter nodalValuesBegin(){ return _nodalValues.begin(); }
   valIter nodalValuesEnd(){ return _nodalValues.end(); }
-  void setNodalValue(int i, scalar s){ _nodalValues[i] = s; }
-  void getCellValues(int t, std::vector<scalar> &values)
+  void setNodalValue(int i, scalar s){ _nodalValues[i].first = s; }
+  void getNodalValuesForCell(int t, std::vector<scalar> &values)
   {
     int i, j, k;
     getCellIJK(t, i, j, k);
     for(int I = 0; I < 2; I++)
       for(int J = 0; J < 2; J++)
         for(int K = 0; K < 2; K++){
-          typename std::map<int, scalar>::iterator it = 
-            _nodalValues.find(getNodeIndex(i + I, j + J, k + K));
+          valIter it = _nodalValues.find(getNodeIndex(i + I, j + J, k + K));
           if(it != _nodalValues.end())
-            values.push_back(it->second);
+            values.push_back(it->second.first);
           else{
             Msg::Error("Could not find value i,j,k=%d,%d,%d for cell %d\n", 
                        i + I, j + J, k + K, t);
@@ -107,7 +187,7 @@ class cartesianBox {
     if (k < 0) k = 0; if (k >= _Nzeta) k = _Nzeta - 1;
     return getCellIndex(i, j, k);
   }
-  SPoint3 getNodeCoordinates(const int &t) const
+  SPoint3 getNodeCoordinates(int t) const
   {
     int i, j, k;
     getNodeIJK(t, i, j, k);
@@ -117,10 +197,9 @@ class cartesianBox {
     SVector3 D = xi * _xiAxis + eta * _etaAxis + zeta * _zetaAxis;
     return SPoint3(_X + D.x(), _Y + D.y(), _Z + D.z());
   }
-  void insertActiveCell(const int &t){ _activeCells.insert(t); }
-  void eraseActiveCell(const int &t){ _activeCells.erase(t); }
-  void eraseActiveCell(std::set<int>::iterator t){ _activeCells.erase(t); }
-  bool activeCellExists(const int &t)
+  void insertActiveCell(int t){ _activeCells.insert(t); }
+  void eraseActiveCell(int t){ _activeCells.erase(t); }
+  bool activeCellExists(int t)
   {
     return (_activeCells.find(t) != _activeCells.end()); 
   }
@@ -132,6 +211,12 @@ class cartesianBox {
   {
     return i + (_Nxi+1) * j + (_Nxi+1) * (_Neta+1) * k;
   }
+  int getNodeTag(int index)
+  {
+    valIter it = _nodalValues.find(index);
+    if(it != _nodalValues.end()) return it->second.second;
+    else return 0;
+  }
   void getCellIJK(int index, int &i, int &j, int &k) const 
   {
     k = index / (_Nxi * _Neta);
@@ -146,123 +231,61 @@ class cartesianBox {
   }
   void createNodalValues()
   {
-    std::set<int>::const_iterator it = _activeCells.begin();
-    for( ; it != _activeCells.end() ; ++it){
+    for(cellIter it = _activeCells.begin(); it != _activeCells.end(); ++it){
       const int &t = *it;
       int i, j, k;
       getCellIJK(t, i, j, k);
       for (int I = 0; I < 2; I++)
         for (int J = 0; J < 2; J++)
           for (int K = 0; K < 2; K++)
-            _nodalValues[getNodeIndex(i + I, j + J, k + K)] = 0.;
+            _nodalValues[getNodeIndex(i + I, j + J, k + K)] = 
+              std::pair<scalar, int>(0., 0);
     }
     if(_childBox) _childBox->createNodalValues();
   }
-  void writeMSH(const std::string &filename, bool simplex=false, 
-                bool writeNodalValues=true) const
+  void renumberNodes(int startingNum=1, cartesianBox<scalar> *parent=0)
+  {
+    int num = startingNum;
+    for(valIter it = _nodalValues.begin(); it != _nodalValues.end(); it++){
+      int i, j, k;
+      getNodeIJK(it->first, i, j, k);
+      if(!parent || i % 2 || j % 2 || k % 2)
+        it->second.second = num++;
+      else{
+        int tag = parent->getNodeTag(parent->getNodeIndex(i / 2, j / 2, k / 2));
+        if(!tag) // FIXME! not sure why this can happen, but it does (bug?)
+          it->second.second = num++;
+        else // the node exists in the coarset grid: store it with negative sign
+          it->second.second = -std::abs(tag);
+      }
+    }
+    if(_childBox) _childBox->renumberNodes(num, this);
+  }
+  void writeMSH(const std::string &fileName, bool simplex=false, 
+                bool writeNodalValues=true)
   {
-    FILE *f = fopen(filename.c_str(), "w");
+    FILE *f = fopen(fileName.c_str(), "w");
     if(!f){
-      Msg::Error("Could not open file '%s'", filename.c_str());
+      Msg::Error("Could not open file '%s'", fileName.c_str());
       return;
     }
+    int numNodes = _getNumNodes(), numElements = _getNumElements(simplex);
+    Msg::Info("Writing '%s' (%d nodes, %d elements)", fileName.c_str(), 
+              numNodes, numElements);
     fprintf(f, "$MeshFormat\n2.1 0 8\n$EndMeshFormat\n");
-    {
-      fprintf(f, "$Nodes\n%d\n", (int)_nodalValues.size());
-      typename std::map<int, scalar>::const_iterator it = _nodalValues.begin();
-      for ( ; it != _nodalValues.end(); ++it){
-        SPoint3 p = getNodeCoordinates(it->first);
-        fprintf(f, "%d %g %g %g\n", it->first, p.x(), p.y(), p.z());
-      }    
-      fprintf(f, "$EndNodes\n");
-    }
-    {
-      int coeff = simplex ? 6 : 1;
-      fprintf(f,"$Elements\n%d\n", coeff * (int)_activeCells.size());
-      std::set<int>::const_iterator it = _activeCells.begin();
-      for ( ; it != _activeCells.end(); ++it){
-        int i, j, k;
-        getCellIJK(*it, i, j, k);
-        if(!simplex){
-          fprintf(f, "%d 5 3 1 1 1", *it);
-          fprintf(f, " %d", getNodeIndex(i, j, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j + 1, k + 1));
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k + 1));
-          fprintf(f, "\n");
-        }
-        else{
-          // Elt1
-          fprintf(f, "%d 4 3 1 1 1", *it);
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j + 1, k + 1));
-          fprintf(f, "\n");
-          // Elt2
-          fprintf(f, "%d 4 3 1 1 1", *it + 1);
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j + 1, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j + 1, k));
-          fprintf(f, "\n");
-          // Elt3
-          fprintf(f, "%d 4 3 1 1 1", *it + 2);
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k + 1));
-          fprintf(f, "\n");
-          // Elt4
-          fprintf(f, "%d 4 3 1 1 1", *it + 3);
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k));
-          fprintf(f, "\n");
-          // Elt5
-          fprintf(f, "%d 4 3 1 1 1", *it + 4);
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i, j, k));
-          fprintf(f, "\n");
-          // Elt6
-          fprintf(f, "%d 4 3 1 1 1", *it + 5);
-          fprintf(f, " %d", getNodeIndex(i, j + 1, k));
-          fprintf(f, " %d", getNodeIndex(i, j, k));
-          fprintf(f, " %d", getNodeIndex(i + 1, j, k + 1));
-          fprintf(f, " %d", getNodeIndex(i, j, k + 1));
-          fprintf(f, "\n");
-        }
-      }    
-      fprintf(f,"$EndElements\n");    
-      if(_childBox)
-        _childBox->writeMSH(filename + "_2", simplex, writeNodalValues);
-    }
+    fprintf(f, "$Nodes\n%d\n", numNodes);
+    _printNodes(f);
+    fprintf(f, "$EndNodes\n");
+    fprintf(f,"$Elements\n%d\n", numElements);
+    _printElements(f, simplex);
+    fprintf(f,"$EndElements\n");    
     if(writeNodalValues){
-      fprintf(f,"$NodeData\n1\n\"distance\"\n 1\n 0.0\n3\n0\n 1\n %d\n",
-              (int)_nodalValues.size());
-      typename std::map<int, scalar>::const_iterator it = _nodalValues.begin();
-      for( ; it != _nodalValues.end(); ++it)
-        fprintf(f, "%d %g\n", it->first, it->second);
+      fprintf(f,"$NodeData\n1\n\"distance\"\n1\n0.0\n3\n0\n1\n%d\n", numNodes);
+      _printValues(f);
       fprintf(f, "$EndNodeData\n");
     }
     fclose(f);
   }
-  void writeNodalValues(const std::string &filename) const
-  {
-    FILE *f = fopen(filename.c_str(), "w");
-    fprintf(f, "%d\n", (int)_nodalValues.size());
-    typename std::map<int, scalar>::const_iterator it = _nodalValues.begin();
-    for( ; it != _nodalValues.end(); ++it)
-      fprintf(f, "%d %g\n", it->first, it->second);
-    fclose(f);
-  }
 };
 
 #endif
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index d65901bb94309329bbb44018abcc0be61aebb117..00698341af61c76526e7b2b702f076ca0d54919e 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -888,8 +888,6 @@ Perform various consistency checks on mesh
 @noindent Post-processing options:
 
 @ftable @code
-@item -noview
-Hide all views on startup
 @item -link int
 Select link mode between views (0, 1, 2, 3, 4)
 @item -combine
@@ -903,6 +901,10 @@ Combine views having identical names into multi-time-step views
 @ftable @code
 @item -nodb
 Disable double buffering
+@item -noview
+Hide all views on startup
+@item -nomesh
+Hide all meshes on startup
 @item -fontsize int
 Specify the font size for the GUI
 @item -theme string
diff --git a/utils/api_demos/mainCartesian.cpp b/utils/api_demos/mainCartesian.cpp
index 386fa294fe046924fbc43ac9047106b40faba5bc..cc8a8d0c8f8bce00260832c0f9f51ac2b240fec8 100644
--- a/utils/api_demos/mainCartesian.cpp
+++ b/utils/api_demos/mainCartesian.cpp
@@ -6,7 +6,6 @@
 #include "SOrientedBoundingBox.h"
 #include "Numeric.h"
 #include "GmshMessage.h"
-#include "OS.h"
 
 void insertActiveCells(double x, double y, double z, double rmax,
                        cartesianBox<double> &box)
@@ -32,7 +31,7 @@ void computeLevelset(GModel *gm, cartesianBox<double> &box)
     nodes.push_back(box.getNodeCoordinates(it->first));
     indices.push_back(it->first);
   }
-  Msg::Info("  %d nodes in the grid", (int)nodes.size());
+  Msg::Info("  %d nodes in the grid at level %d", (int)nodes.size(), box.getLevel());
   std::vector<double> dist, localdist;
   std::vector<SPoint3> dummy;
   for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++){
@@ -81,7 +80,7 @@ void fillPointCloud(GEdge *ge, double sampling, std::vector<SPoint3> &points)
   }
 }
 
-int removeOrphanChildCells(cartesianBox<double> *parent)
+int removeBadChildCells(cartesianBox<double> *parent)
 {
   cartesianBox<double> *child = parent->getChildBox();
   if(!child) return 0;
@@ -117,7 +116,7 @@ int removeOrphanChildCells(cartesianBox<double> *parent)
             (k != K - 1 && !parent->activeCellExists(parent->getCellIndex(i, j, k + 1)))))
             for(int ii = 0; ii < 8; ii++) child->eraseActiveCell(idx[ii]);
       }
-  return removeOrphanChildCells(child);
+  return removeBadChildCells(child);
 }
 
 void removeParentCellsWithChildren(cartesianBox<double> *box)
@@ -149,7 +148,7 @@ void removeOutsideCells(cartesianBox<double> *box)
   for(cartesianBox<double>::cellIter it = box->activeCellsBegin(); 
       it != box->activeCellsEnd();){
     std::vector<double> vals;
-    box->getCellValues(*it, vals);
+    box->getNodalValuesForCell(*it, vals);
     double lsmax = *std::max_element(vals.begin(), vals.end());
     double lsmin = *std::min_element(vals.begin(), vals.end());
     double change_sign = lsmax * lsmin;
@@ -186,7 +185,7 @@ int main(int argc,char *argv[])
   int levels = (argc > 6) ? atof(argv[6]) : 1;
 
   // minimum distance between points in the cloud at the coarsest level
-  double sampling = std::min(rmax, std::min(lx, std::min(ly, lz))) / 2.;
+  double sampling = std::min(rmax, std::min(lx, std::min(ly, lz)));
 
   // radius of the "tube" created around edges at the coarsest level
   double rtube = std::max(lx, std::max(ly, lz)) * 2.;
@@ -194,23 +193,28 @@ int main(int argc,char *argv[])
   GModel *gm = GModel::current();
   
   std::vector<SPoint3> points;
-  Msg::Info("Filling point cloud on surfaces");
+  Msg::Info("Filling coarse point cloud on surfaces");
   for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++)
     (*fit)->fillPointCloud(sampling, &points);
   Msg::Info("  %d points in the surface cloud", (int)points.size());
 
-  std::vector<SPoint3> edgePoints;
+  std::vector<SPoint3> refinePoints;
   if(levels > 1){
-    Msg::Info("Filling point cloud on curves");
+    double s = sampling / pow(2., levels - 1);
+    Msg::Info("Filling refined point cloud on curves and curved surfaces");
     for (GModel::eiter eit = gm->firstEdge(); eit != gm->lastEdge(); eit++)
-      fillPointCloud(*eit, sampling / pow(2., levels - 1), edgePoints);
-    Msg::Info("  %d points in the curve cloud", (int)edgePoints.size());
+      fillPointCloud(*eit, s, refinePoints);
+    // FIXME: refine this by computing e.g. "mean" curvature
+    for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++)
+      if((*fit)->geomType() != GEntity::Plane)
+        (*fit)->fillPointCloud(2 * s, &refinePoints);
+    Msg::Info("  %d points in the refined cloud", (int)refinePoints.size());
   }
 
   SBoundingBox3d bb;
   for(unsigned int i = 0; i < points.size(); i++) bb += points[i]; 
-  for(unsigned int i = 0; i < edgePoints.size(); i++) bb += edgePoints[i]; 
-  bb.scale(1.2, 1.2, 1.2);
+  for(unsigned int i = 0; i < refinePoints.size(); i++) bb += refinePoints[i]; 
+  bb.scale(1.21, 1.21, 1.21);
   SVector3 range = bb.max() - bb.min();   
   int NX = range.x() / lx; 
   int NY = range.y() / ly; 
@@ -231,13 +235,16 @@ int main(int argc,char *argv[])
                            NX, NY, NZ, levels);
 
   Msg::Info("Inserting active cells in the cartesian grid");
-  for (unsigned int i = 0; i < points.size();i++)
+  Msg::Info("  level %d", box.getLevel());
+  for (unsigned int i = 0; i < points.size(); i++)
     insertActiveCells(points[i].x(), points[i].y(), points[i].z(), rmax, box);
+
   cartesianBox<double> *parent = &box, *child;
   while((child = parent->getChildBox())){
-    for(unsigned int i = 0; i < edgePoints.size(); i++)
-      insertActiveCells(edgePoints[i].x(), edgePoints[i].y(), edgePoints[i].z(), 
-                        rtube / pow(2., levels - child->getLevel()), *child);
+    Msg::Info("  level %d", child->getLevel());
+    for(unsigned int i = 0; i < refinePoints.size(); i++)
+      insertActiveCells(refinePoints[i].x(), refinePoints[i].y(), refinePoints[i].z(), 
+                        rtube / pow(2., (levels - child->getLevel())), *child);
     parent = child;
   }
 
@@ -245,7 +252,7 @@ int main(int argc,char *argv[])
   // which there is no parent neighbor; then remove parent cells that
   // have children
   Msg::Info("Removing cells to match X-FEM mesh topology constraints");
-  removeOrphanChildCells(&box);
+  removeBadChildCells(&box);
   removeParentCellsWithChildren(&box);
 
   // we generate duplicate nodes at this point so we can easily access
@@ -261,12 +268,10 @@ int main(int argc,char *argv[])
   removeOutsideCells(&box);
 
   Msg::Info("Renumbering mesh vertices across levels");
+  box.renumberNodes();
   
-  
-  Msg::Info("Writing results to disk");
-  box.writeMSH("yeah.msh");
-  box.writeMSH("youhou.msh", true, false);
-  box.writeNodalValues("youhou.pos");
+  box.writeMSH("yeah.msh", true);
+
   Msg::Info("Done!");
   GmshFinalize();
 }