☰
SALOME开源CAE前处理平台:用Python脚本实现几何建模与网格划分自动化
2026/10/27 7:50:03 网站建设 项目流程

简介:这是一份基于 GNU LGPL 协议分发的 SALOME 开源 CAE 前后处理平台资源包,面向数值模拟工程师、科研人员及希望扩展桌面工具的开发者。SALOME 以可重用组件构成开放架构,支持跨平台部署,该包呈现其核心启动脚本、构建配置与界面资源,便于从代码层面理解平台装配方式。包内共 18 个文件,约 566KB,主要包括 PNG 图像资源(应用图标、启动画面)、TS 多语言翻译文件、CMake 构建脚本、TXT 说明文档、LICENCE 许可证、IN 配置模板以及 Python 启动入口等。其中的脚本入口与 CMake 构建配置可帮助读者快速定位程序启动逻辑和依赖关系,多语言翻译文件则展示了国际化机制,非常适合作为学习开源 CAE 软件结构或开展二次开发的基础素材。已有 1194 人学习和下载,对关注 SALOME 官网源码流程或准备基于其组件构建自有前后处理环境的读者具有一定参考价值。

1. SALOME 不是又一个 CAE 前处理壳子:开源 CAE 软件里它凭什么值得花时间

做仿真的人多少都有过这样的经历:几何模型在 CAD 里画好了,导入专用前处理器,破面、丢特征、网格种子乱跳,折腾一整天还没到求解器那一步。SALOME 这个开源 CAE 软件名字在圈子里传了很多年,但真正把它当主力前处理平台用的人不算多——原因很简单,它的上手曲线比一键式商业软件陡不少。可一旦习惯用 Python 脚本驱动这套平台做 CAE 前处理,就会发现一个关键事实:几何建模、网格划分、边界条件命名、格式转换这些活,全部可以参数化、可回溯、可批量重跑,而不是靠鼠标在界面上碰运气。

SALOME 的定位不是一个「能画网格的 CAD」,而是自带几何内核(Open CASCADE)、网格引擎(NETGEN)、数据交换格式(MED)和流程编排模块的一整套前处理基础设施。它适合两类人:一类是做结构、流体、电磁仿真的工程师,想摆脱商业前处理器的授权限制和黑匣子;另一类是仿真流程开发人员,需要在前处理和求解器之间建一条可自动化的数据通道。这篇笔记不写官方手册,只讲我实际用过之后认为最值得先掌握的几块:架构怎么理解、几何和网格怎么用脚本控制、数据怎么和求解器互通,以及最容易翻车的几个坑。

2. 先看懂 SALOME 的四层骨架:几何内核、网格引擎、数据格式与工作流

2.1 为什么说它是平台而不是单一工具

第一次打开 SALOME 的人往往会被界面吓到:左边是对象浏览器,中间是三维视图,顶部一排模块按钮,看起来像个巨型工具箱。实际上它内部是四层结构,理解这个结构才能决定自己该在哪一层干活。

底层是 Open CASCADE 几何内核,负责创建和编辑 CAD 几何体。SALOME 的几何模块(GEOM)把它包装成一套命令式 API,支持标准的画线、拉伸、旋转、扫掠、倒角,也支持布尔运算、投影、切片、离散化这类辅助几何操作。第二层是网格模块(MESH),底层用 NETGEN 做主导网格算法,同时还能对接 Gmsh 的某些算法——这一点比「只能用 NETGEN」的认知要宽一些。第三层是 MED 数据格式,文件后缀 .med,头文件里同时承载网格拓扑、几何节点坐标、组名(Group)和字段(Field)。最后一层是工作流与耦合模块(YACS),可以把几何生成、网格划分、求解器调用、后处理串成一个有向图,类似一个轻量级仿真流水线。

这四层里,最值得普通工程师投入的是前两层加 Python 接口。YACS 工作流在复杂多物理场耦合场景里很强大,但对于大多数单求解器项目,用 Python 脚本串流程比可视化连线更直接、更好维护。后面几节讲的都是基于 Python 脚本的用法。

