首页/文章/ 详情

数据拖垮仿真?Python & ANSYS二次开发-轻松拿捏Mechanical瞬态时域数据

2小时前浏览7


导读:大家好,我是小郭老师,硕士毕业于中科院,专注于运用 Python 深度集成 ANSYS 进行工程数值计算与仿真自动化开发,精通基于 Python实现ANSYS Workbench众多模块的全流程脚本驱动(建模、求解、后处理),并具备将复杂仿真流程封装为高效、可复用软件工具的专业能力,今天给大家分享一些ANSYS二次开发方面的干货。

做科研写论文时,你是不是也遇到过这样的困扰:明明做了 ANSYS 模拟,却没法快速生成如下图所示的模拟瞬态数据和实验数据的对比,导致数值模型的可信度没法直观验证?亦或者,依据项目需求,一定得导出某些关键位置的瞬态响应结果?别急,今天小郭老师就带着大家用 Mechanical 的 Python 脚本开发,解决这个问题。

也诚邀关注我的视频教程ANSYS Workbench & Mechanical企业级二次开发程序与Python应用入门进阶,详情见下文。
 

 


01    

ANSYS Mechanical脚本开发概述    


ANSYS Mechanical 脚本开发是基于Python(或 IronPython)语言,通过调用Mechanical模块的 API(应用程序接口)实现有限元分析流程自动化的技术手段。

它聚焦于Mechanical模块内部的建模、网格划分、边界条件设置、求解控制及后处理等全流程的程序化控制Mechanical,可通过两种方式入门:

  • 一是利用 Mechanical自带的 “Record Script” 功能录制操作过程,生成基础脚本后再按需修改;

  • 二是直接调用官方API 文档中的类与方法(如Model类用于模型管理、Mesh类用于网格控制),实现更灵活的定制。


02    

瞬态数据导出关键命令:Named Selection + Result Sets    


在 Mechanical 的 Python 脚本开发中,要实现模拟数据的精准提取与后续对比,关键在于结合Named Selection(命名选择) 和Result Sets(结果集)。

先跟大家好好聊聊 Named Selection。它就像是给 ANSYS 里的 “特定对象组” 贴标签,是对已选出的实体、有限元对象、组合和集 合进行的命名操作。在二次开发中,Named Selection可以用来定位目标边、面、几何体,乃至某个区域下的网格节点。

Named Selection(命名选择)主要有两种创建方式,直接法和间接法。在二次开发场景下,两者的实用性差异很大:

直接法:第一步得先选出要命名的点、线、面等对象,接着右键点击 “create named selections”,输入名称后点击 OK 完成创建。

这个方法听起来简单,但在二次开发里实现起来非常复杂,得结合ID概念和 SelectionMana ger 类,代码逻辑比较绕,但能实现很复杂的功能。

关于这部分内容,我在《ANSYS Workbench & Mechanical 二次开发与 Python 应用》第2章有做详细介绍,涵盖基本用法、示例等各种内容。

间接法:通过 Worksheet 进行选择。只要按照 Worksheet 给定的逻辑写代码,就能快速实现 Named Selection 创建,今天咱们的实战案例就用这种方法。

Result Sets(结果集)的创建方式如图所示。右键激活已经完成后处理求解的云图对象,选择Create Results at All Sets,即可生成TreeGroup对象。该对象内包含所有时步下的云图结果。

创建结果集的适用范围非常广,仅对极少数不适用,包括:

  • Explicit Dynamics, Response Spectrum, Random Vibration, or Topology Optimization an alyses(显示动力学、响应谱、随机振动和拓扑优化分析)

  • Probe Results(探针结果)

  • Fracture Tool(断裂工具)

  • Fatigue Tool(疲劳工具)

  • Composite Failure Tool(复合材料失效工具)


03    

实战操作:从数据筛选到导出的完整流程    


步骤 1:用 Named Selection 筛选目标检测点附近网格节点









































