导读: 大家好,我是小郭老师,硕士毕业于中科院,专注于运用 Python 深度集成 ANSYS 进行工程数值计算与仿真自动化开发,精通基于 Python实现ANSYS Workbench众多模块的全流程脚本驱动(建模、求解、后处理),并具备将复杂仿真流程封装为高效、可复用软件工具的专业能力,今天给大家分享一些ANSYS二次开发方面的干货。
在ANSYS仿真后处理中,提取任意自定义平面的物理量(如应力、位移、应变)是高频需求——小到零部件的截面分析,大到复杂结构的多平面验证,都离不开“筛选目标平面节点”这一步。但传统手动框选的方式,不仅容易漏选、错选,精度全靠肉眼判断,遇到复杂网格或多批次分析时,重复操作更是耗时费力。
前阵子有学员专门找我反馈:“能不能做一个工具,我选3个节点定好平面,软件自动把平面内所有节点都抓出来?”。今天就基于这个真实工程需求,带大家用ANSYS二次开发实现“3点定平面+节点自动抓取+一键封装”,全程干货,代码可直接复制使用!
其实这个需求的核心逻辑很简单——用数学方法精准定位平面,再用代码批量筛选节点,具体可以拆成4个关键步骤,小白也能看懂:
整个过程用代码替代了手动框选的“模糊操作”,既保证了精度,又省去了重复劳动,这正是ANSYS二次开发的实用价值所在。
下面我们结合完整代码,逐模块拆解核心功能——代码基于ANSYS Mechanical的Python API开发,兼容大部分版本,关键部分都加了详细注释,大家可以边看边理解。
这部分是整个工具的“数学核心”,负责平面方程计算和节点有效性判断,完全独立于ANSYS界面,逻辑通用:
代码块
Python
自动换行
复制代码
123456789101112131415161718192021222324
def calculate_plane_equation(p1, p2, p3):
"""
通过三个点计算平面方程系数
参数:
p1, p2, p3: 三个点的坐标,每个点是一个包含(x, y, z)的元组/列表
返回:
a, b, c, d: 平面方程ax + by + cz + d = 0的系数
"""
# 计算从p1出发的两个向量
AB = (p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]) # 向量AB
AC = (p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]) # 向量AC
# 通过叉积计算法向量
normal = (AB[1]*AC[2] - AB[2]*AC[1], # 法向量的x分量
AB[2]*AC[0] - AB[0]*AC[2], # 法向量的y分量
AB[0]*AC[1] - AB[1]*AC[0]) # 法向量的z分量
# 提取法向量分量作为平面方程系数a, b, c
a, b, c = normal
d = -(a * p1[0] + b * p1[1] + c * p1[2]) # 计算常数项d
return a, b, c, d
复制成功
通过3个基准点的坐标,用向量叉积求出平面的法向量,进而推导平面方程ax+by+cz+d=0的4个系数(a、b、c、d)。 核心逻辑:先计算从第一个点出发的两个向量,再通过叉积得到垂直于这两个向量的法向量(法向量方向就是平面的垂直方向),最后代入点坐标求出常数项d。
代码块
Python
自动换行
复制代码
123456789101112131415161718192021222324
def is_point_on_plane(point, plane_coeffs, tolerance=1e-2):
"""
判断点是否在平面上
参数:
point: 点的坐标(x, y, z)
plane_coeffs: 平面方程系数(a, b, c, d)
tolerance: 距离容差,默认为1e-3
返回:
True/False: 点是否在平面上
"""
a, b, c, d = plane_coeffs # 解包平面方程系数
# 计算点到平面的距离
numerator = abs(a*point[0] + b*point[1] + c*point[2] + d) # 绝对距离
denominator = math.sqrt(a*a + b*b + c*c) # 法向量模长
if denominator == 0: # 避免除零错误
return False
normalized_distance = numerator / denominator # 计算归一化距离
return normalized_distance < tolerance # 判断是否在容差范围内
复制成功
判断单个节点是否在目标平面上,核心是“距离容差法”: 计算节点到平面的垂直距离,若距离小于设定的容差(默认1e-2,可根据网格精度调整),则认为节点在平面上。 这里加了“除零防护”——如果法向量模长为0(说明3个基准点共线,无法构成平面),直接返回False,避免程序报错。
代码块
Python
自动换行
复制代码
123456789101112131415161718192021222324
def get_nodes_on_plane(mesh_data, plane_p1, plane_p2, plane_p3, tolerance=1e-2):
"""
获取网格中位于指定平面上的所有节点
参数:
mesh_data: 网格数据对象
plane_p1, plane_p2, plane_p3: 定义平面的三个点
tolerance: 距离容差,默认为1e-3
返回:
on_plane_nodes: 位于平面上的节点ID列表
"""
# 计算平面方程
plane_coeffs = calculate_plane_equation(plane_p1, plane_p2, plane_p3)
on_plane_nodes = [] # 存储平面上节点ID的列表
# 遍历网格中的所有节点
for node in mesh_data.Nodes:
node_coords = (node.X, node.Y, node.Z) # 获取节点坐标
if is_point_on_plane(node_coords, plane_coeffs, tolerance): # 判断是否在平面上
on_plane_nodes.append(node.Id) # 存储节点ID
return on_plane_nodes
复制成功
批量遍历模型所有节点,调用上面的“节点平面判断函数”,把符合条件的节点ID收集起来,最终返回一个“平面内节点ID列表”,为后续创建命名选择做准备。
这部分是代码与ANSYS Mechanical交互的关键,负责获取用户操作、校验输入合法性、执行筛选并生成命名选择:
通过获取模型的全局网格数据,这是读取所有节点坐标的基础; 通过获取用户当前选中的节点,提取节点ID和坐标。
强制要求用户必须选中3个节点——如果选中节点数不是3,会弹出错误提示(“错误!手动选择必须选择3个节点”),并终止程序,避免因输入错误导致计算失败。
代码块
Python
自动换行
复制代码
12345
# 确定平面的三个点
if len(node_ids) != 3: # 必须选择3个节点
msg = Ansys.Mechanical.Application.Message("错误!手动选择必须选择3个节点", MessageSeverityType.Error)
ExtAPI.Application.Messages.Add(msg)
raise ValueError("错误!手动选择必须选择3个节点")
复制成功
(3)平面节点抓取与命名选择创建
调用前面定义的函数,获取目标平面上的所有节点ID; 通过创建新的命名选择,将筛选出的节点ID赋值给命名选择,最后执行生成,全程自动完成,无需手动干预。
代码块
Python
自动换行
复制代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
# 导入数学库,用于向量和距离计算
import math
################################################################################
# 函数定义
################################################################################
def calculate_plane_equation(p1, p2, p3):
"""
通过三个点计算平面方程系数
参数:
p1, p2, p3: 三个点的坐标,每个点是一个包含(x, y, z)的元组/列表
返回:
a, b, c, d: 平面方程ax + by + cz + d = 0的系数
"""
# 计算从p1出发的两个向量
AB = (p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]) # 向量AB
AC = (p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]) # 向量AC
# 通过叉积计算法向量
normal = (AB[1]*AC[2] - AB[2]*AC[1], # 法向量的x分量
AB[2]*AC[0] - AB[0]*AC[2], # 法向量的y分量
AB[0]*AC[1] - AB[1]*AC[0]) # 法向量的z分量
# 提取法向量分量作为平面方程系数a, b, c
a, b, c = normal
d = -(a * p1[0] + b * p1[1] + c * p1[2]) # 计算常数项d
return a, b, c, d
def is_point_on_plane(point, plane_coeffs, tolerance=1e-2):
"""
判断点是否在平面上
参数:
point: 点的坐标(x, y, z)
plane_coeffs: 平面方程系数(a, b, c, d)
tolerance: 距离容差,默认为1e-3
返回:
True/False: 点是否在平面上
"""
a, b, c, d = plane_coeffs # 解包平面方程系数
# 计算点到平面的距离
numerator = abs(a*point[0] + b*point[1] + c*point[2] + d) # 绝对距离
denominator = math.sqrt(a*a + b*b + c*c) # 法向量模长
if denominator == 0: # 避免除零错误
return False
normalized_distance = numerator / denominator # 计算归一化距离
return normalized_distance < tolerance # 判断是否在容差范围内
def get_nodes_on_plane(mesh_data, plane_p1, plane_p2, plane_p3, tolerance=1e-2):
"""
获取网格中位于指定平面上的所有节点
参数:
mesh_data: 网格数据对象
plane_p1, plane_p2, plane_p3: 定义平面的三个点
tolerance: 距离容差,默认为1e-3
返回:
on_plane_nodes: 位于平面上的节点ID列表
"""
# 计算平面方程
plane_coeffs = calculate_plane_equation(plane_p1, plane_p2, plane_p3)
on_plane_nodes = [] # 存储平面上节点ID的列表
# 遍历网格中的所有节点
for node in mesh_data.Nodes:
node_coords = (node.X, node.Y, node.Z) # 获取节点坐标
if is_point_on_plane(node_coords, plane_coeffs, tolerance): # 判断是否在平面上
on_plane_nodes.append(node.Id) # 存储节点ID
return on_plane_nodes
################################################################################
# 主程序逻辑:根据指定模式确定平面,然后获取平面上所有节点并创建命名选择
################################################################################
# 获取网格数据
meshData = DataModel.MeshDataByName("Global") # 从DataModel获取网格数据
selection = ExtAPI.SelectionManager.CurrentSelection # 获取当前选择
node_ids = selection.Ids # 获取选择的节点ID
# 确定平面的三个点
if len(node_ids) != 3: # 必须选择3个节点
msg = Ansys.Mechanical.Application.Message("错误!手动选择必须选择3个节点", MessageSeverityType.Error)
ExtAPI.Application.Messages.Add(msg)
# raise ValueError("错误!手动选择必须选择3个节点")
else:
plane_points = [] # 存储平面点坐标
for node_id in selection.Ids: # 遍历选择的节点
node = meshData.NodeById(node_id) # 通过ID获取节点
plane_points.append([node.X, node.Y, node.Z]) # 存储坐标
# 获取平面上所有节点的ID
nodeIds_on_plane = get_nodes_on_plane(meshData, plane_points[0], plane_points[1], plane_points[2])
# 创建命名选择
selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.MeshNodes) # 创建网格节点选择对象
selection.Ids = nodeIds_on_plane # 设置选择的节点ID
ns = Model.AddNamedSelection() # 添加命名选择
ns.Location = selection # 设置选择位置
ns.Generate() # 生成命名选择
复制成功
代码写好后,不用每次都复制粘贴到Scripting窗口——利用ANSYS Mechanical的「User Buttons」功能,可直接封装成自定义按钮,下次用的时候点击一下就行,步骤超简单:
「User Buttons」是ANSYS Mechanical Automation选项卡下的原生功能,专门用于存放用户自定义的二次开发工具,支持Python代码直接封装,无需复杂配置。


