★Claude Code是执行器,我只打字不动手,三天从零啃下了 PyFluent、Scheme、TUI 三座大山
这次要做的是一个电子元件热仿真:PCB板上有 18 个 MOSFET,每个器件等效发热 0.5 W,外壳边界按自然对流处理,计算 2 分钟瞬态温升。
如果完全手工操作 Fluent,大致流程是:
流程本身不复杂,但问题在于重复性。只要改一次工况、网格参数或边界条件,就要重新点一遍 GUI。对工程仿真来说,最怕的不是步骤多,而是重复工作,效率低。
所以这次的目标很明确:把这套操作沉淀成可复现脚本,让 Fluent 自动完成网格生成和求解设置。
Fluent 自动化容易混乱,是因为它同时存在几套“语言”和入口:
Python / PyFluent
-> 通过 gRPC 启动并控制 Fluent
-> 适合做流程编排、Meshing workflow 调用
TUI
-> Fluent Console 里的文本命令
-> 适合稳定复现 /define、/solve、/file 等操作
Scheme / Journal
-> Fluent 内部脚本机制
-> 适合把一组 TUI 交互保存为可回放脚本
GUI Journal
-> 录制界面点击
-> 适合参考,不适合作为主自动化方案
UDF
-> C 语言扩展物理模型
-> 本项目没有使用
最后采用的方案是:网格阶段用 PyFluent 调 Fluent Meshing 的工作流;求解设置阶段用 PyFluent 启动 Solver,再逐个读取已经验证过的 journal 文件。
这个组合比较稳。Python 负责调度,Fluent 自己的 TUI/Journal 负责执行具体设置。
我是仿真工程师,不是程序员。
所以这次的目标不是"学编程"——是找一个会编程的东西,我说话,它干活。
不是浏览器对话框。是运行在终端里的 Agent,能:
为啥用deepseek的api,一是token便宜,用多少算多少;二,也是想看看国产大模型在驱动仿真软件上的能力。
网格生成部分用的是 Fluent Meshing 的 Watertight Geometry 工作流。脚本按任务逐步执行:导入几何、跳过局部尺寸、生成表面网格、描述流固区域、更新边界和区域、生成 polyhedra 体网格,最后切到 Solution 并写出网格文件。
核心逻辑可以概括成这样:
from ansys.fluent.core import launch_fluent
session = launch_fluent(
product_version="23.2.0",
mode="meshing",
processor_count=4,
)
workflow = session.workflow
workflow.InitializeWorkflow(WorkflowType="Watertight Geometry")
task = workflow.TaskObject["Import Geometry"]
task.Arguments.set_state({"FileName": geometry_file, "LengthUnit": "mm"})
task.Execute()
# 后续继续执行 Surface Mesh、Describe Geometry、Volume Mesh 等任务
这一步跑通后,得到约 67 万单元的 polyhedra 网格。对比手动流程,最大的收益不是节省几分钟,而是以后网格参数可以被明确记录、重复执行、批量调整。
这里也踩到一个小坑:有些 Meshing 参数通过 PyFluent API 传递时会受到内部 Scheme 转义影响。最终没有强行追求“所有参数都走 API”,而是选择了一个已经验证稳定的参数组合。自动化不是把所有按钮都翻译成代码,而是把可靠路径固定下来。
Solver 阶段拆成 7 个 journal:
01_import_mesh.jou | ||
02_add_material.jou | ||
03_change_material.jou | ||
04_heat_sources.jou | ||
05_boundary_conditions.jou | ||
06_report_definitions.jou | ||
07_solver_setup.jou |
一开始我尝试过 GUI journal,也尝试把 TUI 命令压成单行。结果都不稳定。
GUI journal 的问题是 widget 路径会变。比如某个树节点的显示名里带 zone id,下一次打开模型 id 可能就不同。脚本看起来录制成功了,但换一个 session 就失效。
单行 TUI 的问题是提示符顺序容易漂移。某些设置在不同状态下会多问或少问几个问题,一旦参数错位,后面的 n、0、1 就会被 Fluent 当成完全不同的输入。
最后稳定下来的方式是用 ti-menu-load-string,把交互式命令写成一行一答:
(ti-menu-load-string "/define/boundary-conditions/wall
pcb-housing:1
0
n
0
n
y
convection
n
10
n
290
n
n
1")
每一行都对应 Fluent Console 里的一个提示符。这个写法不如 GUI 录制“直观”,但可控、可读、可复现。
创建新材料时,change-create 的第一个输入不是 fluid,而是一个已经存在的材料名,例如 air:
(ti-menu-load-string "/define/materials/change-create
air
coolant
y
constant
1072
y
constant
3300
y
constant
0.38
y
constant
0.00438
n
n
n
n")
如果写成 fluid,Fluent 会报错。这个错误很典型:从字面上看,用户想创建的是流体材料;但 TUI 提示符真正要的是“拿哪个已有材料当模板”。
模型里有一个多余的 fluid:1。如果保持激活,后续计算会发散。脚本里必须显式关闭:
/mesh/modify-zones/deactivate-cell-zone fluid:1
这类问题不是自动化脚本自己能判断的,必须依赖仿真工程师对模型、区域和残差表现的判断。
GUI 里填的 Energy Source 不是 W,而是 W/m3。本例中每个 MOSFET 发热 0.5 W,需要根据对应 zone 体积换算成体积热源密度,再写入 Fluent。
如果直接把 0.5 填进去,脚本仍然能运行,但物理意义已经错了。
壁面默认热边界不一定是 convection。要先回答“修改 thermal BC type”,再选择 convection,之后输入 HTC 和环境温度:
y
convection
n
10
n
290
如果这里少一个 y,后面的数值就可能写到错误的提示符上。
当 7 个 journal 都能在 Fluent Console 中单独跑通后,再用 Python 串起来:
journals = [
"01_import_mesh.jou",
"02_add_material.jou",
"03_change_material.jou",
"04_heat_sources.jou",
"05_boundary_conditions.jou",
"06_report_definitions.jou",
"07_solver_setup.jou",
]
for journal in journals:
session.tui.file.read_journal(journal)
这个结构很朴素,但很实用。每个 journal 都是一个可单独验证的模块,哪里失败就回到对应文件修,不需要在一个巨大的脚本里找错。
最终流程变成两步:
python pcb_meshing.py
python pcb_solver.py
脚本完成后保存好 case,再执行指定步数的瞬态计算即可。
这套脚本不是为了“炫技”,而是解决几个很实际的问题:
最重要的一点是:自动化没有替代仿真工程师。它只是把工程师已经验证过的判断固定下来,让这些判断能被稳定重复。
网格参数是否合理、热源单位是否正确、某个 zone 是否应该关闭、边界条件是否符合实际工况,这些仍然需要工程经验。脚本能提高效率,但不能替代物理判断。
project/
├── pcb_meshing.py # 网格生成
├── pcb_solver.py # 求解设置一键脚本
├── pcb_meshing.jou # Meshing journal 备选方案
├── 01_import_mesh.jou # 读网格 + Energy
├── 02_add_material.jou # 创建材料
├── 03_change_material.jou # Zone 类型 + 材料分配
├── 04_heat_sources.jou # 18 个 MOSFET 热源
├── 05_boundary_conditions.jou # 对流边界
├── 06_report_definitions.jou # 最高温度报告
├── 07_solver_setup.jou # 瞬态设置 + 初始化
└── README.md # 完整技术文档
这次最大的体会是:Fluent 自动化要想真正稳定,不能停留在“录制操作”层面,而要理解每个 TUI 提示符背后的工程含义。只有这样,脚本才不是一次性 demo,而是可以继续维护、复用和扩展的工程资产。