一、简介
在岩土工程和地下工程的数值模拟中,ANSYS 和 FLAC3D 是两款使用广泛的有限元/有限差分软件。ANSYS 在网格划分和前处理方面具有强大的功能,尤其对于复杂几何体的四面体网格生成,其自动化程度和网格质量都十分优秀;而 FLAC3D 在岩土本构、非线性分析以及流固耦合等方面有着独特的优势。
在实际工程项目中,经常的做法是,发挥 ANSYS 前处理优势,在 ANSYS 中建立三维计算网格,然后将网格导入 FLAC3D 进行力学分析。
本文介绍一个基于 Python 开发的一站式网格转换工具 ansys2flac.py。该脚本直接读取 ANSYS 导出的节点列表(NLIST.lis)和单元列表(ELIST.lis)两个文本文件,一次性输出 FLAC3D 可识别的 .f3grid 网格文件,实现从 ANSYS 到 FLAC3D 的网格无缝迁移,全程无需任何中间文件,支持多材料分组,适用于大规模三维模型。
整体工作流程: ANSYS 建模/划分网格 → 导出 NLIST.lis 和 ELIST.lis → 运行 ansys2flac.py → 生成 .f3grid → FLAC3D 导入计算
二、ANSYS 端操作:导出节点与单元数据
在 ANSYS 中完成建模、网格划分、材料分组等前处理工作后,需要将模型的节点信息和单元信息分别导出为文本文件,供后续 Python 程序读取解析。这是整个转换流程的起点,导出数据的完整性和正确性直接决定了最终 FLAC3D 模型的质量。
主要需要导出两个文件:
- NLIST.lis:节点列表文件,包含模型中每个节点的编号及其在整体坐标系下的 x、y、z 坐标值。该文件是构建 FLAC3D 网格点(Gridpoint)的数据来源。
- ELIST.lis:单元列表文件,包含每个单元的编号、所属材料号(MAT)、单元类型编号(TYPE)以及组成该单元的各节点编号。该文件是构建 FLAC3D 区域(Zone)和材料分组的数据来源。
以某工程为例,在完成网格划分和材料分组后,具体导出操作如下:
导出节点列表(NLIST)
在 ANSYS 经典界面(APDL 模式)的命令输入框中,直接键入 NLIST 命令并回车执行。ANSYS 将在输出窗口中列出当前模型所有节点的编号和坐标信息。随后,通过菜单 File > Save As 或使用 /OUTPUT 命令将输出内容重定向到文件中保存。操作界面如图 1 所示,红色框标注了命令输入位置。
图 1 在 ANSYS 命令行中输入 NLIST 命令导出节点列表
导出单元列表(ELIST)
同样地,在命令输入框中键入 ELIST 命令并回车。ANSYS 将列出所有单元的编号、材料属性及节点连接关系。如图 2 所示,在命令行中输入 ELIST 后,上方蓝色高亮区域为 ANSYS 的命令提示,显示了 ELIST 命令的完整参数格式(IEL1, IEL2, INC, NNKEY, RKEY),默认参数即可列出全部单元信息。
图 2 在 ANSYS 命令行中输入 ELIST 命令导出单元列表
▶ 导出前的注意事项: 请确保在导出前已完成所有的材料号(MAT)和单元类型(TYPE)分配。如果模型中存在多种材料,ELIST 导出的文件中会自动包含每个单元对应的材料编号,程序将据此自动生成 FLAC3D 中的材料分组。
▶ 导出文件的保存路径: 执行 NLIST/ELIST 命令后,输出内容默认显示在 ANSYS 的输出窗口中。可在命令执行前通过 /OUTPUT,NLIST,lis 命令将输出重定向到文件,或在输出窗口中通过 File > Save As 手动保存。请确保保存的文件名与 Python 程序中读取的文件名一致(默认为 NLIST.lis 和 ELIST.lis)。
三、程序原理与实现:ansys2flac.py
输入文件:
- NLIST.lis —— ANSYS 节点列表(节点号、x、y、z 坐标)
- ELIST.lis —— ANSYS 单元列表(单元号、材料号、类型、节点连接)
输出文件:
- model.f3grid —— FLAC3D 原生网格文件,可直接 Open into Project
脚本 ansys2flac.py 的核心逻辑分为五步:(1) 读取 NLIST 解析节点坐标;(2) 读取 ELIST 解析单元拓扑与材料编号;(3) 写出 GRIDPOINTS 段;(4) 写出 ZONES 段;(5) 按材料分组写出 ZONE GROUPS 段。所有处理在内存中完成,无需任何中间文件。下面分小节展示核心代码。
1.配置文件名
程序顶部预留了三个文件名参数,用户只需根据实际情况修改即可使用,无需改动主体代码。
from collections import defaultdict# 在这里修改文件名nlist_file = 'NLIST.lis'elist_file = 'ELIST.lis'f3grid_file = 'model.f3grid'
2.读取NLIST:解析节点坐标
ANSYS 导出的 NLIST.lis 是带有固定格式的文本文件,其中混杂着标题行、分隔线和空行等无效内容。程序逐行扫描,利用 try-except 异常捕获机制自动跳过格式不匹配的行,仅提取符合「整数 + 三个浮点数」格式的有效节点数据。节点编号被作为字典 nCoor 的键,坐标元组作为值,省去了数组下标到节点编号的映射步骤。
nCoor = {} # 节点坐标, nCoor[node_id] = (x, y, z)with open(nlist_file, 'r') as f:for line in f: parts = line.split()try:# 期望格式: node_id x y z node_id = int(parts[0]) x = float(parts[1]) y = float(parts[2]) z = float(parts[3]) nCoor[node_id] = (x, y, z)except (ValueError, IndexError):# 跳过标题、分隔线、空行等无效行continue
3.读取ELIST:解析单元拓扑与材料标号
ELIST.lis 文件每行包含 14 个字段,分别为:单元编号、材料号、单元类型、3 个保留字段,以及最多 8 个节点编号。对于四面体单元,4 个顶点节点位于第 7、8、9、11 位置(其余为填充字段,予以跳过)。程序在解析时同步记录材料号到 eMat 字典,用于后续的材料分组。
eNode = {} # 单元节点, eNode[elem_id] = [n1, n2, n3, n4]eMat = {} # 单元材料号, eMat[elem_id] = mat_idwith open(elist_file, 'r') as f:for line in f: parts = line.split()try:# 期望格式: elem_id mat_id type_id ... n1 n2 n3 n4 ... elem_id = int(parts[0]) mat_id = int(parts[1])# 节点编号位于第 7~10 位 (索引 6~9), 取 4 个顶点构成四面体 n1 = int(parts[6]) n2 = int(parts[7]) n3 = int(parts[8]) n4 = int(parts[10]) eNode[elem_id] = [n1, n2, n3, n4] eMat[elem_id] = mat_idexcept (ValueError, IndexError):continue
4.写出f3grid:三大段结构
FLAC3D 的 .f3grid 文件由三大段构成:GRIDPOINTS(网格点)、ZONES(单元)、ZONE GROUPS(材料分组)。程序按此顺序依次写入,每段以星号开头的行作为段标识。
(1)GRIDPOINT段——写出节点坐标:
以关键字 G 开头,后跟节点编号和三维坐标,坐标保留 12 位小数以确保精度。节点编号直接沿用 ANSYS 中的原始编号。
with open(f3grid_file, 'w') as f:# 文件头 f.write('* FLAC3D grid produced by FLAC3D\n')# 第三步:输出节点 f.write('* GRIDPOINTS\n')for node_id in sorted(nCoor.keys()): x, y, z = nCoor[node_id] f.write('G %d %15.12f %15.12f %15.12f\n' % (node_id, x, y, z))
(2)ZONE段——写出单元,以T4标识四面体:
以关键字 Z 开头,后跟单元类型标识 T4(四面体)、单元编号和 4 个组成节点的编号。
# 第四步:输出单元 f.write('* ZONES\n')for elem_id in sorted(eNode.keys()): n1, n2, n3, n4 = eNode[elem_id] f.write('Z T4 %d %d %d %d %d \n' % (elem_id, n1, n2, n3, n4))
(3)ZONE GROUPS段——按材料号分组:
程序使用 defaultdict 按材料号自动聚合对应的单元编号,然后为每个材料写出一个 ZGROUP 块。每行最多输出 20 个单元编号以保持文件的可读性。
# 第五步:按材料号输出分组 f.write('* ZONE GROUPS\n') mat_groups = defaultdict(list)for elem_id in sorted(eNode.keys()): mat_groups[eMat[elem_id]].append(elem_id)for mat_id in sorted(mat_groups.keys()): f.write('\n') f.write('ZGROUP "mat_%d" SLOT "Construction"\n' % mat_id) zone_list = mat_groups[mat_id] cnt = 0for zid in zone_list: f.write('%d,' % zid) cnt += 1if cnt % 20 == 0: f.write('\n') f.write('\n')
最终输出的 .f3grid 文件示例如下。GRIDPOINTS 段以 G 开头,每行一个节点;ZONES 段以 Z T4 开头,每行一个四面体单元;ZONE GROUPS 段以 ZGROUP 开头,下方紧跟属于该组的单元号列表。
* FLAC3D grid produced by FLAC3D* GRIDPOINTSG 1 100.123456789012 200.234567890123 -50.345678901234G 2 100.234567890123 200.345678901234 -50.456789012345...* ZONESZ T4 1 1 2 3 5Z T4 2 2 3 4 6...* ZONE GROUPSZGROUP "mat_1" SLOT "Construction"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,...ZGROUP "mat_2" SLOT "Construction"501,502,503,...
四、操作步骤
1.准备输入文件
确保 ANSYS 导出的两个文件与 ansys2flac.py 脚本放置在同一目录下:
2.运行ansys2flac.py
打开 ansys2flac.py,确认顶部的三个文件名参数与实际情况一致后运行。程序运行时会输出读取与写入的统计信息,便于用户核对:
读取完成: 节点数 = 410717 单元数 = 2354318 材料号 = [1, 2, 3]输出完成: model.f3grid 有效单元数 = 2354318 材料分组数 = 3
程序执行完毕后,会在当前目录下生成 .f3grid 文件(默认文件名为 model.f3grid)。对于包含数十万节点和数百万单元的大规模模型,转换过程通常在数分钟内完成。
3.在FLAC3D中导入网格
生成 .f3grid 文件后,需要在 FLAC3D 软件中将其导入。打开 FLAC3D,依次点击菜单 File → Open into Project...(快捷键 Ctrl+O),在弹出的文件选择对话框中定位到生成的 .f3grid 文件并确认打开,如图 3 所示。
图 3 通过 FLAC3D 菜单 File > Open into Project 导入 .f3grid 网格文件
成功导入后,模型网格将立即显示在 FLAC3D 的 Plot 窗口中。如图 4 所示,该示例模型包含约 12万个网格点(Gridpoints)和 68万个单元(Zones),按 4 个材料分组(mat_102、mat_103、mat_2、mat_3)着色显示。控制台(Console)窗口会输出导入的详细统计信息,包括创建的网格点数、区域数和分组数,可据此验证导入是否完整。
图 4 网格成功导入 FLAC3D 后的模型显示(按材料分组着色)
▶ 导入验证建议: 导入后应重点核对以下三项信息:① 网格点总数是否与 ANSYS 中的节点数一致;② 单元总数是否与 ANSYS 中的单元数一致;③ 材料分组数和各组单元数是否与 ANSYS 模型的材料设置匹配。如有差异,请检查 NLIST/ELIST 文件的完整性以及 ELIST 文件中的字段位置是否与脚本预设一致。
五、输入输出文件清单
整个转换流程涉及的核心文件如下表所示。两个输入文件来自 ANSYS 导出,一个输出文件直接交付给 FLAC3D,过程中无任何中间文件。
| | |
|---|
| NLIST.lis | | ANSYS 导出的节点列表,含节点编号与 x、y、z 坐标 |
| ELIST.lis | | ANSYS 导出的单元列表,含单元号、材料号、节点连接 |
| model.f3grid | | FLAC3D 网格文件,可直接 Open into Project 导入 |
六、注意事项
▶ 编号一致性: ANSYS 与 FLAC3D 均使用 1-based 编号(从 1 开始)。脚本直接沿用 ANSYS 中的原始节点号和单元号,不做任何编号偏移或重新编号,便于在 FLAC3D 中通过编号反查 ANSYS 模型中的对应实体。
▶ 编号连续性: ANSYS 中的节点和单元编号不一定连续(例如经过网格删除或合并操作后,编号可能出现跳跃)。脚本使用字典存储节点和单元数据,对编号跳跃天然兼容,输出时按编号排序写出,不会产生空行或错位。
▶ ELIST 字段位置: 脚本默认从 ELIST.lis 的第 7、8、9、11 列读取四面体的 4 个顶点节点。如果 ANSYS 导出的字段顺序略有不同(不同版本可能略有差异),需要手动调整脚本中 parts[6]、parts[7]、parts[8]、parts[10] 这几个索引。
▶ 单元类型兼容性: 当前脚本支持线性四面体(4 节点)单元。如使用二次四面体单元(10 节点 SOLID187),ELIST 文件中每个单元会包含更多节点编号,需要在解析阶段调整字段索引并仅取 4 个顶点节点、忽略 6 个中间节点。
▶ 材料映射: 转换后 FLAC3D 中的材料分组名称为 mat_102、mat_103等,与 ANSYS 中的材料编号一一对应。导入 FLAC3D 后,需通过 zone cmodel assign 和 zone property 命令为各分组指定对应的本构模型(如 Mohr-Coulomb、Elastic)和材料参数(如弹性模量、泊松比、内摩擦角等)。
适用场景: 隧道工程 | 边坡稳定 | 基坑开挖 | 地下硐室 | 岩土力学