2.2 参数化设计的基本功:GEOM 模块的 Python API

SALOME 的 Python 接口不是「部分功能可脚本化」,而是几乎全部功能都走了脚本化通道。你在界面上点一下按钮,底层就在执一段对应的 Python 指令;SALOME 的会话启动后,Python Console 输入一段脚本,几何对象就会在界面上更新。这意味着可以用文本完整复现一个几何建模过程,这是商业前处理器很难给到的体验。

打开 SALOME 后进入 GEOM 模块,新建一个 Python 脚本,最简的几何建模逻辑是这样:先拿到当前 study 里几何组件和构建器的引用,用构建器的MakeBox生成一个长方体,再用AddToStudy将对象注册到对象浏览器。

import salome salome.salome_init() import GEOM from salome.geom import geomBuilder geompy = geomBuilder.New() # 取当前 study 中的几何组件 gg = geompy.GetComponent("GEOM") # 创建一个长 60、宽 30、高 20 的长方体 box = geompy.MakeBoxDXDYDZ(60.0, 30.0, 20.0) # 把对象加入对象浏览器,便于可视化和后续引用 geompy.addToStudy(box, "Box_60_30_20")

这段脚本里,MakeBoxDXDYDZ是按长宽高生成和原点对齐的盒子;若想按空间两点生成,可用MakeBoxTwoPnt。addToStudy这步很多人会漏掉,漏掉之后对象不会出现在界面左侧的树里,后续想用鼠标拖入网格模块就没法操作。之后把变量box传给网格模块,它就是数据源。

2.3 平面裁剪与复合体的常见操作模式

实际模型不会只是一个盒子。从 CAD 导入的零件常常带圆角、孔洞、装配关系,SALOME 里对这类几何的处理是先转成融合后的复合体,再在需要的位置做平面裁剪或布尔切分。下面这段脚本演示了拿两个盒子做布尔减,生成一个带槽的实体:

import GEOM from salome.geom import geomBuilder geompy = geomBuilder.New() box1 = geompy.MakeBoxDXDYDZ(80.0, 40.0, 30.0) box2 = geompy.MakeBoxDXDYDZ(20.0, 40.0, 30.0) # 移动 box2 到合适位置 box2_tr = geompy.MakeTranslation(box2, 10.0, 0.0, 0.0) # 布尔减:从 box1 中挖去 box2_tr cut = geompy.MakeCutList(box1, [box2_tr], True) geompy.addToStudy(cut, "Box_With_Slot")

MakeCutList的第三个参数控制是否保留内部工具实体。常见的误用是把原始工具体留在模型树里,导致后续网格生成时把不该剖分的内部面也画进去。另外注意MakeTranslation返回的是新几何体而不是原地移动,这在脚本中很容易造成思维定式上的翻车——每次都以为原对象位置变了,实际上原对象不变,必须把返回值重新赋值。

3. 用 SALOME 的 CAE 前处理能力把几何变成合格计算域:脚本化建模全流程

3.1 从草图到可仿真几何:拉伸、扫掠与倒角的最小序列

几何建模在 SALOME 里不是终点,而是为网格和求解边界服务的。一张可用的计算域至少要满足两个条件:一是没有游离边或极细长面,二是关键特征(倒角、圆孔、螺纹简化)的几何表达符合仿真目标。SALOME 里我从空白几何起步的典型序列是:画面,拉伸成体,倒角,必要时加关键切分。

以一块带圆角底座的几何为例。先利用MakeVertex生成关键点,连成草绘线,再做面、拉伸:

geompy = geomBuilder.New() # 定义底面矩形四个顶点 p1 = geompy.MakeVertex(0.0, 0.0, 0.0) p2 = geompy.MakeVertex(50.0, 0.0, 0.0) p3 = geompy.MakeVertex(50.0, 30.0, 0.0) p4 = geompy.MakeVertex(0.0, 30.0, 0.0) # 连成四条边并合成线框 e1 = geompy.MakeEdge(p1, p2) e2 = geompy.MakeEdge(p2, p3) e3 = geompy.MakeEdge(p3, p4) e4 = geompy.MakeEdge(p4, p1) wire = geompy.MakeWire([e1, e2, e3, e4]) # 创建平面 face = geompy.MakeFace(wire, 1) # 沿 Z 轴拉伸 solid = geompy.MakePrismVecT(face, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0) geompy.addToStudy(solid, "Base_Block")

