diff --git a/src/common/Context.h b/src/common/Context.h
index fde6d0b98e8a021f425bc2fdcdac6703af16ea9a..3cf6f789d2cdbf8436dda966e8ce1f6a9137c213 100644
--- a/src/common/Context.h
+++ b/src/common/Context.h
@@ -36,7 +36,7 @@ struct contextMeshOptions {
   int meshOnlyVisible, meshOnlyEmpty;
   int minCircleNodes, minCurveNodes, minLineNodes;
   int hoOptimize, hoPeriodic, hoNLayers, hoPrimSurfMesh, hoIterMax, hoPassMax;
-  int hoDistCAD, hoSavePeriodic;
+  int hoDistCAD, hoSavePeriodic, hoFixBndNodes;
   double hoThresholdMin, hoThresholdMax, hoPoissonRatio;
   bool hoNewFastCurvingAlgo;
   int hoCurveOuterBL;
diff --git a/src/common/DefaultOptions.h b/src/common/DefaultOptions.h
index 68b39ea39b4c43493cbc736d901629a05f9f7106..539a6e7adb9484a8c20d31e30798780a4d5cdc24 100644
--- a/src/common/DefaultOptions.h
+++ b/src/common/DefaultOptions.h
@@ -1162,6 +1162,8 @@ StringXNumber MeshOptions_Number[] = {
 
   { F|O, "HighOrderDistCAD", opt_mesh_ho_dist_cad, 0,
     "Try to optimize distance to CAD in high-order optimizer?"},
+  { F|O, "HighOrderFixBoundaryNodes", opt_mesh_ho_fix_bnd_nodes, 0,
+    "Fix boundary nodes during high-order optimization?"},
   { F|O, "HighOrderIterMax", opt_mesh_ho_iter_max, 100,
     "Maximum number of iterations in high-order optimization pass"},
   { F|O, "HighOrderNumLayers", opt_mesh_ho_nlayers, 6.,
diff --git a/src/common/Options.cpp b/src/common/Options.cpp
index 21578b6b7dcfb0740e62c208d1e9f559176a248b..674e31f2d45ec75bd2827753690fdcbafc549ba4 100644
--- a/src/common/Options.cpp
+++ b/src/common/Options.cpp
@@ -6261,6 +6261,12 @@ double opt_mesh_ho_max_in_angle(OPT_ARGS_NUM)
   return CTX::instance()->mesh.hoMaxInnerAngle;
 }
 
+double opt_mesh_ho_fix_bnd_nodes(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET) CTX::instance()->mesh.hoFixBndNodes = val;
+  return CTX::instance()->mesh.hoFixBndNodes;
+}
+
 double opt_mesh_second_order_linear(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET) {
diff --git a/src/common/Options.h b/src/common/Options.h
index 2c9b95f008b6facd0949984218eca1179f18144a..96cc661f6adfb5ed47878f6adf8183abef569548 100644
--- a/src/common/Options.h
+++ b/src/common/Options.h
@@ -568,6 +568,7 @@ double opt_mesh_ho_curve_outer_BL(OPT_ARGS_NUM);
 double opt_mesh_ho_max_rho(OPT_ARGS_NUM);
 double opt_mesh_ho_max_angle(OPT_ARGS_NUM);
 double opt_mesh_ho_max_in_angle(OPT_ARGS_NUM);
+double opt_mesh_ho_fix_bnd_nodes(OPT_ARGS_NUM);
 double opt_mesh_second_order_linear(OPT_ARGS_NUM);
 double opt_mesh_second_order_incomplete(OPT_ARGS_NUM);
 double opt_mesh_cgns_import_order(OPT_ARGS_NUM);
diff --git a/src/mesh/Generator.cpp b/src/mesh/Generator.cpp
index 15cbaf84e52168bcd17fef75cb385a887a685528..4e542c28781f30475f714ce1532179550effc170 100644
--- a/src/mesh/Generator.cpp
+++ b/src/mesh/Generator.cpp
@@ -1015,6 +1015,7 @@ void OptimizeMesh(GModel *m, const std::string &how, bool force, int niter)
     p.BARRIER_MAX = CTX::instance()->mesh.hoThresholdMax;
     p.itMax = CTX::instance()->mesh.hoIterMax;
     p.optPassMax = CTX::instance()->mesh.hoPassMax;
+    p.fixBndNodes = CTX::instance()->mesh.hoFixBndNodes;
     p.dim = m->getDim();
     p.optPrimSurfMesh = CTX::instance()->mesh.hoPrimSurfMesh;
     p.optCAD = CTX::instance()->mesh.hoDistCAD;
@@ -1065,49 +1066,49 @@ void OptimizeMesh(GModel *m, const std::string &how, bool force, int niter)
     }
   }
   else if(how == "DiskQuadrangulation") {
-    for(GFace *gf : m->getFaces())
+    for(GFace *gf : m->getFaces()) {
       if(gf->meshStatistics.status == GFace::DONE) {
         gf->meshStatistics.status = GFace::PENDING;
       }
-
+    }
     transferSeamGEdgesVerticesToGFace(m);
     optimizeTopologyWithDiskQuadrangulationRemeshing(m);
-
-    for(GFace *gf : m->getFaces())
+    for(GFace *gf : m->getFaces()) {
       if(gf->meshStatistics.status == GFace::PENDING) {
         gf->meshStatistics.status = GFace::DONE;
       }
+    }
   }
   else if(how == "QuadCavityRemeshing") {
-    for(GFace *gf : m->getFaces())
+    for(GFace *gf : m->getFaces()) {
       if(gf->meshStatistics.status == GFace::DONE) {
         gf->meshStatistics.status = GFace::PENDING;
       }
-
+    }
     transferSeamGEdgesVerticesToGFace(m);
     optimizeTopologyWithCavityRemeshing(m);
-
-    for(GFace *gf : m->getFaces())
+    for(GFace *gf : m->getFaces()) {
       if(gf->meshStatistics.status == GFace::PENDING) {
         gf->meshStatistics.status = GFace::DONE;
       }
+    }
   }
   else if(how == "QuadQuasiStructured") {
     // The following methods only act on faces whose status is PENDING
-    for(GFace *gf : m->getFaces())
+    for(GFace *gf : m->getFaces()) {
       if(gf->meshStatistics.status == GFace::DONE) {
         gf->meshStatistics.status = GFace::PENDING;
       }
-
+    }
     transferSeamGEdgesVerticesToGFace(m);
     quadMeshingOfSimpleFacesWithPatterns(m);
     optimizeTopologyWithDiskQuadrangulationRemeshing(m);
     optimizeTopologyWithCavityRemeshing(m);
-
-    for(GFace *gf : m->getFaces())
+    for(GFace *gf : m->getFaces()) {
       if(gf->meshStatistics.status == GFace::PENDING) {
         gf->meshStatistics.status = GFace::DONE;
       }
+    }
   }
   else if(how == "UntangleMeshGeometry") {
 #if defined(HAVE_WINSLOWUNTANGLER)
@@ -1120,7 +1121,7 @@ void OptimizeMesh(GModel *m, const std::string &how, bool force, int niter)
         untangleGFaceMeshConstrained(gf, nIterWinslow, timeMax);
       }
       else {
-        Msg::Debug("- Face %i: not planar, do not apply Winslow untangling",
+        Msg::Debug("- Surface %i: not planar, do not apply Winslow untangling",
                    gf->tag());
       }
     }