首页/文章/ 详情

Abaqus-Python&Pyvista梦幻联动,木木带你手把手玩转odb文件

1月前浏览332

本期推文主要内容:

  1. 基于 Python 提取 ODB 文件场数据(节点位移、应力)
  2. 在 Abaqus 环境中生成 csv 文件,并使用 matplotlib 绘制曲线图
  3. 避免生产 vtk 文件,直接使用 Pyvista 库进行 odb 文件重绘

提取 odb 文件场数据

节点位移

该操作较为简单,我就直接以代码的形式展现,并加以注释,主要用于提取模型全部节点的位移指定节点集的位移

odb_path = 'Job-2.odb'
node_set_name = 'SET-LEFT'

last_frame = odb.steps[odb.steps.keys()[-1]].frames[-1]
# 提取模型的全部节点位移
all_nodes = odb.rootAssembly.instances['PART-1-1'].nodes
displacement_field = last_frame.fieldOutputs['U'].values

# 提取模型节点集的节点位移
displacement_nset = last_frame.fieldOutputs['U'].getSubset(region=node_set).values

节点应力

应力就比较有意思了,因为有限元中的应力最开始是基于积分点上面的概念,在绘制云图时又常常使用的是节点的应力,这时就需要面对一个问题,就是如何将积分点处的应力转换为节点处,对于有限元的应力处理,我会单独开设一起推文详细讲述。

在使用 python处理 Abaqus odb 文件中的应力时,可以使用 getSubset 选取应力的位置:INTEGRATION_POINTELEMENT_NODALCENTROID。如果选取的是INTEGRATION_POINT(高斯积分点),则需要自己建立插值函数将积分点应力外插至节点处,较为麻烦,在考虑作图时不建议这么搞;若选取的是CENTROID(单元形心) 或者 ELEMENT_NODAL(单元节点),则提取的值已经由 Abaqus 进行插值后的值,直接进行均匀化处理就行。

具体参考依据,可见 Abaqus 帮助文档:If the requested field values are not found in the output database at the specified ELEMENT_NODAL orCENTROID positions, they are extrapolated from the field data at the INTEGRATION_POINT position.

为了简单起见,我选择的是 ELEMENT_NODAL,处理共节点的应力时采用“绕节点直接平均”的方式,对于单元形状差异较大的情况,可采用“加权平均”或者其他考虑单元面积/体积变化的均匀化方法,即:

# 二维情况下,提取的是应力四个分量:S11,S22,S33,S12
stress_field = last_frame.fieldOutputs['S']
stress_values = stress_field.getSubset(position=ELEMENT_NODAL).values

# 应力均匀化(绕节点直接平均)
node_stress_map = defaultdict(list) 
for value in stress_values:
    node_label = value.nodeLabel
    node_stress_map[node_label].append(value.data)  