MakeFace的第一个参数是线框,第二个参数表示是否自动检测内部孔洞;如果线框里有闭合内环而这里设成 1,会直接生成带孔的平面,省去手动把内环指定为孔的步骤。MakePrismVecT的后三个参数是拉伸方向向量,这里用的 0,0,1 表示沿正 Z 轴拉伸。若几何体需要倒角,可用MakeFillet或MakeFilletAll,后者对某条边自动识别相邻面并过渡,省去手动选所有连接边。

3.2 命名边界是前处理的战略动作:Group 机制与几何分区

很多人在 SALOME 里把网格画完就导出,却不知道真正决定求解效率的是「边界定义」。求解器读入 MED 文件时,边界条件不是靠坐标范围猜的,而是靠网格上的组名(Group)。老板让你改一个孔的位置,如果之前边界名字起得潦草,重画网格后所有边界条件都要重新关联——这一步往往是前处理时间超支的元凶。

在 SALOME 几何阶段就创建好组的习惯很值得养成。比如给上面那个带孔实体把每个孔面单独建为一个 Group:

# 找出所有类型为面、半径等于 5 的圆柱面 faces = geompy.SubShapeAll(solid, geompy.ShapeType["FACE"]) hole_faces = [] for face in faces: if geompy.GetType(face) == geompy.ShapeType["FACE"]: # 获取该面的几何特性并判断是否为圆柱面 props = geompy.BasicProperties(face) # 这里用面积/周长/类型等组合筛选,实际常用 GetShapeType 与 geompy.GetCylDims is_cyl = geompy.GetCylDims(face) if is_cyl is not None: hole_faces.append(face) # 把所有孔面合并到一个组,命名为 "HOLES" geompy.CreateGroup(solid, geompy.ShapeType["FACE"]) # 另一常见做法:手动把选中的 face 填入组 hole_group = geompy.CreateGroup(solid, geompy.ShapeType["FACE"]) for f in hole_faces: geompy.AddObject(hole_group, f) geompy.addToStudy(hole_group, "HOLES")

这段脚本的价值在于把「找孔面」从手工点击变成了可重复执行的逻辑。GetCylDims会返回圆柱面的轴、半径、高度等参数,若返回None说明不是圆柱面。实际操作里孔径不同,筛选条件就要改成尺寸条件,这正好体现参数化脚本相比手选的优势:改孔径后重跑脚本,组自动更新名字不变,求解器侧边界条件文件不用动。

3.3 离散化与检查:让几何进入网格模块前先过一遍体检

几何体建完后,SALOME 的 MESH 模块要求先「划分」再「验证」。这里的划分不是最终网格,而是几何离散准备——比如设置每段曲线的离散段数,让后续 NETGEN 生成曲面网格时有足够的表现力。不管是导入的 STEP 文件还是脚本生成的几何,我都会先做一遍subshape检查:统计边数、面数、最大最小边长等几何特征,再决定网格尺寸。

import SMESH from salome.smesh import smeshBuilder smesh = smeshBuilder.New() # 假设 solid 是之前创建的几何体 mesh = smesh.Mesh(solid, "Base_Block_Mesh") # 设定全局网格尺寸和线性细化策略 algo = mesh.Segment() algo.LocalSize(2.0) # 生成二维三角网格 mesh.Triangle().MaxSize(3.0) # 生成体网格 mesh.Quadrangle() mesh.Hexahedron() # 执行计算并统计 mesh.Compute()

