From 19b0df1068174e563c29a44607c290fa3106762f Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Tue, 13 Mar 2007 16:11:43 +0000
Subject: [PATCH] *** empty log message ***

---
 Common/CommandLine.cpp         |   9 ++-
 Common/Context.h               |   2 +-
 Common/DefaultOptions.h        |   4 +-
 Common/Options.cpp             |  15 +++-
 Common/Options.h               |   1 +
 Fltk/Callbacks.cpp             |   5 +-
 Fltk/GUI.cpp                   |  21 +++--
 Geo/MElement.h                 |   6 ++
 Geo/gmshEdge.cpp               |   4 +-
 Mesh/HighOrder.cpp             | 140 ++++++++++++++++++++++++++++++++-
 benchmarks/2d/naca12_2d.geo    |   4 +-
 benchmarks/2d/wing-splines.geo |   2 +-
 12 files changed, 191 insertions(+), 22 deletions(-)

diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 39bc1bb08e..afab1b5a77 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -1,4 +1,4 @@
-// $Id: CommandLine.cpp,v 1.95 2007-03-11 20:18:57 geuzaine Exp $
+// $Id: CommandLine.cpp,v 1.96 2007-03-13 16:11:42 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -86,7 +86,8 @@ void Print_Usage(char *name){
   Msg(DIRECT, "  -algo string          Select mesh algorithm (iso, netgen, tetgen)");
   Msg(DIRECT, "  -smooth int           Set number of mesh smoothing steps");
   Msg(DIRECT, "  -optimize             Optimize quality of tetrahedral elements");
-  Msg(DIRECT, "  -order int            Set mesh order (1, 2)");
+  Msg(DIRECT, "  -order int            Set mesh order (1, ..., 5)");
+  Msg(DIRECT, "  -optimize_hom         Optimize higher order meshes (in 2D)");
   Msg(DIRECT, "  -clscale float        Set characteristic length scaling factor");
   Msg(DIRECT, "  -clcurv               Compute characteristic lengths from curvatures");
   Msg(DIRECT, "  -rand float           Set random perturbation factor");
@@ -373,6 +374,10 @@ void Get_Options(int argc, char *argv[])
           exit(1);
         }
       }
+      else if(!strcmp(argv[i] + 1, "optimize_hom")) {
+        i++;
+	opt_mesh_smooth_internal_edges(0, GMSH_SET, 1);
+      }
       else if(!strcmp(argv[i] + 1, "format") || !strcmp(argv[i] + 1, "f")) {
         i++;
         if(argv[i] != NULL) {
diff --git a/Common/Context.h b/Common/Context.h
index 0374e518fb..c385df6870 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -173,7 +173,7 @@ public :
     int dual;
     int light, light_two_side, light_lines;
     int format, nb_smoothing, algo2d, algo3d, algo_recombine;
-    int order, second_order_linear, second_order_incomplete;
+    int order, second_order_linear, second_order_incomplete, smooth_internal_edges;
     int min_circ_points;
     int bgmesh_view_num, constrained_bgmesh, lc_from_curvature;
     double normals, tangents, explode;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 2765c041e5..84a5d86d0e 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -907,7 +907,9 @@ StringXNumber MeshOptions_Number[] = {
     "Display the dual mesh obtained by barycentric subdivision" },
 
   { F|O, "ElementOrder" , opt_mesh_order , 1. , // "Order" is a reserved token in the parser
-    "Element order (1=linear elements, 2=quadratic elements)" },
+    "Element order (1=linear elements, N (<6) = elements of higher order)" },
+  { F|O, "SmoothInternalEdges" , opt_mesh_smooth_internal_edges , 0 , // "Order" is a reserved token in the parser
+    "Number of smoothing steps of internal edges for high order meshes" },
   { F|O, "Explode" , opt_mesh_explode , 1.0 ,
     "Element shrinking factor (between 0 and 1)" },
 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index f3e5a26d62..0c6aad7bd0 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.336 2007-02-16 08:54:03 geuzaine Exp $
+// $Id: Options.cpp,v 1.337 2007-03-13 16:11:42 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -4804,11 +4804,22 @@ double opt_mesh_order(OPT_ARGS_NUM)
     CTX.mesh.order = (int)val;
 #if defined(HAVE_FLTK)
   if(WID && (action & GMSH_GUI))
-    WID->mesh_butt[3]->value(CTX.mesh.order == 2);
+    WID->mesh_value[3]->value(CTX.mesh.order);
 #endif
   return CTX.mesh.order;
 }
 
