Gmsh教程

1、几何和网格数据

# 导入Gmsh模块和sys模块用于处理命令行参数  
import gmsh  
import sys  
  
# 初始化Gmsh  
gmsh.initialize()  
  
# 检查命令行参数,如果提供了参数且不是以'-'开头,则尝试打开该文件  
if len(sys.argv) > 1 and sys.argv[1][0] != '-':  
    gmsh.open(sys.argv[1])  
else:  
    # 否则,创建一个简单的圆锥几何体并生成网格  
    gmsh.model.occ.addCone(1, 0, 0, 1, 0, 0, 0.5, 0.1)  # 创建一个圆锥,参数依次为:标签、底部中心点x,y,z、顶部中心点x,y,z、半径、高度  
    gmsh.model.occ.synchronize()  # 同步OCC内核与Gmsh模型  
    gmsh.model.mesh.generate()  # 生成网格  
  
# 打印当前模型的名称和维度  
print('Model ' + gmsh.model.getCurrent() + ' (' + str(gmsh.model.getDimension()) + 'D)')  
  
# 获取模型中的所有基本实体(点、曲线、表面、体积)  
entities = gmsh.model.getEntities()  
  
for e in entities:  
    dim, tag = e  # 分解出实体的维度和标签  
  
    # 获取实体的网格节点信息  
    nodeTags, nodeCoords, nodeParams = gmsh.model.mesh.getNodes(dim, tag)  
  
    # 获取实体的网格元素信息  
    elemTypes, elemTags, elemNodeTags = gmsh.model.mesh.getElements(dim, tag)  
  
    # 获取实体的类型和名称  
    type = gmsh.model.getType(dim, tag)  
    name = gmsh.model.getEntityName(dim, tag)  
    if len(name): name += ' '  
  
    # 打印实体信息  
    print("Entity " + name + str(e) + " of type " + type)  
  
    # 计算并打印网格中的节点和元素数量  
    numElem = sum(len(i) for i in elemTags)  
    print(" - Mesh has " + str(len(nodeTags)) + " nodes and " + str(numElem) + " elements")  
  
    # 获取并打印实体的上下相邻实体信息  
    up, down = gmsh.model.getAdjacencies(dim, tag)  
    if len(up):  
        print(" - Upward adjacencies: " + str(up))  
    if len(down):  
        print(" - Downward adjacencies: " + str(down))  
  
    # 检查实体是否属于物理组,并打印物理组信息  
    physicalTags = gmsh.model.getPhysicalGroupsForEntity(dim, tag)  
    if len(physicalTags):  
        s = ''  
        for p in physicalTags:  
            n = gmsh.model.getPhysicalName(dim, p)  
            if n: n += ' '  
            s += n + '(' + str(dim) + ', ' + str(p) + ') '  
        print(" - Physical groups: " + s)  
  
    # 检查实体是否是分区实体,并打印分区和父实体信息  
    partitions = gmsh.model.getPartitions(dim, tag)  
    if len(partitions):  
        print(" - Partition tags: " + str(partitions) + " - parent entity " + str(gmsh.model.getParent(dim, tag)))  
  
    # 打印构成实体网格的所有元素类型信息  
    for t in elemTypes:  
        name, dim, order, numv, parv, _ = gmsh.model.mesh.getElementProperties(t)  
        print(" - Element type: " + name + ", order " + str(order) + " (" + str(numv) + " nodes in param coord: " + str(parv) + ")")  
  
# 如果命令行参数中没有'-nopopup',则启动Gmsh GUI以显示模型  
if '-nopopup' not in sys.argv:  
    gmsh.fltk.run()  
  
# 清除所有模型数据  
gmsh.clear()  
  
# 结束Gmsh会话  
gmsh.finalize()

2、网格导入、离散实体、混合模型、地形网格

import gmsh  # 导入Gmsh库  
import sys  # 导入系统库,用于访问命令行参数  
import math  # 导入数学库  
  
gmsh.initialize()  # 初始化Gmsh库  
  
