Tetgen软件学习和使用

Tetgen安装

以下用到的所有安装包下载链接

Windows系统下安装

1.下载好tetgen的源代码

从CSDN链接或者官网连接直接下载即可。

2. 进行源代码编译

我使用的是Visual Studio 2013进行的编译,操作如下:
用VS2013进行源代码编译教程
添加好下载的源码,如下图所示:
用VS2013进行源代码编译教程
然后点击项目名称右键,选择如下图所示的操作,添加_CRT_SECURE_NO_WARNINGS,就可以进行编译了,不然会报错。
用VS2013进行源代码编译教程
编译好后,会生成tetgen.exe文件,如下图:
用VS2013进行源代码编译教程
上面这些做好就可以使用了这个tetgen.exe 进行操作了。

Ubuntu操作系统下进行安装

在终端直接一条命令就可以:

sudo apt install tetgen

ubuntu系统和wsl子系统下安装tetgen

TetGen简单使用

1. Windows操作系统下使用

管理员命令打开PowerShell:

Wndows下TetGen使用教程
运行如下两行代码:

cd D:\tetgen\
.\tetgen.exe -p example.poly

其结果如下:

Opening example.poly.
Delaunizing vertices...
Delaunay seconds:  0
Creating surface mesh ...
Surface mesh seconds:  0.001
Constrained Delaunay...
Constrained Delaunay seconds:  0
Removing exterior tetrahedra ...
Exterior tets removal seconds:  0
Optimizing mesh...
Optimization seconds:  0

Writing example.1.node.
Writing example.1.ele.
Writing example.1.face.
Writing example.1.edge.

Output seconds:  0.004
Total running seconds:  0.005

Statistics:

  Input points: 28
  Input facets: 23
  Input segments: 44
  Input holes: 2
  Input regions: 2

  Mesh points: 28
  Mesh tetrahedra: 68
  Mesh faces: 160
  Mesh faces on facets: 50
  Mesh edges on segments: 44

Wndows下TetGen使用教程

2. Ubuntu操作系统下使用

切换到example所在的目录,输入命令行:

tetgen -p example.poly

结果如下:

Opening example.poly.
Delaunizing vertices...
Delaunay seconds:  0
Creating surface mesh ...
Surface mesh seconds:  0
Constrained Delaunay...
Constrained Delaunay seconds:  0
Removing exterior tetrahedra ...
Exterior tets removal seconds:  0
Optimizing mesh...
Optimization seconds:  0

Writing example.1.node.
Writing example.1.ele.
Writing example.1.face.
Writing example.1.edge.

Output seconds:  0
Total running seconds:  0

Statistics:

  Input points: 28
  Input facets: 23
  Input segments: 44
  Input holes: 2
  Input regions: 2

  Mesh points: 28
  Mesh tetrahedra: 68
  Mesh faces: 160
  Mesh faces on facets: 50
  Mesh edges on segments: 44

Ubuntu操作系统下使用

3. 文件在Windows下用Tetview打开

命令行操作如下:

.\tetview-win.exe example.1.ele

效果是这样的:
Windows下使用tetview

TetGen详细操作

TetGen文件格式说明

下表列出TetGen使用的所有格式。所有文件都是ASCII码形式,可能包含有以#为前缀的
注释。点,四面体,面,洞和最小体积约束编号必须是连贯的,开始编号为1或者0。然而,
所有的输入文件必须是一致的。当读.node(.poly,.smesh)时,TetGen自动检测你选择的文
件。当其他程序调用TetGen时,如果你想要对象的编码从0开始,那么使用-z命令。

文件类型输入或者输出属性
.nodeinput/output节点列表文件
.polyinputPLC.
.smeshinput/outputPLC.
.eleinput/output四面体文件
.faceinput/output三角形面文件
.edgeinput/output边界
.volinput最大体积列表
.varinput约束列表
.neighoutputA list of neighbors

1. .node文件

第一行:<点个数><维数(3)><属性个数><边界标识(0或者1)>
剩下的行为点列表:
<点编号><x><y><z>[属性][边界标识]

