外观
Gmsh 生成 MSH2 网格
Gmsh 是一个开源网格生成工具。它既有图形界面,也可以直接通过命令行读取 .geo 几何脚本并导出网格文件。本文只整理一个最常用的入门工作流:写 .geo 几何脚本,定义物理组,然后导出 MSH2 格式的 .msh 网格。文中的命令以 Ubuntu 为例,但核心流程并不依赖 Ubuntu。
在 Ubuntu 上安装 Gmsh
Ubuntu 仓库里通常已经包含 Gmsh,可以直接安装:
sudo apt update
sudo apt install gmsh安装完成后检查版本:
gmsh --version如果只想打开图形界面,可以直接运行:
gmsh不过批量生成网格时,更常用的是命令行。
从 .geo 生成 MSH2 网格
假设有一个二维矩形区域,写成 rectangle.geo:
// rectangle.geo
lc = 0.1;
Point(1) = {0, 0, 0, lc};
Point(2) = {1, 0, 0, lc};
Point(3) = {1, 1, 0, lc};
Point(4) = {0, 1, 0, lc};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Curve Loop(1) = {1, 2, 3, 4};
Plane Surface(1) = {1};
Physical Curve("bottom") = {1};
Physical Curve("right") = {2};
Physical Curve("top") = {3};
Physical Curve("left") = {4};
Physical Surface("domain") = {1};生成二维网格并导出为 MSH2:
gmsh rectangle.geo -2 -format msh2 -o rectangle.msh几个参数的含义:
rectangle.geo:输入的几何脚本。-2:生成二维网格。如果是三维体网格,对应使用-3。-format msh2:指定输出为 Gmsh MSH 2.x 格式。-o rectangle.msh:指定输出文件名。
生成后可以用 Gmsh 打开检查网格:
gmsh rectangle.msh如果 .geo 文件里已经写了 Mesh 2;,也可以直接运行:
gmsh rectangle.geo -format msh2 -o rectangle.msh但在命令行里显式写 -2 更清楚,也更方便脚本化。
.geo 文件是什么
.geo 是 Gmsh 的几何脚本文件。它用文本描述几何点、线、面、体、网格尺寸、物理边界等信息。和在图形界面里点选建模相比,.geo 的优点是可重复、可版本管理,也方便批量修改参数。
一个 .geo 文件通常按下面的顺序组织:
- 定义参数,例如长度、半径、网格尺寸。
- 定义几何点。
- 用点连成线或曲线。
- 用线围成面。
- 必要时用面围成体。
- 定义物理组,给求解器识别边界和区域。
参数
.geo 支持变量,所以可以把常用尺寸写在开头:
width = 1.0;
height = 0.5;
lc = 0.05;后面就可以复用这些变量:
Point(1) = {0, 0, 0, lc};
Point(2) = {width, 0, 0, lc};
Point(3) = {width, height, 0, lc};
Point(4) = {0, height, 0, lc};点定义里的四个值分别是 x、y、z 和该点附近的目标网格尺寸。
点和线
点是几何的基础:
Point(1) = {0, 0, 0, 0.1};
Point(2) = {1, 0, 0, 0.1};直线用两个点定义:
Line(1) = {1, 2};括号里的 1 是实体编号,花括号里的 {1, 2} 是起点和终点的点编号。Gmsh 里很多对象都需要显式编号,编号只要在同一类对象里不冲突即可。
面
二维区域需要先用若干条线组成闭合环:
Curve Loop(1) = {1, 2, 3, 4};
Plane Surface(1) = {1};Curve Loop 里的线必须首尾相接,并且方向一致。如果某条线方向和闭合环方向相反,可以用负号引用:
Curve Loop(2) = {1, 2, -5, 4};这里的 -5 表示使用第 5 条线的反方向。
物理组
求解器通常不关心 Gmsh 里的几何编号,而是需要知道哪些边是入口、出口、墙面,哪个面是计算区域。这时用 Physical 组:
Physical Curve("inlet") = {4};
Physical Curve("outlet") = {2};
Physical Curve("wall") = {1, 3};
Physical Surface("fluid") = {1};导出的 .msh 文件会保留这些物理组。后续有限元或有限体积程序就可以按名字或编号读取边界条件。
网格尺寸
最简单的网格尺寸控制是在 Point 的第四个参数里给出:
lc = 0.1;
Point(1) = {0, 0, 0, lc};也可以给不同区域设置不同的尺寸。例如让左边更细、右边更粗:
Point(1) = {0, 0, 0, 0.02};
Point(2) = {1, 0, 0, 0.10};
Point(3) = {1, 1, 0, 0.10};
Point(4) = {0, 1, 0, 0.02};这类写法适合简单几何。更复杂的局部加密可以用 Gmsh 的 Field,但入门时先掌握点、线、面和物理组就够用了。
特殊几何体的表示
除了直线和多边形,.geo 也可以表示圆弧、圆、球这类常见几何。二维几何里最常见的是用 Circle 定义圆弧;三维实体则通常使用 OpenCASCADE 几何内核提供的 Sphere、Box 等内置构造。
圆弧和圆
圆弧用 Circle 表示:
Circle(1) = {2, 1, 3};它的含义是:从点 2 出发,以点 1 为圆心,到点 3 结束的一段圆弧。
一个完整圆通常拆成四段圆弧:
lc = 0.05;
Point(1) = {0, 0, 0, lc}; // 圆心
Point(2) = {1, 0, 0, lc};
Point(3) = {0, 1, 0, lc};
Point(4) = {-1, 0, 0, lc};
Point(5) = {0, -1, 0, lc};
Circle(1) = {2, 1, 3};
Circle(2) = {3, 1, 4};
Circle(3) = {4, 1, 5};
Circle(4) = {5, 1, 2};
Curve Loop(1) = {1, 2, 3, 4};
Plane Surface(1) = {1};这里 Curve Loop(1) 表示圆周,Plane Surface(1) 表示圆盘区域。
球
球是三维体,推荐使用 OpenCASCADE 内核的 Sphere:
SetFactory("OpenCASCADE");
r = 1.0;
lc = 0.1;
Sphere(1) = {0, 0, 0, r};
Mesh.CharacteristicLengthMin = lc;
Mesh.CharacteristicLengthMax = lc;
Physical Volume("ball") = {1};
Physical Surface("surface") = Boundary{ Volume{1}; };Sphere(1) = {0, 0, 0, r}; 表示以 (0, 0, 0) 为球心、半径为 r 的球体。因为球是体网格,所以生成网格时使用 -3:
gmsh sphere.geo -3 -format msh2 -o sphere.msh如果只想生成球面网格,可以使用 -2:
gmsh sphere.geo -2 -format msh2 -o sphere_surface.msh长方体
OpenCASCADE 也可以直接表示长方体:
SetFactory("OpenCASCADE");
Box(1) = {0, 0, 0, 1, 2, 0.5};
Physical Volume("box") = {1};
Physical Surface("boundary") = Boundary{ Volume{1}; };Box(1) = {x, y, z, dx, dy, dz}; 表示从 (x, y, z) 出发,尺寸为 dx、dy、dz 的长方体。它同样需要用 -3 生成三维体网格。
选择单元类型
Gmsh 的 -2 和 -3 只决定生成二维网格还是三维网格,不直接决定单元类型。默认情况下:
gmsh model.geo -2通常生成二维三角形网格。gmsh model.geo -3通常生成三维四面体网格。
如果要生成四边形或六面体,需要在 .geo 文件里额外控制。
三角形单元
二维面网格默认就是三角形,通常不需要额外设置:
Curve Loop(1) = {1, 2, 3, 4};
Plane Surface(1) = {1};生成命令:
gmsh model.geo -2 -format msh2 -o model.msh四边形单元
生成四边形网格的常用做法是对面进行重组:
Plane Surface(1) = {1};
Recombine Surface {1};也可以要求 Gmsh 尽量重组所有面:
Mesh.RecombineAll = 1;对于矩形、规则四边形这类结构化区域,更推荐配合 Transfinite 指定边上的节点数:
Transfinite Curve {1, 3} = 21;
Transfinite Curve {2, 4} = 11;
Transfinite Surface {1};
Recombine Surface {1};这里 Transfinite Curve {1, 3} = 21; 表示第 1、3 条边上放 21 个点。相对边的点数应保持一致,否则结构化四边形网格可能生成失败或质量较差。
四面体单元
三维体网格默认通常是四面体。只要定义好封闭体,并用 -3 生成即可:
Surface Loop(1) = {1, 2, 3, 4, 5, 6};
Volume(1) = {1};生成命令:
gmsh model.geo -3 -format msh2 -o model.msh如果使用 OpenCASCADE 的 Box、Sphere 等内置体,也可以直接生成四面体网格:
SetFactory("OpenCASCADE");
Box(1) = {0, 0, 0, 1, 1, 1};
Physical Volume("domain") = {1};六面体单元
六面体网格通常不能像四面体那样对任意复杂几何自动生成。常见方式是让几何保持结构化,然后使用 Transfinite 和 Recombine:
Transfinite Curve {1, 3, 5, 7} = 21;
Transfinite Curve {2, 4, 6, 8} = 11;
Transfinite Curve {9, 10, 11, 12} = 6;
Transfinite Surface "*";
Transfinite Volume {1};
Recombine Surface "*";
Recombine Volume {1};对于由二维面拉伸得到的三维体,可以在 Extrude 时直接要求重组,这通常更容易得到六面体网格:
Extrude {0, 0, 1} {
Surface{1};
Layers{10};
Recombine;
}这里 Layers{10}; 表示沿拉伸方向分 10 层,Recombine; 会把拉伸后的单元重组成四边形面和六面体体单元。
可以把这些控制理解成下面的趋势,而不是机械规则:
// 默认情况下,二维面网格通常是三角形
Plane Surface(1) = {1};
// 对规则二维区域,可尝试重组为四边形
Recombine Surface {1};
// 默认情况下,三维体网格通常是四面体
Volume(1) = {1};
// 对结构化三维体,可配合 Transfinite 和 Recombine 生成六面体
Transfinite Volume {1};
Recombine Volume {1};要注意,Recombine 和 Transfinite 不是“保证生成纯四边形/纯六面体”的开关。它们是否有效,取决于几何本身是否适合结构化,以及曲线、面、体之间的拓扑是否协调。实际使用时可以把规则几何优先做成四边形或六面体;复杂几何则通常先使用三角形或四面体,等计算确实需要结构化单元时再单独处理。
一个稍完整的示例
下面是一个带圆孔的矩形区域,常用于测试边界标记和局部网格尺寸:
// plate_with_hole.geo
lc_outer = 0.1;
lc_hole = 0.03;
Point(1) = {-1, -0.5, 0, lc_outer};
Point(2) = { 1, -0.5, 0, lc_outer};
Point(3) = { 1, 0.5, 0, lc_outer};
Point(4) = {-1, 0.5, 0, lc_outer};
Point(10) = {0, 0, 0, lc_hole};
Point(11) = {0.2, 0, 0, lc_hole};
Point(12) = {0, 0.2, 0, lc_hole};
Point(13) = {-0.2, 0, 0, lc_hole};
Point(14) = {0, -0.2, 0, lc_hole};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Circle(11) = {11, 10, 12};
Circle(12) = {12, 10, 13};
Circle(13) = {13, 10, 14};
Circle(14) = {14, 10, 11};
Curve Loop(1) = {1, 2, 3, 4};
Curve Loop(2) = {11, 12, 13, 14};
Plane Surface(1) = {1, 2};
Physical Curve("outer") = {1, 2, 3, 4};
Physical Curve("hole") = {11, 12, 13, 14};
Physical Surface("domain") = {1};生成 MSH2 网格:
gmsh plate_with_hole.geo -2 -format msh2 -o plate_with_hole.msh这个例子里 Plane Surface(1) = {1, 2}; 表示第一个曲线环是外边界,第二个曲线环是孔洞边界。圆孔附近的点使用更小的 lc_hole,所以孔周围网格会更密。
小结
用 Gmsh 生成 MSH2 网格,最常见的流程其实很固定:
- 用
.geo定义点、线、面、体。 - 用
Physical Curve、Physical Surface、Physical Volume标记边界和区域。 - 用
gmsh model.geo -2或gmsh model.geo -3生成二维或三维网格。 - 如果下游程序要求旧版格式,就加上
-format msh2。
入门阶段先把这条主线跑通就够了。等后续确实需要局部加密、边界层、结构化网格时,再单独引入 Field、Transfinite、Extrude 这些更细的控制。
版权所有
版权归属:Guisong Wu