create_ns_by_pointsdef create_ns_by_points(point_coords, ns_name, tolerance=0.05):    ns_point = Model.AddNamedSelection()    ns_point.Name = ns_name    ns_point.ScopingMethod = GeometryDefineByType.Worksheet    axes_config = [        {            "criterion": SelectionCriterionType.LocationX,  # X坐标选择准则            "action": SelectionActionType.Add  # 添加操作(第一个条件)        },        {            "criterion": SelectionCriterionType.LocationY,  # Y坐标选择准则            "action": SelectionActionType.Filter  # 过滤操作(后续条件)        },        {            "criterion": SelectionCriterionType.LocationZ,  # Z坐标选择准则            "action": SelectionActionType.Filter  # 过滤操作(后续条件)        }    ]    for i, config in enumerate(axes_config):        ns_point.GenerationCriteria.Add(None)        criterion = ns_point.GenerationCriteria[i]        criterion.EntityType = SelectionType.MeshNode  # 选择网格节点        criterion.Criterion = config["criterion"]  # 设置选择准则(X/Y/Z坐标)        criterion.Operator = SelectionOperatorType.RangeInclude  # 设置操作符为范围包含        criterion.Action = config["action"]  # 设置动作类型(添加/过滤)        coord_value = point_coords[i]          lower = coord_value * (1 - tolerance)        upper = coord_value * (1 + tolerance)        if lower > upper:            lower, upper = upper, lower        if abs(lower) < 1e-4:            lower = -1e-4        elif abs(upper) < 1e-4:            upper = 1e-4        criterion.LowerBound = Quantity('%.6f [m]' % lower)  # 下界        criterion.UpperBound = Quantity('%.6f [m]' % upper)  # 上界    ns_point.Generate()    return ns_point


咱们来看看关键逻辑:

先初始化命名选择对象,设置名称和创建方式为 Worksheet;

配置坐标轴(X、Y、Z 轴)的筛选规则,比如通过位置信息筛选节点,这里用 “Add” 和 “Filter” 组合确保筛选精准;

计算每个坐标轴的边界值:根据检测点坐标和设定的公差(这里默认为0.05=5%),算出筛选范围。此外,还加了冗余判断 —— 当边界值接近 0 时(小于 1e-4),手动调整避免计算误差;

最后生成命名选择,这样目标检测点附近的网格节点就被精准 “圈” 出来了。

例如,一电子器件冷却三维模型的目标检测点筛选结果如下图所示。可以看到,在给定的监测点坐标范围内(正负5%波动),仅筛选出一个网格节点。

步骤 2:插入后处理对象 + 求解

筛选出目标节点后,下一步就是获取对应的数据。先在分析方案的 Solution 里插入后处理对象,比如温度(Temperature),然后把这个后处理对象的 Location 设置为咱们刚创建的 Named Selection(也就是目标节点组),接着运行第一次求解,让 ANSYS 计算出该节点组在最终时刻下的结果。

步骤 3:创建求解集 + 二次求解

第一次求解后,要创建该后处理对象的 “求解集”,也就是CreateResultsAtAllSets。创建完求解集后,再运行一次求解。这样子,就能获取到整个分析过程中(比如瞬态分析的每个时间步)该节点组的所有结果数据。

步骤 4:遍历求解集 + 数据写入文件

最后一步,就是把结果数据导出来,方便后续和实验数据做对比。我写的export_trasient_file函数就能实现这个功能,核心逻辑包括如下四部分内容:

1、以当前时间为后缀生成 CSV 文件,一个存所有节点的详细数据,一个存每个时间步的平均值(方便快速看整体趋势);

2、写入表头,比如 “Time (s) Node_ID X (m) Y (m) Z (m) Value”,让数据结构清晰,后续用 Excel 或 Origin 处理时直接就能用;

3、遍历每个时间步的结果集,提取时间、节点 ID、节点坐标、结果数值(比如温度值),逐行写入详细数据文件;

4、同时,计算每个时间步下所有节点结果的平均值,写入平均值文件,后续画对比图时,既可以用详细数据,也能用平均值.

函数程序如下所示:

   































def export_trasient_file(result_objs, root_path):    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")    output_file = os.path.join(root_path, "ANSYSResult_%s.csv" % timestamp)    avg_output_file = os.path.join(root_path, "avg_ANSYSResult_%s.csv" % timestamp)    meshData = DataModel.MeshDataByName("Global")    with open(output_file, 'wb'as csvfile, open(avg_output_file, 'wb'as avg_csvfile:        writer = csv.writer(csvfile)  # 详细数据写入器        avg_writer = csv.writer(avg_csvfile)  # 平均值数据写入器        writer.writerow(["Time (s)""Node_ID""X (m)""Y (m)""Z (m)""Value"])        avg_writer.writerow(["Time (s)""Average_Value"])        total_steps = len(result_objs)  # 总时间点数        for i in range(total_steps):            result_obj = result_objs[i]  # 当前时间点的结果对象            time = str(result_obj.Time).split(" ")[0]            result_data = result_obj.PlotData            node_ids = result_data["Node"]            values = result_data["Values"]            sum_value = 0.0  # 结果值总和            for j in range(len(node_ids)):                node_id = node_ids[j]  # 节点ID                node_value = values[j]  # 结果值                node = meshData.NodeById(node_id) # 获取节点对象                row_data = [time, node_id, node.X, node.Y, node.Z, node_value]                writer.writerow(row_data)                sum_value += node_value            if len(node_ids) > 0:                avg_value = sum_value / len(node_ids)            else:                avg_value = 0.0            avg_writer.writerow([time, avg_value])
   



04    

完整代码及关键注释    


上面讲的流程,都浓缩在下面这段代码里了,每个关键步骤我都加了注释,大家拿到手稍作修改(比如改检测点坐标、结果类型)就能用:

   


















































































































































# 导入必要的模块import os  # 提供操作系统相关功能,如文件路径操作import datetime  # 提供日期和时间处理功能import csvdef create_ns_by_points(point_coords, ns_name, tolerance=0.05):    """    基于点坐标创建命名选择    参数:    point_coords -- 点坐标列表 [X, Y, Z]    ns_name -- 命名选择的名称    tolerance -- 容差百分比 (默认0.05,即5%)    返回:    创建的命名选择对象    """    # 创建新的命名选择对象    ns_point = Model.AddNamedSelection()    ns_point.Name = ns_name  # 设置命名选择的名称    ns_point.ScopingMethod = GeometryDefineByType.Worksheet  # 设置作用域方法为工作表    # 定义坐标轴配置列表    axes_config = [        {            "criterion": SelectionCriterionType.LocationX,  # X坐标选择准则            "action": SelectionActionType.Add  # 添加操作(第一个条件)        },        {            "criterion": SelectionCriterionType.LocationY,  # Y坐标选择准则            "action": SelectionActionType.Filter  # 过滤操作(后续条件)        },        {            "criterion": SelectionCriterionType.LocationZ,  # Z坐标选择准则            "action": SelectionActionType.Filter  # 过滤操作(后续条件)        }    ]    # 为每个坐标轴添加生成条件    for i, config in enumerate(axes_config):        # 添加新的生成条件        ns_point.GenerationCriteria.Add(None)        # 获取当前生成条件对象        criterion = ns_point.GenerationCriteria[i]        ### 设置通用属性 ###        criterion.EntityType = SelectionType.MeshNode  # 选择网格节点        criterion.Criterion = config["criterion"]  # 设置选择准则(X/Y/Z坐标)        criterion.Operator = SelectionOperatorType.RangeInclude  # 设置操作符为范围包含        criterion.Action = config["action"]  # 设置动作类型(添加/过滤)        ### 计算并设置边界值 ###        # 获取当前坐标轴的值        coord_value = point_coords[i]          # 计算下界和上界        lower = coord_value * (1 - tolerance)        upper = coord_value * (1 + tolerance)        # 确保上界大于下界        if lower > upper:            lower, upper = upper, lower        # 处理接近零的边界值(避免精度问题)        if abs(lower) < 1e-4:            lower = -1e-4        elif abs(upper) < 1e-4:            upper = 1e-4        # 设置边界值(带单位)        criterion.LowerBound = Quantity('%.6f [m]' % lower)  # 下界        criterion.UpperBound = Quantity('%.6f [m]' % upper)  # 上界    # 生成命名选择    ns_point.Generate()    return ns_pointdef export_trasient_file(result_objs, root_path):    """    导出瞬态结果数据到CSV文件    参数:    result_objs -- 结果对象列表(每个时间点一个结果对象)    root_path -- 文件保存的根目录路径    """    # 获取当前时间作为文件名后缀(格式:年月日_时分秒)    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")    # 构建详细数据文件路径    output_file = os.path.join(root_path, "ANSYSResult_%s.csv" % timestamp)    # 构建平均值数据文件路径    avg_output_file = os.path.join(root_path, "avg_ANSYSResult_%s.csv" % timestamp)    # 获取网格数据(全局网格)    meshData = DataModel.MeshDataByName("Global")    # 打开两个CSV文件准备写入    with open(output_file, 'wb'as csvfile, open(avg_output_file, 'wb'as avg_csvfile:        # 创建CSV写入器        writer = csv.writer(csvfile)  # 详细数据写入器        avg_writer = csv.writer(avg_csvfile)  # 平均值数据写入器        # 写入表头        writer.writerow(["Time (s)""Node_ID""X (m)""Y (m)""Z (m)""Value"])        avg_writer.writerow(["Time (s)""Average_Value"])        # 遍历所有时间点的结果        total_steps = len(result_objs)  # 总时间点数        for i in range(total_steps):            result_obj = result_objs[i]  # 当前时间点的结果对象            # 提取时间值(去除单位)            time = str(result_obj.Time).split(" ")[0]            # 获取绘图数据            result_data = result_obj.PlotData            # 获取节点ID和结果值            node_ids = result_data["Node"]            values = result_data["Values"]            # 初始化当前时间点的统计变量            sum_value = 0.0  # 结果值总和            # 遍历当前时间点的所有节点            for j in range(len(node_ids)):                node_id = node_ids[j]  # 节点ID                node_value = values[j]  # 结果值                node = meshData.NodeById(node_id) # 获取节点对象                # 准备行数据:时间, 节点ID, X坐标, Y坐标, Z坐标, 结果值                row_data = [time, node_id, node.X, node.Y, node.Z, node_value]                # 写入详细数据文件                writer.writerow(row_data)                # 累加结果值(用于计算平均值)                sum_value += node_value            # 计算当前时间点的平均值            if len(node_ids) > 0:                avg_value = sum_value / len(node_ids)            else:                avg_value = 0.0  # 如果没有节点,平均值设为0            # 写入平均值文件:时间, 平均值            avg_writer.writerow([time, avg_value])# 定义监测点坐标 [X, Y, Z]monitor_coords = [01.65e-0025.5207e-003]# 创建监测点命名选择ns_monitor = create_ns_by_points(monitor_coords, ns_name="ns_point1")# 检查命名选择是否成功创建if ns_monitor.Location:    print "定位到监测点,正在导出数据"    # 获取分析解决方案对象    ana lysis = DataModel.Ana lysisList[0]    ana lysis_solution = ana lysis.Solution    # 添加温度结果    temp = a nalysis_solution.AddTemperature()    # 设置温度结果的位置为监测点命名选择    temp.Location = ns_monitor    # 评估所有结果    ana lysis_solution.EvaluateAllResults()    # 获取所有时间点的结果集    temp_sets = temp.CreateResultsAtAllSets()    # 再次评估所有结果(确保数据最新)    an alysis_solution.EvaluateAllResults()    # 获取桌面路径    desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")    # 导出瞬态数据到CSV文件    export_trasient_file(temp_sets, desktop_path)    print "数据导出完毕,路径为:%s" % desktop_pathelse:    print "警告:监测点命名选择创建失败"
   



05    

二次开发的实用性,不止于数据导出    


可能有人会问,手动也能提取数据,为啥要费劲搞二次开发?

作为实战工程师,我举个实际工作中的例子:之前做过一个课题研究,需要处理瞬态温度分析结果,一共 360个时间步,每个时间步要提取10个检测点的数据,重复性工作量大,还很容易出错。

用上面的脚本,设置好坐标后点击运行,2 分钟就能出所有 CSV 文件。之后,再用 Origin 导入数据,10 分钟就能画出模拟与实验的对比曲线图,效率直接翻十几倍!

而且,这个脚本还能灵活修改。比如,把AddTemperature()改成AddEquivalentStress()就能提取应力数据,调整monitor_coords就能换检测点,甚至加个循环能同时处理多个检测点,完全适配不同的项目需求。

实际上,结合ANSYS Mechanical API和Python脚本开发,可以实现Mechanical的完全脚本化和高度可定制化,例如模板开发、自定义载荷、后处理及结果等。

看完这篇,是不是觉得 ANSYS 二次开发没那么难。如果你也在为模拟数据处理头疼,不妨试试这个脚本。强烈推荐读者朋友订阅我的《ANSYS Workbench & Mechanical企业级二次开发程序与Python应用入门进阶》


06    

我的ANSYS二次开发教程      


本课程从基础脚本开发到多工况批量计算的自动化实现,手把手教你用 Python 打通 “仿真流程自动化 - 多工况批量计算” 全链路,让 “重复仿真工作自动化、复杂工况高效计算” 从想法变成日常。

我还为付费用户提供VIP群进行交流、答疑服务持续加餐内容提供定制化培训咨询服务仿真人才库高新内推就业仿真秀还提供奖学金、学完此课程,推荐学习者报名参加工程仿真技术(CAE分析职业能力等级评价证书)。

此外,在使用过程中遇到代码报错、需求调整等问题,欢迎在评论区留言,我会一一解答。后续还会分享更多 ANSYS 二次开发的实战技巧,敬请关注。  


可回放,开具发票,奖学金、直播加餐

提供vip群答疑和模型下载

《ANSYS Workbench & Mechanical企业级二次开发程序与Python应用入门进阶》



    


扫码查看视频教程

以下是课程大纲及主要内容:

 


来源:仿真秀App

ACTMechanicalWorkbenchHyperMeshHyperView振动疲劳断裂复合材料拓扑优化二次开发通用电子焊接材料控制试验
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-10-14
最近编辑:2小时前
仿真圈
技术圈粉 知识付费 学习强国
获赞 11338粉丝 22714文章 3984课程 239
点赞
收藏
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