# 创建一个新的模型,命名为"x2"  
gmsh.model.add("x2")  
  
N = 100  # 设置网格的细分程度  
  
# 定义一个辅助函数,用于计算节点的标签  
def tag(i, j):  
    return (N + 1) * i + j + 1  
  
coords = []  # 用于存储节点坐标的列表  
nodes = []  # 用于存储节点标签的列表  
tris = []  # 用于存储三角形元素标签的列表  
lin = [[], [], [], []]  # 用于存储线性元素(边)标签的列表  
  
# 定义四个角点的标签  
pnt = [tag(0, 0), tag(N, 0), tag(N, N), tag(0, N)]  
  
# 遍历每个网格点,计算其坐标,并存储节点标签和坐标  
for i in range(N + 1):  
    for j in range(N + 1):  
        nodes.append(tag(i, j))  
        # 计算节点的x, y, z坐标,z坐标根据x和y的某种函数关系计算  
        coords.extend([float(i) / N, float(j) / N, 0.05 * math.sin(10 * float(i + j) / N)])  
        # 添加三角形元素  
        if i > 0 and j > 0:  
            tris.extend([tag(i - 1, j - 1), tag(i, j - 1), tag(i - 1, j)])  
            tris.extend([tag(i, j - 1), tag(i, j), tag(i - 1, j)])  
        # 添加边界线性元素  
        if (i == 0 or i == N) and j > 0:  
            lin[3 if i == 0 else 1].extend([tag(i, j - 1), tag(i, j)])  
        if (j == 0 or j == N) and i > 0:  
            lin[0 if j == 0 else 2].extend([tag(i - 1, j), tag(i, j)])  
  
# 添加四个离散实体(点)  
for i in range(4):  
    gmsh.model.addDiscreteEntity(0, i + 1)  
# 设置四个角点的坐标  
gmsh.model.setCoordinates(1, 0, 0, coords[3 * tag(0, 0) - 1])  
gmsh.model.setCoordinates(2, 1, 0, coords[3 * tag(N, 0) - 1])  
gmsh.model.setCoordinates(3, 1, 1, coords[3 * tag(N, N) - 1])  
gmsh.model.setCoordinates(4, 0, 1, coords[3 * tag(0, N) - 1])  
  
# 添加四条线性实体(边)  
for i in range(4):  
    gmsh.model.addDiscreteEntity(1, i + 1, [i + 1, i + 2 if i < 3 else 1])  
  
# 添加一个曲面实体  
gmsh.model.addDiscreteEntity(2, 1, [1, 2, -3, -4])  
  
# 添加节点和坐标到网格  
gmsh.model.mesh.addNodes(2, 1, nodes, coords)  
  
# 添加不同类型的元素到网格  
for i in range(4):  
    gmsh.model.mesh.addElementsByType(i + 1, 15, [], [pnt[i]])  # 添加点元素  
    gmsh.model.mesh.addElementsByType(i + 1, 1, [], lin[i])     # 添加线性元素  
  
# 添加三角形元素到网格  
gmsh.model.mesh.addElementsByType(1, 2, [], tris)  
  
# 重新分类节点和创建几何体  
gmsh.model.mesh.reclassifyNodes()  
gmsh.model.mesh.createGeometry()  
  
# 添加一个额外的几何体,用于演示如何添加更复杂的几何形状  
# ...(此处省略了具体的几何体添加代码,因为主要是重复的添加点和线,然后形成面和体的过程)  
  
# 同步几何体,准备网格化  
gmsh.model.geo.synchronize()  
  
# 设置网格化参数  
transfinite = False  # 是否使用Transfinite网格化方法  
transfiniteAuto = False  # 是否使用自动Transfinite网格化方法  
  