例如:

   158373  3  0  1  #表示有158373个点,维数是三维,属性个数为0,边界标识为1
   1    -10000  -10000  -10000    1   # 表示点号为1,三维坐标是(-10000,-10000,-10000),边界标识是1
   2    -10000  10000  -10000    1
   3    10000  10000  -10000    1
   4    10000  -10000  -10000    1
   5    -10000  -10000  10000    1
   6    -10000  10000  10000    1
   7    10000  10000  10000    1
   8    10000  -10000  10000    1
   9    -10000  -10000  0    1
  10    -10000  10000  0    1
  • 属性为与点关联的浮点型物理量值(例如:质量、导电性等),并不加修改的复制到格网中。如果-p,-q,-a或者-i是选择的,每个Steiner点添加到格网中默认属性值为0。
  • 如果指明了’-w’(权重Delaunay四面体剖分)项,第一个属性为相应点的权重。
  • 如果第一行的第四部分值为1,文件中最后一列为边界标识。边界标识用于识别边界点(点在PLC面上),除了TetGen禁用了-B了开关,否则TetGen生成的.node文件包含边界标识。

边界标识在输出文件.node文件是选择如下:

  • 如果在输入文件中点指定了非零边界标识,那么它在输出文件中将有相同的标识。
  • 另外,如果节点在PLC表面上带有一个非零边界标识,那么这个表面上的节点将指定相同的标识。如果节点在若干的表面上,节点的边界标识在这些表面标识中任意选择。
  • 如果节点在格网的边界上,那么节点的标识指定为1。
  • 其他点分配标识为0
  • TetGen可以决定那些点在边界上,输入边界标识为0(或者没有使用标识)将结果在输出所有点的边界标识为1。

2. .poly文件

  • 一个.poly文件表示一个PLC(piecewise linear complex [分段线性复合体])作为附加信息。尽管这儿没有限制PLC的表面TetGen需要PLC表示的完整的面边界格网范围。
  • .poly文件格式包含了四部分,点列表面列表洞(体)点集列表范围属性列表。前三部分是必须的,第四部分是可选的。

