上一节主要涉及Gmsh的使用入门和几何模型构建简介中,我们讲了Gmsh构建几何的一些基本知识,下面主要侧重于Gmsh在网格生成方面的操作。
网格生成的不同算法
在Gmsh中,当几何模型构建完成后,我们可以使用函数gmsh.model.mesh.generate() 来生成网格,可以通过gmsh.model.mesh.setSize(gmsh.model.getEntities(0), 0.1) 来再次定义尺寸。接下来,我们可以设定不同的算法来生成网格。
python
import gmsh
gmsh.initialize()
gmsh.model.add("model13")
gmsh.model.occ.addBox(1,1,1,1,1,1)
gmsh.model.occ.synchronize()
gmsh.model.mesh.setSize(gmsh.model.getEntities(0), 0.05)
gmsh.option.setNumber("Mesh.Algorithm3D",1)
gmsh.model.mesh.generate(3)
gmsh.fltk.run()
gmsh.finalize()
如果想要生成二维三角形网格,则\textcolor{blue}{generate()}函数中输入参数2,如果生成三维四面体网格,则输入参数3。在这里,我们使用\textcolor{blue}{gmsh.option.setNumber}来设置全局选项,而其他类似的函数如\textcolor{blue}{gmsh.option.setString} 和\textcolor{blue}{gmsh.option.setBool} 可以用来设置字符串和布尔类型的选项的值。
上面的代码中设置了网格生成所使用的算法,\textcolor{blue}{gmsh.option.setNumber("Mesh.Algorithm3D", 1)} 设置了生成四面体网格的算法为Delaunay算法,不同的数字选项表示不同的网格生成算法。在这里,\textcolor{blue}{"Mesh.Algorithm3D"}是用于控制三维网格生成过程中所使用的算法。下面是一些常见的选项值及其含义:
0 - 使用自动算法:Gmsh 将自动选择适合问题的算法。这是默认值。
1 - 使用Delaunay算法,这是一种常见的三角剖分算法,可以用于生成三维表面网格。适用于一般的几何形状。
2 - 使用Frontal-Delaunay 算法:这是一种更快速的 Delaunay 算法变体。适用于具有大量几何实体的复杂三维模型。
3 - 使用 Frontal-Delaunay 算法与局部优化:这个选项在 Frontal-Delaunay 算法的基础上引入了局部优化步骤,以改善网格质量。适用于需要更好网格质量的复杂三维模型。
结果如下:
当然,除了 gmsh.option.setNumber ,还有一些选项参数,如 "Mesh.Algorithm" 用于设置二维网格生成的算法选项,"Geometry.PointNumbers" 用于设置是否显示标签值,"Mesh.Smoothing" 用于设置平滑选项的参数, "Mesh.CharacteristicLengthFactor" 用于设置生成网格的特征长度的因子等。下面的代码中我们将会演示这几种参数的用法。
超限网格与结构网格的生成
超限网格
超限网格是在传统网格方法之外发展出的一种网格生成技术。传统网格方法通常将计算区域划分为规则形状的网格单元,且每个单元具有相同的大小和形状。而超限网格方法则不限制网格单元的形状和大小,允许在计算区域中使用不规则形状的网格单元。
python
import gmsh
import gmsh_geo_tools as tools
gmsh.initialize()
gmsh.model.add('model14')
vertices = [
[0, 0], [2, 0], [2, 1], [1.2, 1.3], [0.7, 1.3], [0, 1]
]
# 调用顶点坐标生成二维网格的API
tools.model_made_point(vertices)
# 均匀插点
gmsh.model.geo.mesh.setTransfiniteCurve(2, 20)
gmsh.model.geo.mesh.setTransfiniteCurve(4, 6)
gmsh.model.geo.mesh.setTransfiniteCurve(5, 6)
gmsh.model.geo.mesh.setTransfiniteCurve(6, 10)
# 等比数列插点
gmsh.model.geo.mesh.setTransfiniteCurve(3, 30, "Progression", 1.1)
gmsh.model.geo.mesh.setTransfiniteCurve(1, 30, "Progression", -1.1)
# 生成超限网格
gmsh.model.geo.mesh.setTransfiniteSurface(1, "Right", [1, 2, 3, 6])
# 将三角形网格合并成四边形网格
gmsh.model.geo.mesh.setRecombine(2, 1)
gmsh.model.geo.synchronize()
# 设置平滑选项的参数
# gmsh.option.setNumber("Mesh.Smoothing", 1000)
# # 设置是否显示标签值
# gmsh.option.setNumber("Geometry.PointNumbers", 1)
gmsh.model.mesh.generate(2)
gmsh.fltk.run()
gmsh.finalize()
上述代码中,调用了tools文件夹(放置了上一章中我定义的用方程生成网格的API)里的model_made_point ,先生成了一个二维图形,然后使用 setTransfiniteCurve 函数在每条边上进行均匀插点,如果加入Progression 参数与相应的值,就会按照等比数列进行插点,即新插入的点到上一个点的距离是到上两个点的距离的给定的值的倍数。之后,调用setTransfiniteSurface 生成超限网格,由于超限插值是在曲面四边形上进行插值,因此需要给定四个顶点。之后我们可以使用setRecombine函数将三角形网格合并成为四边形网格,其中参数含义分别是维数2和需要合并的面1。
同时,我们还可以测试 "Mesh.Smoothing" 和 "Geometry.PointNumbers" 的功能,将32和34行代码注释后,注释与非注释分别得到以下结果:
不难发现,图b比a的网格线更平滑且有点的标签值。
结构网格
结构网格是一种规则的网格结构,也称作均匀网格或正交网格。在结构网格中,计算区域被划分为规则的网格单元,每个单元具有相同的形状和大小。结构网格通常由矩形或立方体网格单元组成,其边界与坐标轴平行。
利用超限插值,我们可以使用Gmsh生成结构网格
python
import gmsh
import gmsh_geo_tools as tools
gmsh.initialize()
gmsh.model.add("model15")
vertices = [
[0, 0], [1, 0], [1, 1], [0, 1]
]
# 调用顶点坐标生成二维网格的API
tools.model_made_point(vertices)
# 对每一边进行均匀插值
for i in range(1, 5):
gmsh.model.geo.mesh.setTransfiniteCurve(i, 10)
# 生成超限网格
gmsh.model.geo.mesh.setTransfiniteSurface(1, "Right")
# 合并为四边形网格
gmsh.model.geo.mesh.setRecombine(1, 1)
gmsh.model.geo.synchronize()
gmsh.model.mesh.generate(2)
gmsh.write("quadrilateralMesh.off")
gmsh.fltk.run()
gmsh.finalize()
由于该几何体本身就是个四边形,所以setTransfiniteSurface 不需要给定四个点的编号。同样的我们对setRecombine进行测试,注释21行,分别得到结构三角形网格和结构四边形网格如下:
网格尺寸场
除了在每点处设置网格尺寸,Gmsh还提供了使用Field设置网格尺寸的方法,通过定义尺寸场类型和相应的尺寸场参数,可以生成不同尺寸分布的网格,我们举例来进行说明。
python
import gmsh
gmsh.initialize()
gmsh.model.add("model16")
lc = 0.15
gmsh.model.occ.addRectangle(0, 0, 0, 1, 1, 1)
gmsh.model.occ.synchronize()
# 定义 Box 尺寸场,标号为1
gmsh.model.mesh.field.add("Box", 1)
# 设定参数
gmsh.model.mesh.field.setNumber(1, "VIn", lc/15)
gmsh.model.mesh.field.setNumber(1, "VOut", lc)
gmsh.model.mesh.field.setNumber(1, "XMin", 0.4)
gmsh.model.mesh.field.setNumber(1, "YMin", 0.4)
gmsh.model.mesh.field.setNumber(1, "XMax", 0.6)
gmsh.model.mesh.field.setNumber(1, "YMax", 0.6)
gmsh.model.mesh.field.setNumber(1, "Thickness", 0.3)
# 将尺寸场设置为背景网格
gmsh.model.mesh.field.setAsBackgroundMesh(1)
gmsh.model.mesh.generate(2)
gmsh.fltk.run()
gmsh.finalize()
结果如下:
上述代码中,我们先定义了一个Box 尺寸场,编号为1,然后调用setNumbers 设置参数(15到21代码中,第一个参数都是尺寸场的编号,第三个参数都是要设置的参数值),通过XMin 、XMax 、YMin 和YMax 定义了一个矩形区域(三维还可以给定ZMin ,ZMax 定义立方体),只有在该区域内的网格尺寸会受到尺寸场的影响。并且给定了区域内外的过渡层厚度Thickness ,在区域内外设置不同的网格尺寸VIn ,VOut 。然后使用setAsBackgroundMesh将尺寸场设置为背景网格,其作用是在生成网格时,确保整个几何模型都受到尺寸场的影响(这意味着,尺寸场所定义的细化和粗化策略将应用于整个几何模型,无论是内部区域还是边界区域)。效果如上图所示。
不同的Field 有着不同的功能,有些Field 还需要结合使用,例如Distance 与Threshold。
python
gmsh.model.mesh.field.add("Distance",2)
gmsh.model.mesh.field.setNumbers(2,"PointsList",[1])
gmsh.model.mesh.field.setNumbers(2,"CurvesList",[2])
gmsh.model.mesh.field.setNumber(2,"Sampling",100)
gmsh.model.mesh.field.add("Threshold", 3)
gmsh.model.mesh.field.setNumber(3, "InField", 2)
gmsh.model.mesh.field.setNumber(3, "SizeMin", lc / 30)
gmsh.model.mesh.field.setNumber(3, "SizeMax", lc)
gmsh.model.mesh.field.setNumber(3, "DistMin", 0.15)
gmsh.model.mesh.field.setNumber(3, "DistMax", 0.5)
gmsh.model.mesh.field.setAsBackgroundMesh(3)
Distance 尺寸场并不提供网格尺寸,它只计算区域内其他点到传入其中的点,边,面的距离,而Threshold 尺寸场可以通过InField 参数传入Distance 的数据,根据到给定点,边,面的距离设置相应的网格尺寸,结果如下所示。
上述代码中,先定义一个Distance 尺寸场,接下来,用代码设置了尺寸场的特定参数。通过
setNumbers 函数,将编号为1的点添加到尺寸场的"PointsList"中,将编号为2的曲线添加到尺寸场的"CurvesList"中,以便通过这些几何实体控制尺寸场的行为,然后设置了尺寸场的一些数值参数,包括 "Sampling" (采样点数),这里设置为100,以决定在离散几何实体的情况下生成网格的质量。接下来,创建一个Threshold 尺寸场,使用setNumber 函数设置各个参数,包括 "InField" (参考尺寸场的ID)设置为2、 "SizeMin" (最小尺寸)设置为lc / 30、"SizeMax" (最大尺寸)设置为lc,"DistMin" (最小距离)设置为0.15,"DistMax"(最大距离)设置为0.5。
Gmsh还提供了NathEval尺寸场,可以直接通过输入数学函数作为尺寸场生成网格。
python
gmsh.model.mesh.field.add("MathEval",4)
gmsh.model.mesh.field.setString(4, "F","Cos(4*3.14*x) * Sin(4*3.14*y) / 10 + 0.101")
gmsh.model.mesh.field.setAsBackgroundMesh(4)
上述代码中,我们在setString 中采用关键字 "F" 来设置尺寸场的函数表达式。字符串"Cos(43.14 x) * Sin(43.14y) / 10+0.101"表示尺寸场的函数表达式。该表达式使用了数学函数cos和sin,其中4*3.14代表周期为2的四分之一正弦波和余弦波。将该表达式除以10然后加上0.101用于对尺寸进行缩放和偏移,以便在生成网格时产生所需的尺寸。
注,输入的函数只能是Gmsh里所提供顶点数学函数,自定义的函数无法输入。
效果如下:
到目前位置我们已经定义了四种尺寸场,接下来我们可以使用Min尺寸场将所有尺寸场整合到一起。
python
gmsh.model.mesh.field.add("Min", 5)
gmsh.model.mesh.field.setNumbers(5, "FieldsList", [1,3,4])
gmsh.model.mesh.field.setAsBackgroundMesh(5)
Min 尺寸场可将其他尺寸场以尺寸场列表 "FieldsList" 的形式输入,取所有尺寸场的网格尺寸最小值,并将输入的尺寸场合并,如下图所示。