需要留意的是smesh.Mesh的第一个参数必须是 GEOM 的对象而非文件名,这是新手最容易卡住的地方。LocalSize(2.0)控制边上的目标长度,MaxSize(3.0)控制面网格最大尺寸。对于流体分析,建议把面网格最大尺寸压到全局边长的 1.5 倍以下,避免进出口面和壁面网格差异过大。生成完毕后要及时查看mesh.GetMeshInfo(),如果出现负数/警告,先回到几何阶段排查自由边,而不是在网格参数里盲目加密。

4. 把网格质量做稳:NETGEN 参数、边界层与导出前的三项体检

4.1 全局尺寸与局部加密:为什么只调 Max Size 会翻车

在 SALOME 里做结构分析时,很多人习惯只改一个全局 Max Size,结果模型稍微复杂一点就出现负体积或者网格数量爆炸。原因是 NETGEN 的三角形/四面体算法对几何曲率敏感,单一全局尺寸在圆角、小缝隙区域会让单元退化。正确的做法是给不同几何实体分配不同的尺寸映射(local size by sub-shape),然后设定尺寸增长率。

# 在之前 mesh 基础上,对特定边实施局部细化 faces = geompy.SubShapeAll(solid, geompy.ShapeType["FACE"]) for idx, f in enumerate(faces): # 假设编号为 5 的面是圆角接触区 if idx == 5: mesh.Segment(f).LocalSize(0.5) mesh.Triangle(f).MaxSize(0.8)

这里mesh.Segment(f)返回的是作用在该面上的划分算法对象,再对这个对象调局部参数。局部尺寸 0.5 + 全局 2.0 的组合,在圆角区生成的网格数量可能成倍增加,但换来的梯度分辨率是值得的。参数设置完成后一定要用mesh.Compute()重新计算,并查看mesh.GetLog()里的警告信息。常见警告包括「节点太靠近」「锯齿边」,这些通常能通过调大局部尺寸或调整几何公差解决。

4.2 边界层网格在 SALOME 里的两种做法

流体仿真几乎绕不开边界层网格。SALOME 的 MESH 模块里生成边界层需要走专门的算法:在目标面附近创建一列垂直于壁面的薄层单元。新手常犯的错是把 boundary layer 的概念和局部细化混为一谈——局部细化只会让网格更小但仍是各向同性,边界层则是拉伸的棱柱层。SALOME 里可以通过AddPrism或对体网格使用Prism算法实现:

# 在壁面区域创建边界层 wall_face = geometry_object_for_wall # 请替换为实际壁面组 algo_prism = mesh.Prism(wall_face, "Prism_3D") algo_prism.SetNumberOfLayers(5) algo_prism.SetThickness(0.2) algo_prism.SetGrowthFactor(1.2) mesh.Compute()

SetNumberOfLayers(5)是层数,SetThickness(0.2)是第一层总厚度,SetGrowthFactor(1.2)是层与层之间的厚度增长系数。这三个参数配合全局 Max Size 才能控制总网格数不失控。边界层适合贴着壁面设,别用在流道入口或出口;在这些地方强行加层只会增加计算量,对精度没帮助。

4.3 导出 MED 前的三种检查手段

网格生成不等于可以导出求解。我每次导出前必做三项体检,缺一不可。

第一项是拓扑完整性检查,在 SMESH 模块里看mesh.GetMeshInfo(),确认节点数、单元数和单元类型分布符合预期,比如只有四面体、五面体、六面体三种,如果出现奇怪的零体积单元,大概率是几何退化导致。第二项是要素组映射检查,在对象浏览器里把几何阶段的 Group 拖到 MESH 对象上,确认每个组都能对应到网格上的相应节点或单元——这一步如果名字对不上,求解器会在边界条件阶段报错。第三项是实体维度检查,SALOME 偶尔会把 2D 面网格当成体网格导出,求解器读入后根本算不了三维,需要在导出脚本里显示指定导出维度。

# 导出 MED 文件的标准写法 import MEDCoupling from salome.medcoupling import medcoupling as mc # 将 SMESH 网格转为 MEDCoupling 通用网格 med_mesh = smesh.ExportMED(fname, "Base_Block_MESH", 3, overwrite=1)