+double opt_mesh_smooth_internal_edges(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.smooth_internal_edges = (int)val;
+#if defined(HAVE_FLTK)
+  if(WID && (action & GMSH_GUI))
+    WID->mesh_butt[3]->value(CTX.mesh.smooth_internal_edges);
+#endif
+  return CTX.mesh.smooth_internal_edges;
+}
+
 double opt_mesh_second_order_linear(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 8020326e82..6d083a38a9 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -468,6 +468,7 @@ double opt_mesh_recombine_algo(OPT_ARGS_NUM);
 double opt_mesh_min_circ_points(OPT_ARGS_NUM);
 double opt_mesh_constrained_bgmesh(OPT_ARGS_NUM);
 double opt_mesh_order(OPT_ARGS_NUM);
+double opt_mesh_smooth_internal_edges(OPT_ARGS_NUM);
 double opt_mesh_second_order_linear(OPT_ARGS_NUM);
 double opt_mesh_second_order_incomplete(OPT_ARGS_NUM);
 double opt_mesh_dual(OPT_ARGS_NUM);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 0b27d00dd6..b02f8eff67 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.517 2007-03-11 20:18:57 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.518 2007-03-13 16:11:42 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -1085,7 +1085,8 @@ void mesh_options_ok_cb(CALLBACK_ARGS)
   opt_mesh_reverse_all_normals(0, GMSH_SET, WID->mesh_butt[0]->value());
   opt_mesh_lc_from_curvature(0, GMSH_SET, WID->mesh_butt[1]->value());
   opt_mesh_optimize(0, GMSH_SET, WID->mesh_butt[2]->value());
-  opt_mesh_order(0, GMSH_SET, WID->mesh_butt[3]->value()? 2 : 1);
+  opt_mesh_order(0, GMSH_SET, WID->mesh_value[3]->value());
+  opt_mesh_smooth_internal_edges(0, GMSH_SET, WID->mesh_butt[3]->value());
   opt_mesh_second_order_incomplete(0, GMSH_SET, WID->mesh_butt[4]->value());
   opt_mesh_constrained_bgmesh(0, GMSH_SET, WID->mesh_butt[5]->value());
   opt_mesh_points(0, GMSH_SET, WID->mesh_butt[6]->value());
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index d1c6bf721c..984e715e08 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.600 2007-02-21 08:17:16 geuzaine Exp $
+// $Id: GUI.cpp,v 1.601 2007-03-13 16:11:42 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -2253,33 +2253,40 @@ void GUI::create_option_window()
       mesh_value[0]->align(FL_ALIGN_RIGHT);
       mesh_value[0]->callback(mesh_options_ok_cb);
 
-      mesh_value[2] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Characteristic length factor");
+      mesh_value[3] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Element orders (1-5)");
+      mesh_value[3]->minimum(1);
+      mesh_value[3]->maximum(5);
+      mesh_value[3]->step(1);
+      mesh_value[3]->align(FL_ALIGN_RIGHT);
+      mesh_value[3]->callback(mesh_options_ok_cb);
+
+      mesh_value[2] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Characteristic length factor");
       mesh_value[2]->minimum(0.001);
       mesh_value[2]->maximum(1000);
       mesh_value[2]->step(0.01);
       mesh_value[2]->align(FL_ALIGN_RIGHT);
       mesh_value[2]->callback(mesh_options_ok_cb);
 
-      mesh_butt[1] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Compute characteritic lenghts automatically from curvatures" );
+      mesh_butt[1] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Compute characteritic lenghts automatically from curvatures" );
       mesh_butt[1]->type(FL_TOGGLE_BUTTON);
       mesh_butt[1]->callback(mesh_options_ok_cb);
 
-      mesh_butt[5] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Constrain background mesh with characteristic length field");
+      mesh_butt[5] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 8 * BH, BW, BH, "Constrain background mesh with characteristic length field");
       mesh_butt[5]->type(FL_TOGGLE_BUTTON);
       mesh_butt[5]->callback(mesh_options_ok_cb);
 
