[lecture du code source gmsh] Processus de maillage de bord

1. Le rôle de la division Edge

Dans l'analyse par éléments finis, les poutres et les fermes sont des unités unidimensionnelles divisées par des lignes. En même temps, le maillage de lignes constitue également la base du maillage de surfaces. Avant de diviser un visage, ses limites doivent d’abord être divisées. Comme le montre la figure ci-dessous, avant de mailler une plaque rectangulaire, il est nécessaire de diviser les quatre frontières et de générer plusieurs nœuds. Des éléments triangulaires ou quadrilatéraux sont générés à partir de ces nœuds.

p=p(u)=[x(u), y(u), z(u)], u\in [0, 1]

2. Géométrie différentielle : théorie des courbes

Avant de lire le code de maillage de bord gmsh, vous devez comprendre certaines connaissances en géométrie différentielle. En géométrie différentielle, les courbes sont exprimées sous forme d'équations paramétriques : 

p=p(u)=[x(u), y(u), z(u)] , u\in[0, 1]

Guide de premier ordre :\dot{p}=\frac{dp}{du}=[\frac{dx(u))}{du},\frac{dy(u))}{du}, \frac{dz(u)) }{toi} ]

Longueur de l'arc de courbe :s(u)=\int_{u{0}}^{u}\left |  \dot{p}(u))\right |du

Il faut comprendre qu'une courbe en géométrie différentielle est généralement représentée par une équation paramétrique. Les paramètres ont une plage de valeurs, 0 représente le point de départ de la courbe et 1 représente le point final. La courbe peut être différenciée pour obtenir la dérivée d'ordre n, et la longueur de l'arc peut être obtenue en intégrant le module de la dérivée du premier ordre. Comprendre ces concepts permet essentiellement de comprendre le code gmsh.

3. Code source de division de courbe gmsh

Le code des courbes de division gmsh est implémenté dans le fichier meshGEdge.cpp, et son entrée est la fonction void meshGEdge::operator()(GEdge *ge).

void meshGEdge::operator()(GEdge *ge)
{

  ge->model()->setCurrentMeshEntity(ge); //设置当前mesh的对象

  if(ge->degenerate(1)) { // 如果是退化边,直接标记完成
    ge->meshStatistics.status = GEdge::DONE;
    return;
  }

  // compute bounds
  Range<double> bounds = ge->parBounds(0); // 范围边的uv坐标范围0-1
  double t_begin = bounds.low(); // 0
  double t_end = bounds.high();  // 1

  // if a BL is ending at one of the ends, then create specific points
  std::vector<MVertex *> _addBegin, _addEnd;

  // integration to get length, number of points, etc
  int N;
  std::vector<IntPoint> Points;
  double a;
  int filterMinimumN;
  meshGEdgeProcessing(ge, t_begin, t_end, N, Points, a, filterMinimumN); // 计算需要划分的点数量N

  // look if we are doing the STL triangulation
  std::vector<MVertex *> &mesh_vertices = ge->mesh_vertices;

  // 如果不存在起始点就退出
  GPoint beg_p, end_p;
  if(!ge->getBeginVertex() || !ge->getEndVertex()) {
    Msg::Warning("Skipping curve with no begin or end point");
    return;
  }
  // 获取曲线的起点、终点
  else if(ge->getBeginVertex() == ge->getEndVertex() &&
          ge->getBeginVertex()->edges().size() == 1) {
    end_p = beg_p = ge->point(t_begin);
    Msg::Debug("Meshing periodic closed curve (tag %i, %i points)", ge->tag(),
               N);
  }
  else {
    // 多数情况下曲线有两个端点
    MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
    MVertex *v1 = ge->getEndVertex()->mesh_vertices[0];
    beg_p = GPoint(v0->x(), v0->y(), v0->z());
    end_p = GPoint(v1->x(), v1->y(), v1->z());
  }

  // do not consider the first and the last vertex (those are not
  // classified on this mesh edge)
  if(N > 1) {
    const double b = a / static_cast<double>(N - 1);
    int count = 1, NUMP = 1;
    IntPoint P1, P2;
    mesh_vertices.resize(N - 2); // 内部点的数量是N-2

      // 通过插值方式插入中间节点
    while(NUMP < N - 1) {
      P1 = Points[count - 1];
      P2 = Points[count];
      const double d = (double)NUMP * b;
      if((std::abs(P2.p) >= std::abs(d)) && (std::abs(P1.p) < std::abs(d))) {
        double const dt = P2.t - P1.t;
        double const dlc = P2.lc - P1.lc;
        double const dp = P2.p - P1.p;
        double const t = P1.t + dt / dp * (d - P1.p);
        SVector3 der = ge->firstDer(t);
        const double d = norm(der);
        double lc = d / (P1.lc + dlc / dp * (d - P1.p));
        GPoint V = ge->point(t);
        // 新生成的点保存下来
        mesh_vertices[NUMP - 1] =
          new MEdgeVertex(V.x(), V.y(), V.z(), ge, t, 0, lc);
        NUMP++;
      }
      else {
        count++;
      }
    }
    mesh_vertices.resize(NUMP - 1);
  }


  if(CTX::instance()->mesh.algo2d != ALGO_2D_BAMG &&
     CTX::instance()->mesh.algo2d != ALGO_2D_QUAD_QUASI_STRUCT &&
     CTX::instance()->mesh.algo2d != ALGO_2D_PACK_PRLGRMS)
    if(_addBegin.empty() && _addEnd.empty())
      filterPoints(ge, filterMinimumN - 2);

  std::vector<MLine *> &lines = ge->lines;

  // 将新生成的边保存下来
  for(std::size_t i = 0; i <= mesh_vertices.size(); i++) {
    MVertex *v0 =
      (i == 0) ? ge->getBeginVertex()->mesh_vertices[0] : mesh_vertices[i - 1];

    MVertex *v1 = (i == mesh_vertices.size()) ?
                    ge->getEndVertex()->mesh_vertices[0] :
                    mesh_vertices[i];
    lines.push_back(new MLine(v0, v1));
  }

  if(ge->getBeginVertex() == ge->getEndVertex() &&
     ge->getBeginVertex()->edges().size() == 1) {
    MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
    v0->x() = beg_p.x();
    v0->y() = beg_p.y();
    v0->z() = beg_p.z();
  }

  Msg::Info("Meshing curve %d (%s): %li interior vertices", ge->tag(),
             ge->getTypeString().c_str(), ge->mesh_vertices.size());

  // 标记划分结束
  ge->meshStatistics.status = GEdge::DONE;
}

Le processus consiste à obtenir la longueur de la ligne et le nombre de nœuds internes par intégration, et à générer des nœuds internes par interpolation. La longueur de la courbe et le nombre de points internes sont toutes des intégrations numériques réalisées via la fonction Intégration. Le principe est que la ligne récursive est utilisée à la place de la courbe, qui se rapproche de la courbe réelle. La profondeur minimale de la récursion est de 7 couches Même une ligne droite doit utiliser 129 points. Après avoir obtenu le nombre de points à insérer, une interpolation linéaire est effectuée pour générer des nœuds internes.

Je suppose que tu aimes

Origine blog.csdn.net/loveoobaby/article/details/131158922
conseillé
Classement