我维护了一个小小的Python包,该包可以在用于网格表示的不同格式之间进行转换
这些文件可能会变得很大,因此在使用Python读取文件时,有效地执行操作非常重要。
其中一个最常用的格式是MSH从GMSH。不幸的是,它的数据布局可以说不是最好的。一个示例文件:
$MeshFormat 2.2 0 8 $EndMeshFormat $Nodes 8 1 -0.5 -0.5 -0.5 2 0.5 -0.5 -0.5 3 -0.5 0.5 -0.5 4 0.5 0.5 -0.5 5 -0.5 -0.5 0.5 6 0.5 -0.5 0.5 7 -0.5 0.5 0.5 8 0.5 0.5 0.5 $EndNodes $Elements 2 1 4 2 1 11 1 2 3 5 2 4 2 1 11 2 5 6 8 $EndElements
对于$Nodes
:
第一个数字(8
)是要跟随的节点数。
在每个节点行中,第一个数字是索引(格式的其余部分ugh实际上并不需要),然后跟随三个空间坐标。
到目前为止,我还没有提出比islice
s 更好的 任何东西for
,这很慢。
# The first line is the number of nodes line = next(islice(f, 1)) num_nodes = int(line) # points = numpy.empty((num_nodes, 3)) for k, line in enumerate(islice(f, num_nodes)): points[k, :] = numpy.array(line.split(), dtype=float)[1:] line = next(islice(f, 1)) assert line.strip() == '$EndNodes'
对于$Elements
:
第一个数字(2
)是要跟随的元素数。
在每个元素行中,第一个数字是index,然后是元素类型的枚举(4
用于四面体)。然后跟随该元素的整数标记的数量(2
在每种情况下,即1
和11
)。对应于元素类型,该行的最后几个条目对应于形成元素的$Node
索引 -对于四面体,最后四个条目。
由于标签的数量可能因元素而异(即,行与行之间)不同,就像元素类型和节点索引的数量一样,每行可以具有不同数量的整数。
对于$Nodes
和$Elements
,都希望能有快速阅读此数据的任何帮助。
这是一个基于NumPy的怪异实现:
f = open('foo.msh') f.readline() # '$MeshFormat\n' f.readline() # '2.2 0 8\n' f.readline() # '$EndMeshFormat\n' f.readline() # '$Nodes\n' n_nodes = int(f.readline()) # '8\n' nodes = numpy.fromfile(f,count=n_nodes*4, sep=" ").reshape((n_nodes,4)) # array([[ 1. , -0.5, -0.5, -0.5], # [ 2. , 0.5, -0.5, -0.5], # [ 3. , -0.5, 0.5, -0.5], # [ 4. , 0.5, 0.5, -0.5], # [ 5. , -0.5, -0.5, 0.5], # [ 6. , 0.5, -0.5, 0.5], # [ 7. , -0.5, 0.5, 0.5], # [ 8. , 0.5, 0.5, 0.5]]) f.readline() # '$EndNodes\n' f.readline() # '$Elements\n' n_elems = int(f.readline()) # '2\n' elems = numpy.fromfile(f,sep=" ")[:-1] # $EndElements read as -1 # This array must be reshaped based on the element type(s) # array([ 1., 4., 2., 1., 11., 1., 2., 3., 5., 2., 4., # 2., 1., 11., 2., 5., 6., 8.])