-      mesh_butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 8 * BH, BW, BH, "Optimize quality of tetrahedra");
+      mesh_butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 9 * BH, BW, BH, "Optimize quality of tetrahedra");
       mesh_butt[2]->type(FL_TOGGLE_BUTTON);
 #if !defined(HAVE_NETGEN)
       mesh_butt[2]->deactivate();
 #endif
       mesh_butt[2]->callback(mesh_options_ok_cb);
 
-      mesh_butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 9 * BH, BW, BH, "Generate second order elements");
+      mesh_butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 10 * BH, BW, BH, "Optimize high order mesh (currently for 2D - plane)");
       mesh_butt[3]->type(FL_TOGGLE_BUTTON);
       mesh_butt[3]->callback(mesh_options_ok_cb);
 
-      mesh_butt[4] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 10 * BH, BW, BH, "Use incomplete second order elements (8-node quads, etc.)");
+      mesh_butt[4] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 11 * BH, BW, BH, "Use incomplete second order elements (8-node quads, etc.)");
       mesh_butt[4]->type(FL_TOGGLE_BUTTON);
       mesh_butt[4]->callback(mesh_options_ok_cb);
 
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 5545a6ca0f..a640b6b6eb 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -313,6 +313,12 @@ class MTriangle : public MElement {
   bool invertmappingXY(double *p, double *uv, double tol = 1.e-8);
   virtual int getNumVertices(){ return 3; }
   virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getOtherVertex(MVertex *v1, MVertex *v2){ 
+    if( _v[0] != v1 && _v[0] != v2 ) return _v[0];
+    if( _v[1] != v1 && _v[1] != v2 ) return _v[1];
+    if( _v[2] != v1 && _v[2] != v2 ) return _v[2];
+    throw;
+  }
   virtual int getNumEdges(){ return 3; }
   virtual MEdge getEdge(int num)
   {
diff --git a/Geo/gmshEdge.cpp b/Geo/gmshEdge.cpp
index 7e5f0c44a9..be39b4f685 100644
--- a/Geo/gmshEdge.cpp
+++ b/Geo/gmshEdge.cpp
@@ -1,4 +1,4 @@
-// $Id: gmshEdge.cpp,v 1.32 2007-03-05 11:07:14 remacle Exp $
+// $Id: gmshEdge.cpp,v 1.33 2007-03-13 16:11:43 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -123,8 +123,6 @@ int gmshEdge::minimumMeshSegments () const
   if(geomType() == Circle || geomType() == Ellipse)
     return (int)(fabs(c->Circle.t1 - c->Circle.t2) *
 		 (double)CTX.mesh.min_circ_points / Pi) - 1;
-  else if(geomType() == Nurb)
-    return 5;
   else
     return GEdge::minimumMeshSegments () ;
 }
diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp
index a445588a11..67aea10db7 100644
--- a/Mesh/HighOrder.cpp
+++ b/Mesh/HighOrder.cpp
@@ -1,4 +1,4 @@
-// $Id: HighOrder.cpp,v 1.7 2007-03-02 08:44:55 geuzaine Exp $
+// $Id: HighOrder.cpp,v 1.8 2007-03-13 16:11:43 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -601,6 +601,137 @@ void SetOrder1(GModel *m)
     removeHighOrderVertices(*it);
 }
 
