From 2bd27f429ca134bd4f092083f8fbcf5ad53d8a99 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sun, 23 Jan 2011 15:48:26 +0000
Subject: [PATCH] basic 2D boundary layers (using old code)

---
 Mesh/BoundaryLayers.cpp | 104 +++++++++++++++++++++++++++++-----------
 Mesh/meshGEdge.cpp      |  89 +++++-----------------------------
 2 files changed, 86 insertions(+), 107 deletions(-)

diff --git a/Mesh/BoundaryLayers.cpp b/Mesh/BoundaryLayers.cpp
index 760a7b3c91..9320f81680 100644
--- a/Mesh/BoundaryLayers.cpp
+++ b/Mesh/BoundaryLayers.cpp
@@ -4,6 +4,7 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include "GModel.h"
+#include "MLine.h"
 #include "MTriangle.h"
 #include "MQuadrangle.h"
 #include "BoundaryLayers.h"
@@ -38,16 +39,17 @@ static void addExtrudeNormals(std::vector<T*> &elements, int invert,
   else{ // get extrusion data from Gouraud-shaded element normals
     for(unsigned int i = 0; i < elements.size(); i++){
       MElement *ele = elements[i];
-      for(int j = 0; j < ele->getNumFaces(); j++){
-        MFace fac = ele->getFace(j);
-        SVector3 n = fac.normal();
-        if(invert) n *= -1.;
-        if(n[0] || n[1] || n[2]){
-          double nn[3] = {n[0], n[1], n[2]};
-          for(int k = 0; k < fac.getNumVertices(); k++){
-            MVertex *v = fac.getVertex(k);
-            ExtrudeParams::normals->add(v->x(), v->y(), v->z(), 3, nn);
-          }
+      SVector3 n(0, 0, 0);
+      if(ele->getDim() == 2)
+        n = ele->getFace(0).normal();
+      else if(ele->getDim() == 1) // FIXME only valid in XY-plane
+        n = crossprod(ele->getEdge(0).tangent(), SVector3(0, 0, 1));
+      if(invert) n *= -1.;
+      if(n[0] || n[1] || n[2]){
+        double nn[3] = {n[0], n[1], n[2]};
+        for(int k = 0; k < ele->getNumVertices(); k++){
+          MVertex *v = ele->getVertex(k);
+          ExtrudeParams::normals->add(v->x(), v->y(), v->z(), 3, nn);
         }
       }
     }
@@ -58,8 +60,29 @@ int Mesh2DWithBoundaryLayers(GModel *m)
 {
   std::set<GFace*> sourceFaces, otherFaces;
   std::set<GEdge*> sourceEdges, otherEdges;
-  std::map<int, bool> sourceFaceInvert;
-  std::map<int, int> sourceUseView;
+  std::map<int, bool> sourceFaceInvert, sourceEdgeInvert;
+  std::map<int, int> sourceFaceUseView, sourceEdgeUseView;
+
+  // 2D boundary layers
+  for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++){
+    GEdge *ge = *it;
+    if(ge->getNativeType() == GEntity::GmshModel && 
+       ge->geomType() == GEntity::BoundaryLayerCurve){
+      ExtrudeParams *ep = ge->meshAttributes.extrude;
+      if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == COPIED_ENTITY){
+        GEdge *from = m->getEdgeByTag(std::abs(ep->geo.Source));
+        if(!from){
+          Msg::Error("Unknown source curve %d for boundary layer", ep->geo.Source);
+          return 0;
+        }
+        if(ep->geo.Source < 0) sourceEdgeInvert[from->tag()] = true;
+        if(ep->mesh.ViewIndex >= 0) sourceEdgeUseView[from->tag()] = ep->mesh.ViewIndex;
+        sourceEdges.insert(from);
+      }
+    }
+  }
+
+  // 3D boundary layers
   for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
     GFace *gf = *it;
     if(gf->getNativeType() == GEntity::GmshModel && 
@@ -72,14 +95,16 @@ int Mesh2DWithBoundaryLayers(GModel *m)
           return 0;
         }
         if(ep->geo.Source < 0) sourceFaceInvert[from->tag()] = true;
-        if(ep->mesh.ViewIndex >= 0) sourceUseView[from->tag()] = ep->mesh.ViewIndex;
+        if(ep->mesh.ViewIndex >= 0) sourceFaceUseView[from->tag()] = ep->mesh.ViewIndex;
         sourceFaces.insert(from);
         std::list<GEdge*> e = from->edges();
         sourceEdges.insert(e.begin(), e.end());
       }
     }
   }