# 根据不同的网格化参数设置,进行网格化  
if transfinite:  
    # 使用Transfinite网格化方法  
    NN = 30  
    for c in gmsh.model.getEntities(1):  
        gmsh.model.mesh.setTransfiniteCurve(c[1], NN)  
    for s in gmsh.model.getEntities(2):  
        gmsh.model.mesh.setTransfiniteSurface(s[1])  
        gmsh.model.mesh.setRecombine(s[0], s[1])  
        gmsh.model.mesh.setSmoothing(s[0], s[1], 100)  
    gmsh.model.mesh.setTransfiniteVolume(v1)  
elif transfiniteAuto:  
    # 使用自动Transfinite网格化方法  
    gmsh.option.setNumber('Mesh.MeshSizeMin', 0.5)  
    gmsh.option.setNumber('Mesh.MeshSizeMax', 0.5)  
    gmsh.model.mesh.setTransfiniteAutomatic()  
else:  
    # 使用默认的网格化方法  
    gmsh.option.setNumber('Mesh.MeshSizeMin', 0.05)  
    gmsh.option.setNumber('Mesh.MeshSizeMax', 0.05)  
  
# 生成网格  
gmsh.model.mesh.generate(3)  
# 将网格写入文件  
gmsh.write('x2.msh')  
  
# 如果命令行参数中没有'-nopopup',则运行Gmsh的图形用户界面  
if '-nopopup' not in sys.argv:  
    gmsh.fltk.run()  
  
# 清理资源,结束Gmsh的使用  
gmsh.finalize()

3、后处理数据导入:基于列表

import gmsh
import sys

gmsh.initialize(sys.argv)

# 下面的循环尝试动态修改三角形坐标,
t1 = gmsh.view.add("A list-based view")
	triangle1 = [0., 1., 1., # x coordinates of the 3 triangle nodes
	0., 0., 1., # y coordinates of the 3 triangle nodes
	0., 0., 0.] # z coordinates of the 3 triangle nodes
	triangle2 = [0., 1., 0., 0., 1., 1., 0., 0., 0.]
	for step in range(0, 10) :
		triangle1.extend([10., 11. - step, 12.])  
		triangle2.extend([11., 12., 13. + step])
gmsh.view.addListData(t1, "ST", 2, triangle1 + triangle2)


line = [
	0., 1., # x coordinate of the 2 line nodes
		1.2, 1.2, # y coordinate of the 2 line nodes
		0., 0.    # z coordinate of the 2 line nodes
]
for step in range(0, 10) :

	line.extend([10. + step, 0., 0.,
		10. + step, 0., 0.])
	gmsh.view.addListData(t1, "VL", 1, line)

			gmsh.view.addListDataString(t1, [20., -20.], ["Created with Gmsh"])
			gmsh.view.addListDataString(t1, [0.5, 1.5, 0.],
				["A multi-step list-based view"],
				["Align", "Center", "Font", "Helvetica"])


			gmsh.view.option.setNumber(t1, "TimeStep", 5)
			gmsh.view.option.setNumber(t1, "IntervalsType", 3)
			ns = gmsh.view.option.getNumber(t1, "NbTimeStep")
			print("View " + str(t1) + " has " + str(ns) + " time steps")


				print("Value at (0.9, 0.1, 0)", gmsh.view.probe(t1, 0.9, 0.1, 0))


				gmsh.view.write(t1, "x3.pos")

t2 = gmsh.view.add("Second order quad")


quad = [0., 1., 1., 0., # x coordinates of the 4 quadrangle nodes
- 1.2, -1.2, -0.2, -0.2, # y coordinates of the 4 quadrangle nodes
0., 0., 0., 0.] # z coordinates of the 4 quadrangle nodes


quad.extend([1., 1., 1., 1., 3., 3., 3., 3., -3.])