这四部分详细描述如下:

  1. 节点列表 所有节点的列表和它与.node具有完全相同的个数。<点个数>可以设置为0,指明这些点集存放在分离的.node文件中。

    第一行: <点个数> <维数 (3)> <属性个数> <边界标识 (0 or 1)>
    下面为点的列表:
    <点编号> <x> <y> <z> [属性] [边界标识]
    ...
    
  2. 面列表 每个面包含一个共面直线图(PSLG, planar straight line graph),它是一个可以包含线段,单点和洞的多边形。多边形(polygons)列表包含面。每个多边形有n个角点,n≥1。它可以退化,当n=1时表示点,当n=2时表示线段。格式如下:

    某一行: <多边形个数s> [洞个数] [边界标识]
    下面是多边形列表:
    <角点个数> <角点 1> <角点 2> ... <角点 #>
    ...
    下面是洞列表
    <洞编号> <x> <y> <z>
    ...
    
 ```shell
 # poly文件示例
 # Part 1 - node list 第一部分:点列表
 # node count, 3 dim , no attribute, no boundary marker
 256	3	0	0
 1	36.0	0.0	0
 2	35.95663642338621	1.7664362757870484	0
 3	35.82665016019909	3.528617051864182	0
 4	35.61035435873212	5.282297080393023	0
 5	35.308270094516296	7.023251592580617	0
 6	34.92112511500358	8.7472864765175	0
 7	34.44985208635952	10.450248381160645	0
 8	33.89558634658875	12.128034722119923	0
 9	33.25966317040632	13.776603565143231	0
 10	32.54361455244396	15.391983363490155	0
 11	31.74916551654078	16.970282525735914	0
 ...
 # Part 2 - face list  第二部分:面列表
 130	1  # 面个数  有边界标识
 # facet count, boundary marker
 1	0	1  # 一个多边形,没有洞,边界标识1, 下面是这么多点构成的一个圆柱面
 128	1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	17	18	19	20	21	22	23	24	25	         26	27	28	29	30	31	32	33	34	35	36	37	38	39	40	41	42	43	44	45	46	47	48	49	50	51	52	53	54	55	56	57	58	59	60	61	62	63	64	65	66	67	68	69	70	71	72	73	74	75	76	77	78	79	80	81	82	83	84	85	86	87	88	89	90	91	92	93	94	95	96	97	98	99	100	101	102	103	104	105	106	107	108	109	110	111	112	113	114	115	116	117	118	119	120	121	122	123	124	125	126	127	128	
 1	0	4  # 一个多边形,没有洞,边界标识4
 4	1	2	130	129  # 4个点(1,2,130,129)构成的面
 1	0	4
 4	2	3	131	130
 1	0	4
 4	3	4	132	131
 1	0	4
 4	4	5	133	132
 1	0	4
 4	5	6	134	133
...

下图就是该文件的具体图例
在这里插入图片描述

3. .smesh文件

4. .ele文件

5. .face文件

    # face文件示例
    8800  1   # 8800个面,没有洞,有边界标识
    1   2595  1194  2593    4  # 第一个面  三个节点组成  边界标识为4
    2   1908  1210  1906    4
    3   1203  2595  2597    4
    4    427   429  2335    4
    5     57  4340  5196    1
    6   3345  1714  3347    4
    7    648  2622  3220    1
    8   1338   582   581    4
    9    471  3845  3846    4
    ...

6. .edge文件

7. .vol文件

8. mtr文件

9. var文件

10. .neigh文件

Tetgen生成输入文件程序例子

  • 看了前面这么多介绍,可能大家还是不怎么会生成自己的模型文件,这里给出一个生成自己模型文件的python程序,大家可以按照自己的需要来修改。
import os
import sys
import time
import math
import numpy as np

nn=4
dlz = [0 for col in range(nn)]
dlz=[20000, 2000, 10000, 20000]
dlx=40000
dly=40000
sumdlz=sum(dlz)

print('The length of the cuboid %0.3f' % dlx)
print('The width of the cuboid is %0.3f' % dly)
print('The height of the cuboid is %0.3f' % sumdlz)

boxname = 'cuboid' + '-' + str(dlx) + '-' + str(dly)  + '-' + str(sumdlz) + '.poly'
boxf = open(boxname,'w')

nx=100
ny=50
nodenum_part=2*(nx+ny)
nodenum=(nn+1)*nodenum_part
dlz1=np.append(0,dlz)

for i in range(0, nn):
   dlz1[i+1]=dlz1[i]+dlz1[i+1]
       

#save the information of nodes  储存所有节点信息
node = [[0 for col in range(4)] for row in range(nodenum)]
for i in range(0,nodenum):
   node[i] = [i+1,0,0,0]  # 第一个值储存节点编号 

for i in range(0, len(dlz1)):
   for j in range(0, int(ny/2)):  # 底面上节点的三维坐标
       node[i*nodenum_part+j][1:] = [dlx/2, j*dly/ny, dlz1[i]-sumdlz]
   for j in range(int(ny/2), int(ny/2+nx/2)):
       node[i*nodenum_part+j][1:] = [dlx/2-(j-int(ny/2))*dlx/nx, dly/2, dlz1[i]-sumdlz]
   for j in range(int(ny/2+nx/2), int(ny/2+nx)):
       node[i*nodenum_part+j][1:] = [-(j-int(nx/2+ny/2))*dlx/nx, dly/2, dlz1[i]-sumdlz]
   for j in range(int(ny/2+nx), int(ny+nx)):
       node[i*nodenum_part+j][1:] = [-dlx/2, dly/2-(j-int(nx+ny/2))*dly/ny, dlz1[i]-sumdlz]
       
   for j in range(int(nx+ny), int(nx+ny+ny/2)):  
       node[i*nodenum_part+j][1:] = [-dlx/2, -(j-int(nx+ny))*dly/ny, dlz1[i]-sumdlz]
   for j in range(int(nx+ny+ny/2), int(nx+ny+ny/2+nx/2)):
       node[i*nodenum_part+j][1:] = [-dlx/2+(j-int(nx+ny+ny/2))*dlx/nx, -dly/2, dlz1[i]-sumdlz]
   for j in range(int(nx+ny+ny/2+nx/2), int(nx+ny+ny/2+nx)):
       node[i*nodenum_part+j][1:] = [(j-int(nx+ny+nx/2+ny/2))*dlx/nx, -dly/2, dlz1[i]-sumdlz]
   for j in range(int(nx+ny+ny/2+nx), int(nx+ny+ny+nx)):
       node[i*nodenum_part+j][1:] = [dlx/2, -dly/2+(j-int(nx+ny+nx+ny/2))*dly/ny, dlz1[i]-sumdlz]
       
#save the information of facets   存储面的信息     
facenum = nn*nodenum_part + nn + 1  # 侧面的面单元和每个立方体的上底面和下底面的和 
   
faceAll = [[0 for col in range(6)] for row in range(facenum-nn-1)]  # 初始化面的数据
  
for j in range(0,nn):
   for i in range(0, nodenum_part-1):
       faceAll[j*nodenum_part+i] = [4, j*nodenum_part+i+1, j*nodenum_part+i+2, j*nodenum_part+i+2+nodenum_part, j*nodenum_part+i+1+nodenum_part, j+nn+2]
   faceAll[(j+1)*nodenum_part-1] = [4, (j+1)*nodenum_part, j*nodenum_part+1, (j+1)*nodenum_part + 1, (j+2)*nodenum_part, j+nn+2]


face = [[0 for col in range(5)] for row in range(facenum-nn-1)]  # 初始化面
faceMark = [[0 for col in range(3)] for row in range(facenum-nn-1)]  # 初始化面标记
   
for i in range(0,facenum-nn-1):
   face[i] = faceAll[i][0:5]
   faceMark[i] = [1,0,faceAll[i][-1]]


meshsize = [-1] # the size of mesh 


numVolumMark = nn # nn regions 
SolventMark = [4, 0.1, 1, 10] # the region mark is 1
region = [[0 for col in range(6)] for row in range(numVolumMark)]
for i in range(0,len(region)):
   region[i] = [i+1,0,0,0,0,0]

for i in range(0,len(region)):
   region[i][1] = (node[i*nodenum_part][1] + node[int(nodenum_part/2+(i+1)*nodenum_part)][1])/2        
   region[i][2] = (node[i*nodenum_part][2] + node[int(nodenum_part/2+(i+1)*nodenum_part)][2])/2
   region[i][3] = (node[i*nodenum_part][3] + node[int(nodenum_part/2+(i+1)*nodenum_part)][3])/2
   region[i][4] = SolventMark[i]
   region[i][5] = meshsize[0]
   
line = '# Part 1 - node list\n'
boxf.write(line)
line = '# <# of points> <dimension 3> <# of attributes> <boundary markers>\n'
boxf.write(line)
line = str(nodenum) + '\t' + '3' + '\t' + '0' + '\t' + '1' + '\n'
boxf.write(line)
for i in range(0, nodenum):
   line = str(node[i][0]) + '\t' + str(node[i][1]) + '\t' + str(node[i][2]) + '\t' + str(node[i][3]) + '\t' + str(0) + '\n'
   boxf.write(line)
   
line = '# Part 2 - face list\n'
boxf.write(line)
line = str(facenum) + '\t' + '1' + '\n'
boxf.write(line)
line = '# facet count, boundary marker\n'
boxf.write(line)
line = '#(Eg.) one polygon, no hole, boundary market is 1\n'
boxf.write(line)

for j in range(0,nn):
   line = str(1) + '\t' + str(0) + '\t' + str(j+1) + '\n'
   boxf.write(line)
   line = str(nodenum_part) + '\t'
   for i in range(j*nodenum_part, (j+1)*nodenum_part):
       line += str(i+1) + '\t'
   line += '\n'
   boxf.write(line)
   for k in range(j*nodenum_part, (j+1)*nodenum_part):
       line = str(faceMark[k][0]) + '\t' + str(faceMark[k][1]) + '\t' + str(faceMark[k][2]) + '\n'
       boxf.write(line)
       line = str(face[k][0]) + '\t' + str(face[k][1]) + '\t' + str(face[k][2]) + '\t' + str(face[k][3]) + '\t' + str(face[k][4]) + '\n'
       boxf.write(line)

# the boundary mark of the top facet is 
line = str(1) + '\t' + str(0) + '\t' + str(nn+1) + '\n'
boxf.write(line)
line = str(nodenum_part) + '\t'
for i in range(nn*nodenum_part, (nn+1)*nodenum_part):
   line += str(i+1) + '\t'
line += '\n'
boxf.write(line)
       
       

line = '# Part 3 - hole list\n'
boxf.write(line)
line = '# <# of polygons> <# of holes> <boundary marker>\n'
boxf.write(line)
line = '0' + '\n'
boxf.write(line)


line = '# Part 4 - region list\n'
boxf.write(line)
line = '#<region #> <x> <y> <z> <region attribute> <region volume constraint>\n'
boxf.write(line)
line = str(numVolumMark) + '\n'
boxf.write(line)
for i in range(0,len(region)):
       line = str(region[i][0]) + '\t' + str(region[i][1]) + '\t' + str(region[i][2]) + '\t' + \
       str(region[i][3]) + '\t' + str(region[i][4]) + '\t' + str(region[i][5]) + '\n'
       boxf.write(line)
boxf.close()
   
   
#boxmeshfile = 'cylinder_' + str(dx) + '_' + str(dy) + '-' + 'refined1'+ '.mesh'
cmd = 'tetgen.exe -pq1.3iaAV -k ' + boxname
os.system(cmd)

该程序运行完成后会生成如下几个文件:
在这里插入图片描述
其效果图是这样:

在这里插入图片描述
在这里插入图片描述

  • 大家在看懂程序后可以生成自己想要的任意层状介质的poly文件,和剖分文件。希望这个程序对大家学习和使用有所帮助。
  • 33
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值