average_node_stresses = {
    node_label: np.mean(stresses, axis=0for node_label, stresses in node_stress_map.items()
}

csv & matplotlib 操作

csv

在数据处理时,常常用到图表,那么如果在 Abaqus 中将数据导出至 csv 表格呢,在 CAE 界面中可以非常容易找到 Abaqus&Excel 选项卡,本次讨论的是在使用 Abaqus-Python 开发中如何将提取的数据导出至 CSV 文件中。

# 获取节点集的节点编号、坐标、竖向位移(借助ChatGPT)
output_data = [
    [node.label, *node.coordinates, next(
        value.data[1for value in displacement_nset if value.nodeLabel == node.label)]
    for node in node_set.nodes[0]
]

# 写入 CSV 文件
csv_file = 'node_set_output.csv'
with open(csv_file, 'w'as f:
    f.write('Node Label,X,Y,Z,U2\n')
    f.writelines(','.join(map(str, data)) + '\n' for data in output_data)

通过上面的代码,即可将指定节点集的节点编号、坐标信息、位移(U2)写入 csv 文件中,效果如下:

matplotlib

此时如果我们想将数据进一步操作,比如绘制节点集上距离裂尖处的 U2 值,如下图所示:

# 计算裂纹尖端的相对距离 r
crack_tip_x = output_data[0][1]  # 裂纹尖端的 X 坐标
data = [[row[0], row[1], row[4], crack_tip_x - row[1]] for row in output_data]
data.sort(key=lambda x: x[3])  

# 提取 r 和 U2 位移用于绘图
r_values, u2_displacements = zip(*[(row[3], row[2]) for row in data])

# 绘图
plt.figure(figsize=(86))
plt.scatter(r_values, u2_displacements, color='blue', label='Data', marker='x')
plt.axhline(0, color='black', linewidth=0.5, linestyle='--')
plt.axvline(0, color='black', linewidth=0.5, linestyle='--')
plt.xlabel('r (mm)', fontsize=12)
plt.ylabel('U2 (mm)', fontsize=12)
plt.title('Displacement vs Relative Distance from Crack Tip', fontsize=14)
plt.legend()
plt.grid(True)
plt.show()

最终可绘制如下效果:

本次案例只是分享如何在 Abaqus 环境中创建 csv 表格文件和使用 matplotlib 进行绘图,原理掌握之后,剩下的就是看操作者本身的需求了。

按照习惯来说,运行上面脚本需要在 Abaqus 界面中,点击 File->Run Script,选择 py 文件进行运行,但是每次修改 py 文件再次运行,都需要重复操作,是不是较为麻烦呢?用户可使用之前推文推荐过的 abqpy 库:【abqpy库介绍】IDE环境下运行Abaqus-Python脚本!

本次推文中的脚本可直接在 Vscode 中运行,不用打开 Abaqus 即可运行!

使用 pyvista 对 odb 文件进行重绘

原理

之前有很多小伙伴都想要对 odb 文件重绘,要么提取场数据在 Matlab 中重新绘制;要么生成 vtk 文件,导入进 Paraview 中进行可视化显示。

这些的操作都不可避免的需要针对特定单元,根据单元节点连接信息进行重新绘制单元面。如此一来,首先是麻烦,其次还是麻烦。今天教大家一个小妙招,不用这些单元节点连接信息,直接根据原来 inp 文件的信息,在原有网格的基础上添加场数据即可,相当方便。

该方法需要用到之前介绍过的 pyvista 库,详细介绍可见:VTK库学习 | 百万级自由度有限元模型云图绘制只需0.02秒!

思路:将 Abaqus 分析结果文件(ODB 文件)中的场数据导出为 .pkl 文件(.pkl 文件是 Python 的二进制序列化文件,用于高效保存和加载复杂数据结构。),并使用 PyVista 库加载已存在的网格文件(INP 文件)。通过读取导出的 .pkl 文件,将场数据添加到网格对象中,从而实现数据可视化。

场数据导出至 pkl 文件

displacement_map = {value.nodeLabel: value.data for value in displacement_field.values}
stress_map = {value.nodeLabel: value.data for value in stress_values}

node_data = {
    node.label: {
        'displacement': displacement_map[node.label],
        'stress': average_node_stresses.get(node.label, None)    
    }
    for node in all_nodes
}

加载 pkl 文件

由于 Abaqus 环境中并不支持 pyvista 库,所以不能在原来的脚本基础上进行运行含有 pyvista 的语句,需要新建一个 py 脚本,单独运行。

input_file = 'node_displacement.pkl'
with open(input_file, 'rb'as f:
    node_data = pickle.load(f)

# 读取场数据
node_displacement = []
node_stress = []

for node_label, data in node_data.items():
    displacement = data['displacement']
    S = data['stress']
    u1, u2 = displacement[0], displacement[1]
    s11, s22, s12 = S[0], S[1], S[3
    umag = np.sqrt(u1**2 + u2**2)
    mises = np.sqrt(s11**2 - s11 * s22 + s22**2 + 3 * s12**2)
    node_displacement.append([u1, u2, umag])
    node_stress.append([s11, s22, s12, mises])

# pyvista里面的数据类型都是np.array
node_displacement = np.array(node_displacement)
node_stress = np.array(node_stress)

基于 pyvista 重绘 odb 云图

# 加载inp文件
mesh = pv.read_meshio('Job-2.inp')

# 添加位移数据为标量字段
mesh["U1"] = node_displacement[:, 0]  # 第一列为 U1
mesh["U2"] = node_displacement[:, 1]  # 第二列为 U2
mesh["Umag"] = node_displacement[:, 2]  # 第三列为 Umag
mesh["S11"] = node_stress[:, 0]  # 第一列为 S11
mesh["S22"] = node_stress[:, 1]  # 第二列为 S22
mesh["S12"] = node_stress[:, 2]  # 第三列为 S12
mesh["Mises"] = node_stress[:, 3]  # 第四列为 Mises

################以下操作是pyvista绘图设置,可作参考####### 
plotter = pv.Plotter()

custom_cmap = LinearSegmentedColormap.from_list(
    'custom_cmap',
    plt.cm.coolwarm(np.linspace(0112)),  # 使用 coolwarm 的分段颜色
    N=12  # 分段数量
)

plotter.add_mesh(
    mesh,
    scalars="Mises",  # 标量字段
    cmap=custom_cmap,  # 颜色映射
    show_edges=False,  # 不显示网格边缘
    show_scalar_bar=False,
)

# 添加标量条
plotter.add_scalar_bar(
    title="Stress (MPa)",  # 标量条标题
    n_labels=13,  # 标签数量
    n_colors=12,  # 颜色分区数量
    fmt="%.3e",  # 数值格式
    vertical=True,  # 垂直显示
    width=0.05,  # 标量条宽度
    position_x=0.03,  # x 坐标位置
    position_y=0.5,  # y 坐标位置
    font_family="times",  # 字体
)

plotter.add_axes(line_width=5,
cone_radius=0.6,
shaft_length=0.7,
tip_length=0.3,
ambient=0.5,
label_size=(0.40.16))

plotter.camera_position = "xy" 

# 显示绘图
plotter.show()

最终绘制的效果:

使用 pyvista 库有很多好处:

  1. 扩展性好
  2. 速度极快,丝滑
  3. 可借助内部方法 .save_meshio 导出文件类型很多,如:Abaqus, Ansys msh, AVS-UCD, CGNS, DOLFIN XML, Exodus, FLAC3D, H5M, Kratos/MDPA, Medit, MED/Salome, Gmsh (versions 2 and 4), OBJ, OFF, PERMAS, PLY, STL, TetGen .node/.ele, SVG (2D only, output only), UGRID, WKT (TIN), XDMF, and more.
  4. 更多好处可见官网:https://docs.pyvista.org

脚本获取

本次演示使用到了两个 py脚本、一个 odb 文件和一个 inp 文件,后台回复:odb文件重绘,即可自动获取(注意字母和汉字之间没有空格)。

友情提示:本次的计算分析基于 Abaqus2025 平台,python 脚本语言遵循 python3 的语法。


本篇推文详细介绍了 Abaqus-Python 二次开发中提取场数据的操作流程,包括数据提取、图表处理,并借助 PyVista 库实现可视化重绘。希望本文对您有所帮助,感谢阅读,期待下期再见!



来源:易木木响叮当
AbaqusSTEPS二次开发MATLABUGpython裂纹
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-01-08
最近编辑:1月前
易木木响叮当
硕士 有限元爱好者
获赞 229粉丝 300文章 368课程 2
点赞
收藏
作者推荐
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