diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index c55f76908b7dada0e9d9d0b962763abbfe7212f8..8f983b939682b5cb062cc3a9c63d0797f8b7b545 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -1775,14 +1775,18 @@ static void mesh_optimize_cb(Fl_Widget *w, void *data)
   CTX::instance()->lock = 1;
   OptimizeMesh(GModel::current());
   CTX::instance()->lock = 0;
-  CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
   drawContext::global()->draw();
 }
 
 static void mesh_refine_cb(Fl_Widget *w, void *data)
 {
   RefineMesh(GModel::current(), CTX::instance()->mesh.secondOrderLinear);
-  CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
+  drawContext::global()->draw();
+}
+
+static void mesh_smooth_cb(Fl_Widget *w, void *data)
+{
+  SmoothMesh(GModel::current());
   drawContext::global()->draw();
 }
 
@@ -1795,7 +1799,6 @@ static void mesh_optimize_netgen_cb(Fl_Widget *w, void *data)
   CTX::instance()->lock = 1;
   OptimizeMeshNetgen(GModel::current());
   CTX::instance()->lock = 0;
-  CTX::instance()->mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
   drawContext::global()->draw();
 }
 
@@ -3795,6 +3798,8 @@ static menuItem static_modules[] = {
   {"0Modules/Mesh/Partition",
    (Fl_Callback *)mesh_partition_cb} ,
 #endif
+  {"0Modules/Mesh/Smooth 2D",
+   (Fl_Callback *)mesh_smooth_cb} ,
   {"0Modules/Mesh/Reclassify 2D",
    (Fl_Callback *)mesh_classify_cb} ,
 #if defined(HAVE_FOURIER_MODEL)
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 92c6d67507a8514aaefcf43b62bed0891216e65f..82920af3822511dc5c178099d4acdcd4ce139d62 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -367,7 +367,7 @@ static void Mesh2D(GModel *m)
                 temp[K]->geomType()==GEntity::RuledSurface) {
               if (temp[K]->meshAttributes.method != MESH_TRANSFINITE &&
                   !temp[K]->meshAttributes.extrude) {
-                smoothing smm(CTX::instance()->mesh.optimizeLloyd,6);
+                smoothing smm(CTX::instance()->mesh.optimizeLloyd, 6);
                 //m->writeMSH("beforeLLoyd.msh");
                 smm.optimize_face(temp[K]);
                 int rec = ((CTX::instance()->mesh.recombineAll ||
@@ -405,7 +405,7 @@ static void Mesh2D(GModel *m)
                 (*it)->geomType()==GEntity::RuledSurface) {
               if ((*it)->meshAttributes.method != MESH_TRANSFINITE &&
                   !(*it)->meshAttributes.extrude) {
-                smoothing smm(CTX::instance()->mesh.optimizeLloyd,6);
+                smoothing smm(CTX::instance()->mesh.optimizeLloyd, 6);
                 //m->writeMSH("beforeLLoyd.msh");
                 smm.optimize_face(*it);
                 int rec = ((CTX::instance()->mesh.recombineAll ||
@@ -484,7 +484,7 @@ void fillv_(std::multimap<MVertex*, MElement*> &vertexToElement,
   }
 }
 
-int LaplaceSmoothing (GRegion *gr)
+int LaplaceSmoothing(GRegion *gr)
 {
   std::multimap<MVertex*, MElement*> vertexToElement;
   fillv_(vertexToElement, (gr)->tetrahedra.begin(), (gr)->tetrahedra.end());
@@ -826,9 +826,10 @@ static void Mesh3D(GModel *m)
     TestConformity(m);
   }
 
-  // Ensure that all volume Jacobians are positive
+  // ensure that all volume Jacobians are positive
   m->setAllVolumesPositive();
 
+  CTX::instance()->mesh.changed = ENT_ALL;
   double t2 = Cpu();
   CTX::instance()->meshTimer[2] = t2 - t1;
   Msg::StatusBar(true, "Done meshing 3D (%g s)", CTX::instance()->meshTimer[2]);
@@ -840,7 +841,6 @@ void OptimizeMeshNetgen(GModel *m)
   double t1 = Cpu();
 
   std::for_each(m->firstRegion(), m->lastRegion(), optimizeMeshGRegionNetgen());
-
   // Ensure that all volume Jacobians are positive
   m->setAllVolumesPositive();
 
@@ -854,14 +854,29 @@ void OptimizeMesh(GModel *m)
   double t1 = Cpu();
 
   std::for_each(m->firstRegion(), m->lastRegion(), optimizeMeshGRegionGmsh());
-
   // Ensure that all volume Jacobians are positive
   m->setAllVolumesPositive();
 
+  CTX::instance()->mesh.changed = ENT_ALL;
   double t2 = Cpu();
   Msg::StatusBar(true, "Done optimizing 3D mesh (%g s)", t2 - t1);
 }
 
+void SmoothMesh(GModel *m)
+{
+  Msg::StatusBar(true, "Smoothing 2D mesh...");
+  double t1 = Cpu();
+
+  for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it){
+    GFace *gf = *it;
+    laplaceSmoothing(gf);
+  }
+
+  CTX::instance()->mesh.changed = ENT_ALL;
+  double t2 = Cpu();
+  Msg::StatusBar(true, "Done smoothing 2D mesh (%g s)", t2 - t1);
+}
+
 void AdaptMesh(GModel *m)
 {
   Msg::StatusBar(true, "Adapting 3D mesh...");
@@ -870,6 +885,7 @@ void AdaptMesh(GModel *m)
   for(int i = 0; i < 10; i++)
     std::for_each(m->firstRegion(), m->lastRegion(), adaptMeshGRegion());
 
+  CTX::instance()->mesh.changed = ENT_ALL;
   double t2 = Cpu();
   Msg::StatusBar(true, "Done adaptating 3D mesh (%g s)", t2 - t1);
 }
@@ -885,7 +901,6 @@ void RecombineMesh(GModel *m)
   }
 
   CTX::instance()->mesh.changed = ENT_ALL;
-
   double t2 = Cpu();
   Msg::StatusBar(true, "Done recombining 2D mesh (%g s)", t2 - t1);
 }
diff --git a/Mesh/Generator.h b/Mesh/Generator.h
index d698173f65c7bdc3bcffd7d44709f5a92482c60a..52ec48a3710385020d039a377c3cdd9f70b7f7d4 100644
--- a/Mesh/Generator.h
+++ b/Mesh/Generator.h
@@ -13,6 +13,7 @@ void AdaptMesh(GModel *m);
 void GenerateMesh(GModel *m, int dimension);
 void OptimizeMesh(GModel *m);
 void OptimizeMeshNetgen(GModel *m);
+void SmoothMesh(GModel *m);
 void RefineMesh(GModel *m, bool linear, bool splitIntoQuads=false,
                 bool splitIntoHexas=false);
 void RecombineMesh(GModel *m);
diff --git a/Mesh/meshRefine.cpp b/Mesh/meshRefine.cpp
index 91326339f495d8074a32720b00c3e020695b050f..532b4aa39336c8f42df5ec9cf58cff4af6b9e426 100644
--- a/Mesh/meshRefine.cpp
+++ b/Mesh/meshRefine.cpp
@@ -21,7 +21,7 @@
 #include "meshGFaceOptimize.h"
 
 void subdivide_pyramid(MElement* element,
-		       GRegion* gr, 
+		       GRegion* gr,
 		       faceContainer &faceVertices,
 		       std::vector<MHexahedron*> &dwarfs88);
 
@@ -475,6 +475,7 @@ void RefineMesh(GModel *m, bool linear, bool splitIntoQuads, bool splitIntoHexas
   // Check all 3D elements for negative volume and reverse if needed
   m->setAllVolumesPositive();
 
+  CTX::instance()->mesh.changed = ENT_ALL;
   double t2 = Cpu();
   Msg::StatusBar(true, "Done refining mesh (%g s)", t2 - t1);
 }
@@ -712,7 +713,7 @@ static double schneiders_z(int i){
     0.000000,
     -0.500000,
     1.000000,
-    0.000000, 
+    0.000000,
     -1.000000,
     0.051666,
     -0.058015,
@@ -935,7 +936,7 @@ static int schneiders_connect(int i,int j){
 
 
 void subdivide_pyramid(MElement* element,
-		       GRegion* gr, 
+		       GRegion* gr,
 		       faceContainer &faceVertices,
 		       std::vector<MHexahedron*> &dwarfs88)
 {
@@ -947,9 +948,9 @@ void subdivide_pyramid(MElement* element,
 
   dwarfs88.resize(88);
   v.resize(105);
-  
+
   for (int i=0;i<105;i++)v[i] = NULL;
-  
+
   v[29] = element->getVertex(0);
   v[27] = element->getVertex(1);
   v[3] = element->getVertex(2);
@@ -979,7 +980,7 @@ void subdivide_pyramid(MElement* element,
     gr->addMeshVertex(v[25]);
     faceVertices[MFace(v[29],v[27],v[102])].push_back(v[25]);
   }
-  
+
   fIter = faceVertices.find(MFace(v[27],v[3],v[102]));
   if (fIter != faceVertices.end())
     v[95] = fIter->second[0];
@@ -1009,7 +1010,7 @@ void subdivide_pyramid(MElement* element,
     gr->addMeshVertex(v[99]);
     faceVertices[MFace(v[5],v[29],v[102])].push_back(v[99]);
   }
-  
+
   for(i=0;i<105;i++){
     if (!v[i]){
       element->pnt(schneiders_z(i),schneiders_x(i),schneiders_y(i)/1.414213,point);
@@ -1027,11 +1028,10 @@ void subdivide_pyramid(MElement* element,
     index6 = schneiders_connect(5,i);
     index7 = schneiders_connect(6,i);
     index8 = schneiders_connect(7,i);
-    
+
     dwarfs88[i]=(new MHexahedron(v[index1],v[index2],
 				v[index3],v[index4],
 				v[index5],v[index6],
 				v[index7],v[index8]));
   }
 }
-