ExportMED的第三个参数3表示导出三维体网格;如果是二维壳单元,这里要传 2。overwrite=1表示覆盖同名文件。实际操作中导出让很多同事挠头的点在于:导出前要先把网格对象Mesh提升到 study 顶层,否则界面导出按钮灰化。脚本化的话则无此顾虑,直接调用即可。

5. 把 SALOME 接进真实仿真流程:与开源求解器的数据交换和自动化集成

5.1 用 MED 文件打通 SALOME 与求解器:Code_Aster 和 OpenFOAM 的常见对接模式

SALOME 本身不求解,它的价值在「把几何和网格做成任何求解器都能读的通用格式」。开源生态里最经常见到的是 SALOME + Code_Aster 的组合。Code_Aster 的网格模块能直接读 .med 文件,而 Code_Aster 的边界条件命令语言(COMM)也通过组名引用网格。SALOME 侧只要你确保几何组名与 COMM 里的引用严格一致,基本不需要中间格式转换。OpenFOAM 则略有不同:它原生支持的是 .msh 或 OpenFOAM 自身的字典格式。常见做法是:用 SALOME 导出 .med,再通过 MEDCoupling 转换到 Gmsh 格式或直接写 converter 脚本。这个环节的稳定性直接影响整个仿真链路的自动化程度。

5.2 流程自动化:用 Python 串起「几何更新 → 网格重算 → 导出」的批处理循环

日常做前处理最耗时间的往往不是单次操作,而是反复修改设计参数后的重跑。SALOME 的脚本化基因在这里发挥最大价值。我通常把整个前处理封装成一个可带参数的 Python 脚本:某次方案需要扫 10 个板厚值,那就写一个循环,每次循环里更新几何尺寸、重算网格、导出带索引的 MED 文件。

import salome, GEOM, SMESH from salome.geom import geomBuilder from salome.smesh import smeshBuilder def run_preprocess(thickness): geompy = geomBuilder.New() smesh = smeshBuilder.New() # 用参数化方式建几何 box = geompy.MakeBoxDXDYDZ(100.0, 50.0, thickness) geompy.addToStudy(box, "Box_t_%s" % thickness) # 生成网格 mesh = smesh.Mesh(box, "Mesh_t_%s" % thickness) mesh.Segment().LocalSize(2.0) mesh.Triangle().MaxSize(2.0) mesh.Compute() # 导出 fname = "box_t_%s.med" % thickness smesh.ExportMED(fname, "mesh_t_%s" % thickness) return fname # 批量扫描 5 个厚度 for t in [5.0, 10.0, 15.0, 20.0, 25.0]: print(run_preprocess(t))

这个循环看似简单,却解决了前处理领域一个核心痛点:参数扫描场景下,人为干预降到最低。脚本里的smesh = smeshBuilder.New()在循环外只需初始化一次,但geomBuilder.New()必须在每次循环内重取,否则上一轮的对象引用可能失效。

5.3 避坑:SALOME 集成过程中的 4 个高频故障与排查方法

坑一:导入 STEP 文件后几何显示正常,一划分网格就提示「没有可用几何体」。现象是 MESH 模块对象树里看不到任何子几何。原因是导入的 STEP 被 SALOME 当作一个独立的外部参考对象,并没有自动注册到 MESH 模块的几何容器里。解决:导入后手动执行geompy.addToStudy(file_object, "ImportedShape"),再基于该对象建立网格。

坑二:同一台机器跑批量脚本,内存占用持续升高,最后直接卡死。原因是每次循环里生成的几何对象和网格对象都残留在 study 里,SALOME 把它们都保存在内存中。解决:循环末尾删除不再使用的对象引用,或者把每组参数另起一个 SALOME session 跑。SALOME 脚本启动时可以通过环境变量控制 batch 模式,不要让图形界面常驻。

坑三:MED 文件导出来给求解器读,报「单元类型不支持」或「组名带非法字符」。这个通常是因为组名里用了中文或空格。SALOME 界面上手输名字图省事,输入了「Wall 1」「入口-前」这种,求解器读必炸。解决:几何组命名规范直接用大写字母加下划线,例如WALL_INLET、WALL_OUTLET。脚本里加一层名字清洗函数,把所有非法字符替换成下划线,能省掉后面所有对接麻烦。