gmsh.view.setInterpolationMatrices(t2, "Quadrangle", 9,
	[0, 0, 0.25, 0, 0, -0.25, -0.25, 0, 0.25,
	0, 0, 0.25, 0, 0, -0.25, 0.25, 0, -0.25,
	0, 0, 0.25, 0, 0, 0.25, 0.25, 0, 0.25,
	0, 0, 0.25, 0, 0, 0.25, -0.25, 0, -0.25,
	0, 0, -0.5, 0.5, 0, 0.5, 0, -0.5, 0,
	0, 0.5, -0.5, 0, 0.5, 0, -0.5, 0, 0,
	0, 0, -0.5, 0.5, 0, -0.5, 0, 0.5, 0,
	0, 0.5, -0.5, 0, -0.5, 0, 0.5, 0, 0,
	1, -1, 1, -1, 0, 0, 0, 0, 0],
	[0, 0, 0,
	2, 0, 0,
	2, 2, 0,
	0, 2, 0,
	1, 0, 0,
	2, 1, 0,
	1, 2, 0,
	0, 1, 0,
	1, 1, 0])

gmsh.view.addListData(t2, "SQ", 1, quad)
	gmsh.view.option.setNumber(t2, "AdaptVisualizationGrid", 1)
	gmsh.view.option.setNumber(t2, "TargetError", 1e-2)
	gmsh.view.option.setNumber(t2, "MaxRecursionLevel", 5)


if '-nopopup' not in sys.argv :
	gmsh.fltk.run()

	gmsh.finalize()

4、后处理数据导入:基于模型

import gmsh
import sys

gmsh.initialize(sys.argv)
创建第一个模型:
gmsh.model.add("simple model")
surf = gmsh.model.addDiscreteEntity(2)

gmsh.model.mesh.addNodes(2, surf, [1, 2, 3, 4],
                         [0., 0., 0., 1., 0., 0., 1., 1., 0., 0., 1., 0.])
gmsh.model.mesh.addElementsByType(surf, 2, [1, 2], [1, 2, 3, 1, 3, 4])

添加和可视化节点数据:

t1 = gmsh.view.add("Continuous")
for step in range(0, 10):
    gmsh.view.addHomogeneousModelData(
        t1, step, "simple model", "NodeData",
        [1, 2, 3, 4],  # tags of nodes
        [10., 10., 12. + step, 13. + step])  # data, per node

t2 = gmsh.view.add("Discontinuous")
for step in range(0, 10):
    gmsh.view.addHomogeneousModelData(
        t2, step, "simple model", "ElementNodeData",
        [1, 2],  
        [10., 10., 12. + step, 14., 15., 13. + step]) 
创建第二个模型:
gmsh.model.add("another model")
gmsh.model.occ.addBox(0, 0, 0, 1, 1, 1)
gmsh.model.occ.synchronize()
gmsh.model.mesh.generate(3)
获取和可视化第二个模型的节点数据:

nodes, coord, _ = gmsh.model.mesh.getNodes()
for step in range(11, 20):
    gmsh.view.addHomogeneousModelData(
        t1, step, "another model", "NodeData", nodes,
        [step * coord[i] for i in range(0, len(coord), 3)])

gmsh.view.write(t1, "x4_t1.msh")
gmsh.view.write(t2, "x4_t2.msh")

if '-nopopup' not in sys.argv:
    gmsh.fltk.run()

gmsh.finalize()

5、附加几何数据:参数化、法线、曲率

import gmsh
import sys
import math

gmsh.initialize(sys.argv)

gmsh.model.add("x5")
s = gmsh.model.occ.addSphere(0, 0, 0, 1)
b = gmsh.model.occ.addBox(0.5, 0, 0, 1.3, 2, 3)
gmsh.model.occ.fuse([(3, s)], [(3, b)])
gmsh.model.occ.synchronize()
gmsh.model.mesh.generate(2)