+bool straightLine ( std::vector<MVertex *> &l , MVertex *n1, MVertex *n2)
+{
+  // x = a * t + b
+  // x1 = b
+  // x2 = a + b
+  for (int i=0;i<l.size();i++)
+    {
+      MVertex *v = l[i];
+      double b = n1->x();
+      double a = n2->x() - b;
+      double t = (v->x() - b)/a;
+      double by = n1->y();
+      double ay = n2->y() - by;
+      double y = ay * t + by;
+      if (fabs(y-v->y()) > 1.e-11 * CTX.lc)
+	{
+	  //	  printf("coucou %g %g\n",y,v->y());
+	  return false;      
+	}
+    }
+
+  return true;
+  
+}
+
+void smoothInternalEdges ( GFace *gf , edgeContainer &edgeVertices)
+{
+  typedef std::map<std::pair<MVertex*, MVertex*> , std::vector<MElement*> > edge2tris;
+  edge2tris e2t;
+  for(unsigned int i = 0; i < gf->triangles.size(); i++){
+    MTriangle *t = gf->triangles[i];
+    for(int j = 0; j < t->getNumEdges(); j++){
+      MEdge edge = t->getEdge(j);
+      std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex());
+      e2t[p].push_back(t);
+    }
+  }
+  for (  edge2tris::iterator it = e2t.begin() ; it != e2t.end() ; ++it)
+    {
+      std::pair<MVertex*, MVertex*> edge = it->first;
+      std::vector<MVertex*> e1,e2,e3,e4,e;
+      std::vector<MElement*> triangles = it->second;
+
+      if (triangles.size() == 2)
+	{
+	  MVertex *n2 = edge.first; 
+	  MVertex *n4 = edge.second;
+	  MTriangle *t1 = (MTriangle*)triangles[0];
+	  MTriangle *t2 = (MTriangle*)triangles[1];
+	  MVertex *n1 = t1->getOtherVertex (n2,n4);
+	  MVertex *n3 = t2->getOtherVertex (n2,n4);
+	  if (n1<n2)
+	    e1 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n1,n2)];
+	  else
+	    e1 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n2,n1)];
+	  if (n2<n3)
+	    e2 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n2,n3)];
+	  else
+	    e2 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n3,n2)];
+	  if (n3<n4)
+	    e3 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n3,n4)];
+	  else
+	    e3 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n4,n3)];
+	  if (n4<n1)
+	    e4 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n4,n1)];
+	  else
+	    e4 = edgeVertices[std::make_pair<MVertex*, MVertex*> (n1,n4)];
+	  if (n2<n4)
+	    e = edgeVertices[std::make_pair<MVertex*, MVertex*> (n2,n4)];
+	  else
+	    e = edgeVertices[std::make_pair<MVertex*, MVertex*> (n4,n2)];
+	  
+	  if ((!straightLine ( e1,n1,n2) ||
+	       !straightLine ( e2,n2,n3) ||
+	       !straightLine ( e3,n3,n4) ||
+	       !straightLine ( e4,n4,n1) ))
+	      //	      &&  straightLine ( e,n2,n4))
+	    {
+	      for (int i=0 ; i < e.size() ; i++)
+		{
+		  double v = (double)(i+1) / (e.size()+1);
+		  double u = 1.-v;
+		  
+// 		  printf("%g %g\n",u,v);
+ 
+ 		  MVertex *vert  = (n2<n4)?e[i]:e[e.size()-i-1];
+ 		  MVertex *vert1 = (n1<n2)?e1[e1.size()-i-1]:e1[i];
+ 		  MVertex *vert3 = (n3<n4)?e3[i]:e3[e3.size()-i-1];
+		  MVertex *vert4 = (n4<n1)?e4[e4.size()-i-1]:e4[i];
+ 		  MVertex *vert2 = (n2<n3)?e2[i]:e2[e2.size()-i-1];
+		  
+		  
+// 		  printf("n1 %g %g\n",n1->x(),n1->y());
+// 		  printf("n2 %g %g\n",n2->x(),n2->y());
+// 		  printf("n3 %g %g\n",n3->x(),n3->y());
+// 		  printf("n4 %g %g\n",n4->x(),n4->y());
+		  
+// 		  printf("vert1 %g %g\n",vert1->x(),vert1->y());
+// 		  printf("vert2 %g %g\n",vert2->x(),vert2->y());
+// 		  printf("vert3 %g %g\n",vert3->x(),vert3->y());
+// 		  printf("vert4 %g %g\n",vert4->x(),vert4->y());
+		  
+// 		  printf("vert %g %g\n",vert->x(),vert->y());
+		  
+		  
+		  vert->x() = vert->x() + 0.05 * ( 
+		    (1.-u) * vert4->x() + u * vert2->x() +
+		    (1.-v) * vert1->x() + v * vert3->x() -
+		    ( (1.-u)*(1.-v) * n1->x() 
+		      + u * (1.-v) * n2->x() 
+		      + u*v*n3->x() 
+		      + (1.-u) * v * n4->x()) - vert->x());
+		    vert->y() = vert->y() + 0.05 * (
+		    (1.-u) * vert4->y() + u * vert2->y() +
+		    (1.-v) * vert1->y() + v * vert3->y() -
+		    ( (1.-u)*(1.-v) * n1->y() 
+		      + u * (1.-v) * n2->y() 
+		      + u*v*n3->y() 
+		      + (1.-u) * v * n4->y()) - vert->y());
+		  
+		    //		  printf("vert %g %g\n\n",vert->x(),vert->y());
+		}
+	      
+	    }
+	}
+    }
+  
+  
+}
+
+
 void SetOrderN(GModel *m, int order, bool linear, bool incomplete)
 {
   // replace all the elements in the mesh with second order elements
@@ -636,6 +767,13 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete)
   for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
     setHighOrder(*it, edgeVertices, faceVertices, linear, incomplete, nPts);
 