坑四:边界层生成后,体网格反而冲突,报负体积。现象是加了Prism算法后部分区域出现叠层穿透。原因是边界层厚度大于局部网格尺寸,导致棱柱层压碎了原有四面体。解决:先按SetThickness预估首层厚度,确认它小于局部尺寸的 1/3;同时把SetGrowthFactor从 1.2 降到 1.05 重新试算。如果还不行,就把边界层区域的面网格尺寸先加密,再加边界层。

6. 用 MEDCoupling 做验证式调试:网格数据的快速可视化自查与轻量后处理

6.1 直接操作 MED 数值文件:不用打开界面就能验证网格量

很多仿真工程师有一个共同困惑:导出 MED 之后,怎么快速确认文件里网格数量、组名、坐标范围对不对?不需要打开 SALOME 图形界面,直接用一个 Python 脚本通过 MEDCoupling 读取 MED 文件,做数字层面的检查。MEDCoupling 是 SALOME 平台下的一个数值库,独立于图形环境,能直接读 MED 文件并操作数组。

import medcoupling as mc # 读取 MED 文件 med_file = mc.MEDFileMesh.New() med_file.read("box_t_10.med") mesh_u = med_file.getMeshWithName("mesh_t_10") # 获取节点坐标数组 coords, _ = mesh_u.getCoords() print("节点数:", len(coords)) # 获取单元类型分布 cell_type_count = mesh_u.getMeshInfo() print("单元统计:", cell_type_count) # 检查组名列表 all_groups = med_file.getGroupsNames() print("组列表:", all_groups)

这段脚本对导出的 MED 文件做三个层次的快速体检:节点坐标数量是否和预期一致(比如一个 100x50x10 的盒子,粗糙网格下节点数应该在几千量级),单元类型统计是否只有四面体或六面体加边界层棱柱,以及组名列表是否满足求解器命令文件里的引用。任何一层异常都先回到 SALOME 里重算网格,而不用打开求解器白跑一遍流程。

6.2 关联几何特征做数值验证:坐标范围与特征尺寸的自动比对

除了基础的单元统计外,更高级的验证逻辑是把数值与几何参数对比。比如模型设计厚度是 10 mm,导出网格的 Z 轴坐标范围必须是 0 到 10(或符合坐标系偏移)。这类验证过去靠肉眼在界面里看标尺,现在可以用脚本自动断言:

import numpy as np z_min = coords[:, 2].min() z_max = coords[:, 2].max() thickness_expected = 10.0 # 容差设为 1e-6,防止节点坐标误差导致误报 assert abs(z_max - z_min - thickness_expected) < 1e-6, "厚度不一致"

实际项目里把这种断言塞进 CI 流程,每次修改设计参数后自动跑一遍 SALOME 前处理验证,比任何人肉眼检查都可靠。它也帮我避免过很多次「版本改乱了,旧网格混进新模型」的事故。

6.3 从脚本验证到流程闭环:我的参数化前处理习惯

最后分享一个我自己的习惯:每一版几何/网格参数都写一个配置文件,用 JSON 或 YAML 保存全部前处理参数,脚本启动时读这个文件。哈希文件名里带有参数版本号;改动尺寸后重跑,断言网格属性不越界,再进入求解器。这样做的好处是任何一次仿真结果出了问题,都能快速定位是哪一版几何和网格在支撑它——这是 CAE 前处理流程从「尽力而为」走向「可控可追溯」的最关键一步。

这个习惯也是 SALOME 相比商业前处理器最大的价值兑现点。用鼠标点出来的前处理流程是不可复现的,而 SALOME 的脚本化让每一步都有据可查。劝各位如果决定上手 SALOME,不要在界面上逗留太久,尽早切换到 Python 脚本工作流,后面前处理速度会拉开那些还在靠手工点选的人一大截。希望这篇笔记能帮你少走一点弯路,把 SALOME 真正用成顺手的前处理利器。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询