Win10环境下FiPy使用Gmsh3D导入Gmsh 3D网格报错如何解决
FiPy Gmsh3D接口导入3D网格全场景报错问题
环境配置
- 操作系统:Windows 10
- 软件版本:FiPy 3.4.2.1、Python 3.7.9、Gmsh 4.8.4
执行代码
mesh = Gmsh3D(join(output,'case_1.msh'),communicator=serialComm)
首次执行报错
首次调用触发GmshException,核心报错为:
Gmsh hasn't produced any cells! Check your Gmsh code.
对应Gmsh运行输出日志:
Info : Running 'gmsh C:\Users\pcnou\AppData\Local\Temp\tmppouz68km.geo -3 -nopopup -format msh2 -o C:\Users\pcnou\AppData\Local\Temp\tmp5es89ie5.msh' [Gmsh 4.6.0, 1 node, max. 1 thread] Info : Started on Wed May 05 10:22:49 2021 Info : Reading 'C:\Users\pcnou\AppData\Local\Temp\tmppouz68km.geo'... Info : Done reading 'C:\Users\pcnou\AppData\Local\Temp\tmppouz68km.geo' Info : Meshing 1D... Info : Done meshing 1D (Wall 0s, CPU 0s) Info : Meshing 2D... Info : Done meshing 2D (Wall 0s, CPU 0s) Info : Meshing 3D... Info : Done meshing 3D (Wall 0s, CPU 0s) Info : 0 nodes 0 elements Info : Writing 'C:\Users\pcnou\AppData\Local\Temp\tmp5es89ie5.msh'... Info : Done writing 'C:\Users\pcnou\AppData\Local\Temp\tmp5es89ie5.msh' Info : Stopped on Wed May 05 10:22:49 (From start: Wall 0.00999999s, CPU 0.03125s)
格式转换后导入的二次报错
将原.msh文件转换为.msh2格式后重新导入,触发IndexError,核心堆栈为:
IndexError Traceback (most recent call last) <ipython-input-47-38097a945970> in <module> ----> 1 mesh = Gmsh3D(join(output,'case_1.msh2'),communicator=serialComm) # Doesn't work ~\Anaconda3\envs\Ansys\Lib\site-packages\fipy\meshes\gmshMesh.py in __init__(self, arg, communicator, overlap, background) 1991 self.cellGlobalIDs, 1992 self.gCellGlobalIDs, -> 1993 self._orderedCellVertexIDs_data) = self.mshFile.read() 1994 1995 self.mshFile.close() ~\Anaconda3\envs\Ansys\Lib\site-packages\fipy\meshes\gmshMesh.py in read(self) 815 parprint("Recovering coords.") 816 parprint("numcells %d" % numCellsTotal) --> 817 vertexCoords, vertIDtoIdx = self._vertexCoordsAndMap(cellsToGmshVerts) 818 819 # translate Gmsh IDs to `vertexCoord` indices ~\Anaconda3\envs\Ansys\Lib\site-packages\fipy\meshes\gmshMesh.py in _vertexCoordsAndMap(self, cellsToGmshVerts) 1008 allVerts = nx.unique(nx.array(allVerts, dtype=nx.INT_DTYPE)) # remove dups 1009 allVerts = nx.sort(allVerts) -> 1010 maxVertIdx = allVerts[-1] + 1 # add one to offset zero 1011 vertGIDtoIdx = nx.ones(maxVertIdx, 'l') * -1 # gmsh ID -> vertexCoords idx 1012 vertexCoords = nx.empty((len(allVerts), self.coordDimensions)) IndexError: index -1 is out of bounds for axis 0 with size 0
问题现象汇总
- 直接导入.geo源文件也会触发与首次导入完全一致的报错
- 无论使用目标业务网格文件、标准测试.msh文件还是对应.geo源文件开展验证,均无法正常完成导入
- 核心疑问:问题源于网格文件本身缺陷,还是Gmsh3D接口使用方式存在问题?
问题根因与解决方案
根因定位
报错由FiPy接口与Gmsh版本不兼容导致,不属于网格文件本身缺陷,也非接口调用方式错误:
- 自动运行流程的版本错配
FiPy 3.4.2.1的Gmsh3D接口发布时,完全适配Gmsh 4.6.0的运行逻辑,调用时会自动生成临时geo文件触发Gmsh划分,但不会主动给封闭面域绑定Physical Volume标签。Gmsh 4.8.4默认仅对绑定物理标签的实体生成网格,无标签的体积域不会产出任何单元,最终输出空网格文件,触发“无单元生成”的报错。 - 格式解析的兼容断层
FiPy内置的msh2解析器仅支持Gmsh 4.6.0的文件输出规则,Gmsh 4.8.4导出的msh2文件存在实体编号偏移、物理标签存储逻辑变更的问题,解析器无法识别到3D四面体单元,最终获取到空的顶点列表,触发空列表索引越界的IndexError。
操作步骤
按顺序执行即可正常导入:
- 版本对齐
将系统安装的Gmsh 4.8.4替换为Gmsh 4.6.0,确保FiPy调用的Gmsh可执行文件版本与接口适配版本一致,消除运行逻辑分叉。 - 网格合法性校验
用Gmsh手动打开geo源文件,完成两项强制配置:- 给所有待划分的封闭体积域绑定
Physical Volume标签 - 执行3D划分后,确认网格统计信息不为0节点0单元
导出网格时,选择Gmsh 2.2 ASCII格式(即严格意义的msh2格式),禁止使用新版二进制msh2格式或msh4格式。
- 给所有待划分的封闭体积域绑定
- 绕开自动调用流程
不要让FiPy自动触发Gmsh运行geo的流程,直接将手动生成的合法msh2文件传入接口:from fipy import Gmsh3D, serialComm mesh = Gmsh3D(join(output, 'case_1_valid.msh2'), communicator=serialComm) - 兜底排查
若导入仍报错,手动打开msh2文件做两项校验:- 定位
$Elements段,确认存在类型为4的单元(对应Gmsh规则的四面体3D单元),如果仅存在线段、三角形面、点单元,说明未生成有效3D网格 - 确认节点编号为从1开始的连续整数,不存在编号缺失导致的解析器读取空列表问题
- 定位
内容的提问来源于stack exchange,提问作者Eric Planas
相关产品推荐
相关产品推荐