-  if(sourceFaces.empty()) return 0;
+
+  if(sourceEdges.empty() && sourceFaces.empty())
+    return 0;
 
   // compute set of non-source edges and faces
   for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++)
@@ -96,27 +121,48 @@ int Mesh2DWithBoundaryLayers(GModel *m)
   // extrusion)
   std::for_each(sourceFaces.begin(), sourceFaces.end(), orientMeshGFace());
 
-  // compute a normal field for all the source faces
+  // compute a normal field for all the source edges or faces
   if(ExtrudeParams::normals) delete ExtrudeParams::normals;
   ExtrudeParams::normals = new smooth_data();
-  for(std::set<GFace*>::iterator it = sourceFaces.begin(); 
-      it != sourceFaces.end(); it++){
-    GFace *gf = *it;
-    int invert = sourceFaceInvert.count(gf->tag());
-    OctreePost *octree = 0;
+  
+  if(sourceFaces.empty()){
+    for(std::set<GEdge*>::iterator it = sourceEdges.begin(); 
+        it != sourceEdges.end(); it++){
+      GEdge *ge = *it;
+      int invert = sourceEdgeInvert.count(ge->tag());
+      OctreePost *octree = 0;
 #if defined(HAVE_POST)
-    if(sourceUseView.count(gf->tag())){
-      int index = sourceUseView[gf->tag()];
-      if(index >= 0 && index < PView::list.size())
-        octree = new OctreePost(PView::list[index]);
-      else
-        Msg::Error("Unknown View[%d]: using normals instead", index);
+      if(sourceEdgeUseView.count(ge->tag())){
+        int index = sourceEdgeUseView[ge->tag()];
+        if(index >= 0 && index < PView::list.size())
+          octree = new OctreePost(PView::list[index]);
+        else
+          Msg::Error("Unknown View[%d]: using normals instead", index);
+      }
+#endif
+      addExtrudeNormals(ge->lines, invert, octree);
     }
+  }
+  else{
+    for(std::set<GFace*>::iterator it = sourceFaces.begin(); 
+        it != sourceFaces.end(); it++){
+      GFace *gf = *it;
+      int invert = sourceFaceInvert.count(gf->tag());
+      OctreePost *octree = 0;
+#if defined(HAVE_POST)
+      if(sourceFaceUseView.count(gf->tag())){
+        int index = sourceFaceUseView[gf->tag()];
+        if(index >= 0 && index < PView::list.size())
+          octree = new OctreePost(PView::list[index]);
+        else
+          Msg::Error("Unknown View[%d]: using normals instead", index);
+      }
 #endif
-    addExtrudeNormals(gf->triangles, invert, octree);
-    addExtrudeNormals(gf->quadrangles, invert, octree);
+      addExtrudeNormals(gf->triangles, invert, octree);
+      addExtrudeNormals(gf->quadrangles, invert, octree);
+    }
   }
-  if(sourceUseView.empty())
+  if(sourceEdgeUseView.empty() && sourceFaceUseView.empty())
     ExtrudeParams::normals->normalize();
 
   // set the position of boundary layer points using the smooth normal
diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp
index 89ea5c5e04..0d6f918420 100644
--- a/Mesh/meshGEdge.cpp
+++ b/Mesh/meshGEdge.cpp
@@ -20,66 +20,6 @@ typedef struct {
   double t, lc, p;
 } IntPoint;
 
-struct xi2lc {
-  double xi, lc;
-  xi2lc(const double &_xi, const double _lc)
-    : xi(_xi), lc(_lc)
-  { 
-  }
-  bool operator < (const xi2lc &other) const
-  {
-    return xi < other.xi; 
-  }
-};
-
-static std::vector<xi2lc> interpLc;
-
-static void buildInterpLc(const std::vector<IntPoint> &lcPoints)
-{
-  IntPoint p;
-  interpLc.clear();
-  for(unsigned int i = 0; i < lcPoints.size(); i++){
-    p = lcPoints[i];
-    interpLc.push_back(xi2lc(p.t, p.lc));
-  }
-}
-
-static double F_Lc_usingInterpLc(GEdge *ge, double t)
-{
-  std::vector<xi2lc>::iterator it = std::lower_bound(interpLc.begin(),
-                                                     interpLc.end(), xi2lc(t, 0));
-  double t1 = it->xi;
-  double l1 = it->lc;
-  it++;
-  if(it == interpLc.end()) return l1;
-  double t2 = it->xi;
-  double l2 = it->lc;
-  double l = l1 + ((t - t1) / (t2 - t1)) * (l2 - l1);
-  return l;
-}
-
-static double F_Lc_usingInterpLcBis(GEdge *ge, double t)
-{
-  GPoint p = ge->point(t);
-  double lc_here;
-
-  Range<double> bounds = ge->parBounds(0);
-  double t_begin = bounds.low();
-  double t_end = bounds.high();
-
-  SVector3 der = ge->firstDer(t);
-  const double d = norm(der);
-
-  if(t == t_begin)
-    lc_here = BGM_MeshSize(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
-  else if(t == t_end)
-    lc_here = BGM_MeshSize(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
-  else
-    lc_here = BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z());
-
-  return d / lc_here;
-}
-
 static double F_Lc(GEdge *ge, double t)
 {
   GPoint p = ge->point(t);
@@ -122,7 +62,7 @@ static double F_Lc_aniso(GEdge *ge, double t)
 
   SVector3 der = ge->firstDer(t);
 
-  double lSquared = dot (der,lc_here,der);
+  double lSquared = dot(der, lc_here, der);
 
   //  der.normalize();
   //  printf("in the function %g n %g %g\n", sqrt(lSquared),der.x(),der.y());
@@ -367,25 +307,18 @@ void meshGEdge::operator() (GEdge *ge)
     N = ge->meshAttributes.nbPointsTransfinite;
   }
   else{
-    /*if(CTX::instance()->mesh.lcIntegrationPrecision > 1.e-2){ JF says this code was a test but it is not useful
-      std::vector<IntPoint> lcPoints;
-      Integration(ge, t_begin, t_end, F_Lc_usingInterpLcBis, lcPoints, 
-                  CTX::instance()->mesh.lcIntegrationPrecision);
-      buildInterpLc(lcPoints);
-      a = Integration(ge, t_begin, t_end, F_Lc_usingInterpLc, Points, 1.e-8);
-    }
-    else*/{
-      if (CTX::instance()->mesh.algo2d == ALGO_2D_BAMG) 
-	a = Integration(ge, t_begin, t_end, F_Lc_aniso, Points,
-			CTX::instance()->mesh.lcIntegrationPrecision);
-      else
-	a = Integration(ge, t_begin, t_end, F_Lc, Points,
-			CTX::instance()->mesh.lcIntegrationPrecision);
-    }
+    if (CTX::instance()->mesh.algo2d == ALGO_2D_BAMG) 
+      a = Integration(ge, t_begin, t_end, F_Lc_aniso, Points,
+                      CTX::instance()->mesh.lcIntegrationPrecision);
+    else
+      a = Integration(ge, t_begin, t_end, F_Lc, Points,
+                      CTX::instance()->mesh.lcIntegrationPrecision);
     N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.));
   }
-  
-  if(CTX::instance()->mesh.algoRecombine == 1 && N%2 == 0) N++;
+
+  // force odd number of points for if blossom is used for
+  // recombination
+  if(CTX::instance()->mesh.algoRecombine == 1 && N % 2 == 0) N++;
 
   //  printFandPrimitive(ge->tag(),Points);
 
-- 
GitLab