+
+  if (CTX.mesh.smooth_internal_edges)
+    for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it)
+      {
+	for (int i=0;i<10;i++)smoothInternalEdges ( *it , edgeVertices);
+      }  
+
   double t2 = Cpu();
   Msg(INFO, "Mesh second order complete (%g s)", t2 - t1);
   Msg(STATUS1, "Mesh");
diff --git a/benchmarks/2d/naca12_2d.geo b/benchmarks/2d/naca12_2d.geo
index 43358fce04..b754796ced 100644
--- a/benchmarks/2d/naca12_2d.geo
+++ b/benchmarks/2d/naca12_2d.geo
@@ -1,4 +1,4 @@
-lc = 0.001;
+lc = 0.2;
 lc2 = 0.2;
 lc3 = 0.05;
 Point(1) =  {1.000000e+00,0.000000e+00,0.000000e+00,lc}; 
@@ -224,5 +224,5 @@ Line Loop(10) = {2,3,4,1};
 Plane Surface(11) = {9,10};
 
 //Attractor Point{101,200} = {0.04,0.04,2};
-Attractor Line{1,2,3,4} = {1,.05,3};
+//Attractor Line{1,2,3,4} = {1,.05,3};
 Mesh.Algorithm = 2;
diff --git a/benchmarks/2d/wing-splines.geo b/benchmarks/2d/wing-splines.geo
index 0114a15d64..02492d17ef 100644
--- a/benchmarks/2d/wing-splines.geo
+++ b/benchmarks/2d/wing-splines.geo
@@ -1,6 +1,6 @@
 scale = 1 ;
 
-lc_wing = 0.01 * scale ;
+lc_wing = 0.04 * scale ;
 lc_box = 10 * scale ;
 
 Point(3895) = {1.177410e-02*scale,-2.768003e-03*scale,0,lc_wing};
-- 
GitLab