python如何做数据切片(Python有限元网格文件数据读取与转换)(1)

从开源中汲取营养,我们就是站在了巨人的肩膀上!

导读:一个CAE软件,需要从CAD生成网格,使用求解器求解,最后通过可视化进行数据分析。整个过程中,每一步都不是容易的事。而我们只能从事其中一部分。

最近,我在写有限元程序DinoFem过程中,就遇到了很多这方面的问题。

今天就推荐一个读取和转换工具,Meshio。

内容:

1、meshio 解决了什么问题

2、meshio的使用

3、points

4、cells

5、网格数据的读取

6、其他函数

7、创建和输出

官方的文档写得过于简单,但是从源码可以看到详细的使用方法。本文就介绍一下meshio的基本操作。

python如何做数据切片(Python有限元网格文件数据读取与转换)(2)

1、meshio 解决了什么问题

就在前天,我们国产自主CAE联盟的群里,大家都比较困扰于格式问题。确实,现在整个制造业、建筑业、或者其他行业,大部分都在使用3D模型来进行产品设计,甚至于已经进入了生产运营的管理。例如现在比较火的#数字孪生#更是把3D模型和各方面的控制系统等都融合在了一起。

而,就3D模型而言,整个都是国外传到中国的,所有的格式,都是国外的标准。在这一块,我们就有先天不足。作为国际化的世界,我们可能无法左右标准,但是至少得做到有熟悉的开源的格式转换工具。

就网格来说,meshio解决的是与各种标准格式互相支持的问题。包括读取,写入,转换等。

支持:Abaqus,ANSYS,AVS-UCD,FLAC3D,VTK,Nastran等等。见下图

python如何做数据切片(Python有限元网格文件数据读取与转换)(3)

meshio所支持的格式

文件格式,就像我们的饮食习惯,更是文化的一部分。而文化是思想的承载者。

2、meshio使用

官方的教程很简单,主要介绍的内容都在第一个案例里,其他的,本质上是字典操作。

import meshio mesh = meshio.read( filename, # string, os.PathLike, or a buffer/open file file_format="stl", # optional if filename is a path; inferred from extension ) # mesh.points, mesh.cells, mesh.cells_dict, ... # mesh.vtk.read() is also possible

但是,实际上使用却没有那么简单,倒是也没有那么难。

Meshio是由一些字典和字典操作,数据操作组成的。主要的内容在_mesh.py文件中有详细的说明。实际上,每一个格式的支持,代码中都写得很详细。

python如何做数据切片(Python有限元网格文件数据读取与转换)(4)

3、points

我们先看第一个点的信息。以inp文件为例

import meshio m = meshio.read("fem_test003.inp") print(type(m.points),m.points.shape)

输出信息:

<class 'numpy.ndarray'> (227, 3)

说明这个points就是按顺序排的一个点列,numpy的ndarray类型。数据有227个点。三维坐标。

4、cells

cells的信息同样可以读取,但是,cells有点不一样,我们可以先打印出cells信息看看

[<meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 1>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 4>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 1>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: line, num cells: 2>, <meshio CellBlock, type: triangle, num cells: 18>, <meshio CellBlock, type: triangle, num cells: 18>, <meshio CellBlock, type: triangle, num cells: 18>, <meshio CellBlock, type: triangle, num cells: 139>, <meshio CellBlock, type: triangle, num cells: 139>, <meshio CellBlock, type: triangle, num cells: 18>, <meshio CellBlock, type: triangle, num cells: 18>, <meshio CellBlock, type: triangle, num cells: 18>, <meshio CellBlock, type: triangle, num cells: 12>, <meshio CellBlock, type: triangle, num cells: 8>, <meshio CellBlock, type: triangle, num cells: 12>, <meshio CellBlock, type: triangle, num cells: 12>, <meshio CellBlock, type: triangle, num cells: 12>, <meshio CellBlock, type: tetra, num cells: 627>]

输出的是一个信息表,第一个是类的类型,CellBlock类。

type,名称

num,数量

我们看一下这个CellBlock类的定义

class CellBlock(collections.namedtuple("CellBlock", ["type", "data"])): def __repr__(self): return f"<meshio CellBlock, type: {self.type}, num cells: {len(self.data)}>"

其实就是一个字典。是collection吓的namedtuple类。

print打印的输出形式,也在代码中写得很清楚,和我们的输出完全一致。

5、网格数据的读取

主要读取的数据是cell_sets_dict属性

a=[e for e in m.cell_sets_dict.keys()] print(a[0:10]) print(a[10:20]) print(a[20:30]) print(a[30:40]) print(a[40:])

我们可以打印这个属性的key列表

['face1', 'face2', 'face3', 'Line1', 'Line2', 'Line3', 'Line4', 'Line5', 'Line6', 'Line7']

['Line8', 'Line9', 'Line10', 'Line11', 'Line12', 'Line13', 'Line14', 'Line15', 'Line16', 'Line17']

['Line18', 'Line19', 'Line20', 'Line21', 'Line22', 'Line23', 'Line24', 'Line25', 'Line26', 'Line27']

['Line28', 'Line29', 'Line30', 'Line31', 'Line32', 'Line33', 'Surface1', 'Surface2', 'Surface3', 'Surface4']

['Surface5', 'Surface6', 'Surface7', 'Surface8', 'Surface9', 'Surface10', 'Surface11', 'Surface12', 'Surface13', 'Volume1']

从这个列表可以看到每一个字典的对象。例如,我们要查找face1的指标

python如何做数据切片(Python有限元网格文件数据读取与转换)(5)

图中可以看到,结果是一系列的三角单元所在的指标。

我们需要从三角单元指标中去查。

print(m.get_cells_type("triangle"))

get_cells_type函数,就是提取每一个类型这里是triangle的所有的编号,和对应的点列。每一个面由点列组成。

python如何做数据切片(Python有限元网格文件数据读取与转换)(6)

我们可以查找原来的inp文件对应一下

python如何做数据切片(Python有限元网格文件数据读取与转换)(7)

可以看到前三排是和刚才的输出是一致的。不同的是,指标要减少1个,因为python是从0开始排的。

我们主要的操作,就在这个字典中进行。

6、其他函数

python如何做数据切片(Python有限元网格文件数据读取与转换)(8)

prune函数,做了一些清理工作。

python如何做数据切片(Python有限元网格文件数据读取与转换)(9)

python如何做数据切片(Python有限元网格文件数据读取与转换)(10)

第一步,清理了低维数的数值(remove_lower_dimensional_cells),第二步,是去掉了离散的点(remove_orphaned_nodes)。

还有去掉z方向的值的,将3D转化成2D的函数。

def prune_z_0(self, tol=1.0e-13): """Remove third (z) component of points if it is 0 everywhere (up to a tolerance). """

具体使用的时候,可以根据需求,再去看一下代码。

7、创建和输出

创建和输出,官方文档有一些简单的介绍。应该是够用了。

python如何做数据切片(Python有限元网格文件数据读取与转换)(11)

8、结束

做数值仿真是需要大量的工作的。从CAD到计算再到后处理。每一个工作都需要大量的技术人员参与。而且门槛都不低。

,