1. 在ANSYS Mechanical中,打开已划分网格的模型;
2. 选中网格节点功能,选择至少三个的网格节点:

3. 点击「Automation -> User Buttons -> GetPlaneNodes (自己给定的按钮名称)」,程序会自动计算平面、筛选节点,并创建命名选择;
4. 后续提取物理量时,直接选择这个命名选择,即可快速获取目标平面的所有物理量数据。

这个工具虽然简单,但精准解决了“自定义平面节点筛选”的高频痛点,核心优势很明确:
• 适配任意平面:不管是倾斜平面、复杂截面,只要选3个基准点,就能自动抓取所有平面内节点;
• 操作极简:封装后一键调用,无需专业编程知识,普通工程师也能快速上手;
• 延伸性强:生成的命名选择可直接用于物理量提取、云图显示、数据导出,甚至批量优化分析。
其实ANSYS二次开发不用追求“高大上”,从实际工程需求出发,用几行代码解决一个具体痛点,就是最实用的开发。比如这个工具,看似简单,却能让工程师从重复的手动操作中解放出来,把时间花在更核心的仿真分析上——这正是二次开发的核心意义。
如果大家还有其他ANSYS使用中的痛点(比如批量设置载荷、自动生成报告、多工况对比等),欢迎在评论区留言,后续会持续分享针对性的二次开发实战案例!
点击链接《https://www.fangzhenxiu.com/course/13411984/》,立即学习《ANSYS Workbench & Mechanical企业级二次开发程序与Python应用入门进阶》,掌握ANSYS Workbench & Mechanical的脚本自动化开发能力。
本课程从基础脚本开发到多工况批量计算的自动化实现,手把手教你用 Python 打通 “仿真流程自动化 - 多工况批量计算” 全链路,让 “重复仿真工作自动化、复杂工况高效计算” 从想法变成日常。
我还为付费用户提供VIP群进行交流、答疑服务、持续加餐内容、提供定制化培训和咨询服务、仿真人才库高薪内推就业、仿真秀还提供奖学金、学完此课程,推荐学习者报名参加工程仿真技术(CAE分析职业能力等级评价证书)。
以下是课程大纲及主要内容:

免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删