normals = []
curvatures = []
计算法线和曲率:
for e in gmsh.model.getEntities(2):

    s = e[1]

    tags, coord, param = gmsh.model.mesh.getNodes(2, s, True)

    norm = gmsh.model.getNormal(s, param)

    curv = gmsh.model.getCurvature(2, s, param)

    for i in range(0, len(coord), 3):
        normals.append(coord[i])
        normals.append(coord[i + 1])
        normals.append(coord[i + 2])
        normals.append(norm[i])
        normals.append(norm[i + 1])
        normals.append(norm[i + 2])
        curvatures.append(coord[i])
        curvatures.append(coord[i + 1])
        curvatures.append(coord[i + 2])
        curvatures.append(curv[i // 3])

可视化法线和曲率
vn = gmsh.view.add("normals")
gmsh.view.addListData(vn, "VP", len(normals) // 6, normals)
gmsh.view.option.setNumber(vn, 'ShowScale', 0)
gmsh.view.option.setNumber(vn, 'ArrowSizeMax', 30)
gmsh.view.option.setNumber(vn, 'ColormapNumber', 19)
vc = gmsh.view.add("curvatures")
gmsh.view.addListData(vc, "SP", len(curvatures) // 4, curvatures)
gmsh.view.option.setNumber(vc, 'ShowScale', 0)
参数化和坐标转换:
bounds = gmsh.model.getParametrizationBounds(1, 5)
N = 20
t = [bounds[0][0] + i * (bounds[1][0] - bounds[0][0]) / N for i in range(N)]
xyz1 = gmsh.model.getValue(1, 5, t)

uv = gmsh.model.reparametrizeOnSurface(1, 5, t, 1)
xyz2 = gmsh.model.getValue(2, 1, uv)

if max([abs(a - b) for (a, b) in zip(xyz1, xyz2)]) < 1e-12:
    gmsh.logger.write('Evaluation on curve and surface match!')
else:
    gmsh.logger.write('Evaluation on curve and surface do not match!', 'error')

if '-nopopup' not in sys.argv:
    gmsh.fltk.run()

gmsh.finalize()
注释代码

6、附加网格数据:积分点、雅可比矩阵和基函数

import gmsh
import sys

gmsh.initialize(sys.argv)

gmsh.model.add("x6")

添加几何体并生成网格:
gmsh.model.occ.addRectangle(0, 0, 0, 1, 0.1):在原点添加一个矩形,长度为1,高度为0.1。
gmsh.model.occ.synchronize():同步几何体,确保所有更改都被考虑。
gmsh.model.mesh.setTransfiniteAutomatic():设置网格生成为自动超限插值。
gmsh.model.mesh.generate(2):生成2维网格。
设置网格元素阶数:
elementOrder = 1
interpolationOrder = 2
gmsh.model.mesh.setOrder(elementOrder)

获取并打印网格元素信息:
def pp(label, v, mult):
    print(" * " + str(len(v) / mult) + " " + label + ": " + str(v))

elementTypes = gmsh.model.mesh.getElementTypes()
遍历所有元素类型,获取并打印每种元素类型的名称、维度、阶数、节点数、局部节点坐标、基本节点数等信息。
对于每种元素类型,获取并打印积分点、基函数及其梯度、雅可比矩阵的行列式等信息。
结束:
for t in elementTypes:
    elementName, dim, order, numNodes, localNodeCoord, numPrimNodes =\
    gmsh.model.mesh.getElementProperties(t)
    print("\n** " + elementName + " **\n")

    localCoords, weights =\
    gmsh.model.mesh.getIntegrationPoints(t, "Gauss" + str(interpolationOrder))
    pp("integration points to integrate order " +
       str(interpolationOrder) + " polynomials", localCoords, 3)

    numComponents, basisFunctions, numOrientations =\
    gmsh.model.mesh.getBasisFunctions(t, localCoords, "Lagrange")
    pp("basis functions at integration points", basisFunctions, 1)
    numComponents, basisFunctions, numOrientations =\
    gmsh.model.mesh.getBasisFunctions(t, localCoords, "GradLagrange")
    pp("basis function gradients at integration points", basisFunctions, 3)

    jacobians, determinants, coords =\
    gmsh.model.mesh.getJacobians(t, localCoords)
    pp("Jacobian determinants at integration points", determinants, 1)

gmsh.finalize()

7、其他网格数据:内部边缘和面

import sys  
import gmsh  # 导入gmsh库,用于几何建模和网格生成  
  
gmsh.initialize(sys.argv)  # 初始化gmsh环境  
  
gmsh.model.add("x7")  # 添加一个新的模型,命名为"x7"  
  
# 在模型中添加一个立方体,左下角位于原点,边长为1  
gmsh.model.occ.addBox(0, 0, 0, 1, 1, 1)  
gmsh.model.occ.synchronize()  # 同步几何实体,准备进行网格划分  
  
# 设置网格的最小尺寸为2  
gmsh.option.setNumber("Mesh.MeshSizeMin", 2.)  
gmsh.model.mesh.generate(3)  # 生成三维网格  
  
# 获取四面体元素类型  
elementType = gmsh.model.mesh.getElementType("tetrahedron", 1)  
edgeNodes = gmsh.model.mesh.getElementEdgeNodes(elementType)  # 获取四面体的边节点  
faceNodes = gmsh.model.mesh.getElementFaceNodes(elementType, 3)  # 获取四面体的面节点  
  
# 创建网格的边和面  
gmsh.model.mesh.createEdges()  
gmsh.model.mesh.createFaces()  
  
# 获取所有边的标签和方向  
edgeTags, edgeOrientations = gmsh.model.mesh.getEdges(edgeNodes)  
# 获取所有面的标签和方向,只考虑3维的面  
faceTags, faceOrientations = gmsh.model.mesh.getFaces(3, faceNodes)  
  
# 获取所有四面体的标签和节点标签  
elementTags, elementNodeTags = gmsh.model.mesh.getElementsByType(elementType)  
edges2Elements = {}  
faces2Elements = {}  
# 遍历所有边和面,记录每个边和面所属的四面体  
for i in range(len(edgeTags)): # 每个四面体有6条边  
    if not edgeTags[i] in edges2Elements:  
        edges2Elements[edgeTags[i]] = [elementTags[i // 6]]  
    else:  
        edges2Elements[edgeTags[i]].append(elementTags[i // 6])  
for i in range(len(faceTags)): # 每个四面体有4个面  
    if not faceTags[i] in faces2Elements:  
        faces2Elements[faceTags[i]] = [elementTags[i // 4]]  
    else:  
        faces2Elements[faceTags[i]].append(elementTags[i // 4])  
  
# 添加一个新的离散实体,维度为2  
s = gmsh.model.addDiscreteEntity(2)  
  
maxElementTag = gmsh.model.mesh.getMaxElementTag()  # 获取当前最大的元素标签  
uniqueFaceTags = set()  
tagsForTriangles = []  
faceNodesForTriangles = []  
# 遍历所有面的标签,为每一个面创建一个三角形元素  
for i in range(len(faceTags)):  
    if faceTags[i] not in uniqueFaceTags:  
        uniqueFaceTags.add(faceTags[i])  
        tagsForTriangles.append(faceTags[i] + maxElementTag)  
        faceNodesForTriangles.append(faceNodes[3 * i])  
        faceNodesForTriangles.append(faceNodes[3 * i + 1])  
        faceNodesForTriangles.append(faceNodes[3 * i + 2])  
# 获取三角形元素类型  
elementType2D = gmsh.model.mesh.getElementType("triangle", 1)  
# 添加三角形元素到模型中  
gmsh.model.mesh.addElementsByType(s, elementType2D, tagsForTriangles,  
                                  faceNodesForTriangles)  
  
# 打印每个三角形连接的四面体  
for t in tagsForTriangles:  
    print("triangle " + str(int(t)) + " is connected to tetrahedra " +  
          str(faces2Elements[t - maxElementTag]))  
  
# 获取所有边的标签和节点  
edgeTags, edgeNodes = gmsh.model.mesh.getAllEdges()  
# 获取所有面的标签和节点,只考虑3维的面  
faceTags, faceNodes = gmsh.model.mesh.getAllFaces(3)  
  
# 如果命令行参数中没有'-nopopup',则启动gmsh的图形界面  
if '-nopopup' not in sys.argv:  
    gmsh.fltk.run()  
  
gmsh.finalize()  # 清理并退出gmsh环境