Gmsh划分三维体的步骤与划分GFace的步骤非常相似。其基本结构也相同,如GRegion继承自GEntity,GEntity隶属于一个GModel。网格的节点存储在GEntity的mesh_vertices中,划分的网格存储在GEdge,GFace,GRegion中。
Delaunay方法是三维非结构网格生成的主力算法,Gmsh的三维网格使用此方法。此处讨论使用Delaunay插入法划分三维实体,其前提是,构成实体的边界面,边已经划分完毕(此部分Gmsh调用TetGen实现)。就好像meshGFaceDelaunayInsertion处理GFace网格时,边界已经划分完成。具体划分代码主要包含在meshGRegion.cpp,meshGRegionDelaunayInsertion.cpp 中 。本文主要对GMesh划分GRegion的代码做一剖析,依然遵循"去繁从简,抓住主要步骤"。
1. 数据结构
classMTet4定义如下,
class MTet4 {
friend class MTet4Factory;//用于创建MTet
private:
bool deleted; //标识单元是否在查找Cavity过程中被删除。
double circum_radius; //外接球半径/期望尺寸
MTetrahedron *base; //存储四面体基本信息,继承自MElement
MTet4 *neigh[4];// 存储四个邻居
GRegion *gr;
}
circum_radius的赋值:前面也提过,这个处理很聪明。使我们要细化的单元永远位于数组的首位。Gmsh期望单元尺寸的计算比较复杂,后边再单独学习。
GMsh支持的单元类型如下图,本文仅关注Delaunay四面体。
2. 划分边界
将Mesh1D,Mesh2D划分得到的边界顶点四面体化,并且恢复边界。3D Delaunay恢复边界是比较复杂的,比插入算法本身难度大。划分边界使用下述函数,但是其内部调用了TetGen。至于为何Gmsh这部分代码不自己开发,不得而知。
3. 插入内部点
划分好边界之后,对不符合尺寸要求的四面体进行细化。在其外接球球心插入点,此部分操作与之前文章描述的Delaunay一致。如果仅划分三维体表面(Mesh.Algorithm3D 设置为“ Initial mesh only”),此部分代码不会执行。
4. Region划分全过程
请牢记GMsh划分网格的全过程:由GModel出发,划分Model下的所有Entity。Entity的具体类为GEdge,GFace,GRegion。
路漫漫其修远兮,共勉。
参考:
GMsh源码