diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index 75a324b3a14b50d6b5dff071481246b48af4ff17..814c20676ad6c51cedbd879f9ed8678912624c69 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -943,7 +943,7 @@ gmsh::model::getParametrization(const int dim, const int tag,
     GFace *gf = static_cast<GFace *>(entity);
     for(std::size_t i = 0; i < coord.size(); i += 3) {
       SPoint3 p(coord[i], coord[i + 1], coord[i + 2]);
-      SPoint2 uv = gf->parFromPoint(p);
+      SPoint2 uv = gf->parFromPoint(p, true, true);
       parametricCoord.push_back(uv.x());
       parametricCoord.push_back(uv.y());
     }
@@ -6476,6 +6476,7 @@ _addModelData(const int tag, const int step, const std::string &modelName,
     d->initAdaptiveData(view->getOptions()->timeStep,
                         view->getOptions()->maxRecursionLevel,
                         view->getOptions()->targetError);
+  view->setChanged(true);
 #else
   Msg::Error("Views require the post-processing module");
 #endif
@@ -6722,6 +6723,7 @@ GMSH_API void gmsh::view::addListData(const int tag,
   for(int idxtype = 0; idxtype < 24; idxtype++) {
     if(dataType == types[idxtype]) {
       d->importList(idxtype, numElements, data, true);
+      view->setChanged(true);
       return;
     }
   }
@@ -6838,6 +6840,7 @@ gmsh::view::addListDataString(const int tag, const std::vector<double> &coord,
     }
   }
   d->finalize();
+  view->setChanged(true);
 #else
   Msg::Error("Views require the post-processing module");
 #endif
@@ -6965,6 +6968,7 @@ GMSH_API void gmsh::view::setInterpolationMatrices(
 
   if(dGeo <= 0) {
     data->setInterpolationMatrices(itype, F, P);
+    view->setChanged(true);
     return;
   }
 
@@ -6985,6 +6989,7 @@ GMSH_API void gmsh::view::setInterpolationMatrices(
     for(int j = 0; j < 3; j++) { Pg(i, j) = expGeo[3 * i + j]; }
   }
   data->setInterpolationMatrices(itype, F, P, Fg, Pg);
+  view->setChanged(true);
 #else
   Msg::Error("Views require the post-processing module");
 #endif
@@ -7026,6 +7031,7 @@ GMSH_API void gmsh::view::copyOptions(const int refTag, const int tag)
     return;
   }
   view->setOptions(ref->getOptions());
+  view->setChanged(true);
 #if defined(HAVE_FLTK)
   if(FlGui::available()) FlGui::instance()->updateViews(true, true);
 #endif
diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp
index 82ca8bfc08a3639823b514f894eae94189cf1571..c78cb27e98e7755686fc8019862f830d9974e706 100644
--- a/Geo/GFace.cpp
+++ b/Geo/GFace.cpp
@@ -468,7 +468,7 @@ void GFace::writeGEO(FILE *fp)
       num.push_back((*it)->tag());
     for(auto it = dir.begin(); it != dir.end(); it++)
       ori.push_back((*it) > 0 ? 1 : -1);
-    fprintf(fp, "Line Loop(%d) = ", tag());
+    fprintf(fp, "Curve Loop(%d) = ", tag());
     for(std::size_t i = 0; i < num.size(); i++) {
       if(i)
         fprintf(fp, ", %d", num[i] * ori[i]);
@@ -988,11 +988,12 @@ void GFace::getMetricEigenVectors(const SPoint2 &param, double eigVal[2],
 }
 
 void GFace::XYZtoUV(double X, double Y, double Z, double &U, double &V,
-                    double relax, bool onSurface) const
+                    double relax, bool onSurface, bool convTestXYZ) const
 {
   const double Precision = onSurface ? 1.e-8 : 1.e-3;
   const int MaxIter = onSurface ? 25 : 10;
   const int NumInitGuess = 9;
+  bool testXYZ = (convTestXYZ || CTX::instance()->mesh.NewtonConvergenceTestXYZ);
 
   double Unew = 0., Vnew = 0., err, err2;
   int iter;
@@ -1063,17 +1064,15 @@ void GFace::XYZtoUV(double X, double Y, double Z, double &U, double &V,
 
       if(iter < MaxIter && err <= tol && Unew <= umax && Vnew <= vmax &&
          Unew >= umin && Vnew >= vmin) {
-        if(onSurface && err2 > 1.e-4 * CTX::instance()->lc &&
-           !CTX::instance()->mesh.NewtonConvergenceTestXYZ) {
+        if(onSurface && err2 > 1.e-4 * CTX::instance()->lc && !testXYZ) {
           Msg::Warning("Converged at iter. %d for initial guess (%d,%d) "
                        "with uv error = %g, but xyz error = %g in point "
-                       "(%e,%e,%e) on surface %d",
+                       "(%e, %e, %e) on surface %d",
                        iter, i, j, err, err2, X, Y, Z, tag());
         }
 
-        if(onSurface && err2 > 1.e-4 * CTX::instance()->lc &&
-           CTX::instance()->mesh.NewtonConvergenceTestXYZ) {
-          // not converged in XYZ coordinates
+        if(onSurface && err2 > 1.e-4 * CTX::instance()->lc && testXYZ) {
+          // not converged in XYZ coordinates: try again
         }
         else {
           return;
@@ -1084,18 +1083,19 @@ void GFace::XYZtoUV(double X, double Y, double Z, double &U, double &V,
 
   if(!onSurface) return;
 
-  if(relax < 1.e-6)
-    Msg::Error("Could not converge: surface mesh will be wrong");
+  if(relax < 1.e-3)
+    Msg::Error("Inverse surface mapping could not converge");
   else {
     Msg::Info("point %g %g %g : Relaxation factor = %g", X, Y, Z, 0.75 * relax);
-    XYZtoUV(X, Y, Z, U, V, 0.75 * relax);
+    XYZtoUV(X, Y, Z, U, V, 0.75 * relax, onSurface, convTestXYZ);
   }
 }
 
-SPoint2 GFace::parFromPoint(const SPoint3 &p, bool onSurface) const
+SPoint2 GFace::parFromPoint(const SPoint3 &p, bool onSurface,
+                            bool convTestXYZ) const
 {
   double U = 0., V = 0.;
-  XYZtoUV(p.x(), p.y(), p.z(), U, V, 1.0, onSurface);
+  XYZtoUV(p.x(), p.y(), p.z(), U, V, 1.0, onSurface, convTestXYZ);
   return SPoint2(U, V);
 }
 
diff --git a/Geo/GFace.h b/Geo/GFace.h
index dab4b377575a1cf8e2ae73a6e33e559fd4489fdd..a0b222e52c0948f5261bff925f49f157d79803fb 100644
--- a/Geo/GFace.h
+++ b/Geo/GFace.h
@@ -148,7 +148,7 @@ public:
 
   // compute the parameters UV from a point XYZ
   void XYZtoUV(double X, double Y, double Z, double &U, double &V, double relax,
-               bool onSurface = true) const;
+               bool onSurface = true, bool convTestXYZ = false) const;
 
   // get the bounding box
   virtual SBoundingBox3d bounds(bool fast = false);
@@ -181,7 +181,8 @@ public:
 
   // return the parameter location on the face given a point in space
   // that is on the face
-  virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface = true) const;
+  virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface = true,
+                               bool convTestXYZ = false) const;
 
   // true if the parameter value is interior to the face
   virtual bool containsParam(const SPoint2 &pt);
diff --git a/Geo/OCCFace.cpp b/Geo/OCCFace.cpp
index cdc4b132511f47536f69c125ce21a64e7cfeef05..ab4f0a3c20c178851607a9c9876f8ac46c6d3e08 100644
--- a/Geo/OCCFace.cpp
+++ b/Geo/OCCFace.cpp
@@ -285,16 +285,17 @@ GPoint OCCFace::closestPoint(const SPoint3 &qp,
     return GFace::closestPoint(qp, initialGuess);
 }
 
-SPoint2 OCCFace::parFromPoint(const SPoint3 &qp, bool onSurface) const
+SPoint2 OCCFace::parFromPoint(const SPoint3 &qp, bool onSurface,
+                              bool convTestXYZ) const
 {
   // less robust but can be much faster
   if(CTX::instance()->geom.occUseGenericClosestPoint)
-    return GFace::parFromPoint(qp);
+    return GFace::parFromPoint(qp, onSurface, convTestXYZ);
   double uv[2];
   if(_project(qp.data(), uv, nullptr))
     return SPoint2(uv[0], uv[1]);
-  else
-    return GFace::parFromPoint(qp);
+  else // fallback: force convergence test in XYZ coordinates
+    return GFace::parFromPoint(qp, true, true);
 }
 
 GEntity::GeomType OCCFace::geomType() const
diff --git a/Geo/OCCFace.h b/Geo/OCCFace.h
index 2f870bbd5f8c572c6bfe1b1f72db9511768ce904..611994b68bb4ae10ea1385543f223363224164d3 100644
--- a/Geo/OCCFace.h
+++ b/Geo/OCCFace.h
@@ -45,7 +45,8 @@ public:
   virtual GEntity::GeomType geomType() const;
   virtual ModelType getNativeType() const { return OpenCascadeModel; }
   virtual void *getNativePtr() const { return (void *)&_s; }
-  virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface = true) const;
+  virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface = true,
+                               bool convTestXYZ = false) const;
   virtual double curvatureMax(const SPoint2 &param) const;
   virtual double curvatures(const SPoint2 &param, SVector3 &dirMax,
                             SVector3 &dirMin, double &curvMax,
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 58e724951a149696ad6b70e9fd9986be794eb293..fe0ad5ed0a9a5a9f2245e09a334db4ed76a07d88 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -254,7 +254,8 @@ GPoint discreteFace::closestPoint(const SPoint3 &queryPoint,
   return closestPoint(queryPoint, 1e-1);
 }
 
-SPoint2 discreteFace::parFromPoint(const SPoint3 &p, bool onSurface) const
+SPoint2 discreteFace::parFromPoint(const SPoint3 &p, bool onSurface,
+                                   bool convTestXYZ) const
 {
   GPoint gp = closestPoint(p, 1e-6);
   return SPoint2(gp.u(), gp.v());
diff --git a/Geo/discreteFace.h b/Geo/discreteFace.h
index 26853964630287ed76b980cecf8a7ad7cba23671..6d12db6525982751b1860eb6b1dd78d3be58a445 100644
--- a/Geo/discreteFace.h
+++ b/Geo/discreteFace.h
@@ -43,7 +43,8 @@ public:
   virtual ~discreteFace() {}
   using GFace::point;
   GPoint point(double par1, double par2) const;
-  SPoint2 parFromPoint(const SPoint3 &p, bool onSurface = true) const;
+  SPoint2 parFromPoint(const SPoint3 &p, bool onSurface = true,
+                       bool convTestXYZ = false) const;
   Range<double> parBounds(int i) const;
   bool containsParam(const SPoint2 &pt);
   GPoint closestPoint(const SPoint3 &queryPoint, double maxDistance,
diff --git a/Geo/gmshFace.cpp b/Geo/gmshFace.cpp
index c4d0dd483bf670a0082729dfa14b888baaa98550..633bb8ac14158d824b66324c144d053dcf559559 100644
--- a/Geo/gmshFace.cpp
+++ b/Geo/gmshFace.cpp
@@ -287,7 +287,8 @@ GPoint gmshFace::closestPoint(const SPoint3 &qp,
   return GPoint(v.Pos.X, v.Pos.Y, v.Pos.Z, this, u);
 }
 
-SPoint2 gmshFace::parFromPoint(const SPoint3 &qp, bool onSurface) const
+SPoint2 gmshFace::parFromPoint(const SPoint3 &qp, bool onSurface,
+                               bool convTestXYZ) const
 {
   if(_s->Typ == MSH_SURF_PLAN) {
     double x, y, z, VX[3], VY[3];
@@ -298,7 +299,7 @@ SPoint2 gmshFace::parFromPoint(const SPoint3 &qp, bool onSurface) const
     return SPoint2(u, v);
   }
   else {
-    return GFace::parFromPoint(qp, onSurface);
+    return GFace::parFromPoint(qp, onSurface, convTestXYZ);
   }
 }
 
diff --git a/Geo/gmshFace.h b/Geo/gmshFace.h
index e616af4c88ce0a7d5129e370632f7afde97edba0..01ba5ab2917c8263ed124ddd34beda7712276ce6 100644
--- a/Geo/gmshFace.h
+++ b/Geo/gmshFace.h
@@ -32,7 +32,8 @@ public:
   virtual bool haveParametrization();
   virtual ModelType getNativeType() const { return GmshModel; }
   virtual void *getNativePtr() const { return _s; }
-  virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface = true) const;
+  virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface = true,
+                               bool convTestXYZ = false) const;
   virtual void resetMeshAttributes();
   void resetNativePtr(Surface *s);
   bool degenerate(int dim) const;