简介
在有限元软件Abaqus中,场输出数据的提取通常可在后处理界面中借助创建XY Data或者使用Report选项中的Field Output功能来实现。然而,这些功能只适用于在提取的数据量较少时使用。如果需要同时提取多个Odb文件或多个分析步中的场输出数据,手动提取将变得非常繁琐。此时,使用Python可非常轻松地实现对场输出数据的批量提取。本文将主要介绍如何基于Python输出Abaqus场输出数据。
程序实现
为基于Python提出场输出数据,本文的主要思路为:首先,在Python程序中定义提出场输出数据所需要设定的一些参数,例如待提取Odb文件的路径和文件名,待提取数据所在的分析步和增量步,以及待提取的场输出变量的名称,如应力或应变结果。此外,大多数情况下我们并不需要提取整个模型中所有单元的场输出数据,因此需要指定待提取的单元或节点。考虑到当单元或节点数量较多时,在Python程序中直接指定单元或节点编号非常繁琐,因此最好是可以在后处理界面中以可视化地方式提前定义好单元或节点集,然后在Python程序中通过指定单元集或节点集的名称来访问指定的单元或节点。 实现上述功能所对应的代码片段下所示。
#-* - coding:UTF-8 -*-
#导入Abaqus模块
from odbAccess import *
from abaqusConstants import *
#提取参数定义
Odb_Path='C:/Users/Lenovo/Desktop/Field_Output_Extract/' #Odb文件路径
Odb_Name='Plate.odb' #Odb文件名称
Elem_Set_Name='Stress_Elem' #单元集 合名称
Step_Name='Step-1' #待提取分析步名称(与Odb文件中分析步名称一致)
File_Variable_Label='E' #待提取场变量(与Abaqus中定义一致)
Frame_Start=0 #待提取增量步的起始编号
Frame_End=5 #待提取增量步的终止编号
#------------------------------读取待提取的单元集中的单元号-----------------------
#以只读方式打开odb文件
My_Odb=openOdb(path=Odb_Path+Odb_Name,readOnly=True)
#读取用户指定的单元集 合
try:
My_Elem_Set=My_Odb.rootAssembly.elementSets[Elem_Set_Name]
except:
print('\n'*2)
print("Error:The specified element set does not exist!")
#读取单元集 合中的单元号
My_Elem_Labels=[]
for Element in My_Elem_Set.elements:
for Sub_Element in Element:
My_Elem_Labels.append(Sub_Element.label)
#------------------------------------------------------------------------------
在上述代码中,Odb_Path
和Odb_Name
分别代表了Odb文件所在路径和Odb文件名。Elem_Set_Name
代表用户定义的单元集 合名称。Step_Name
为待提取场输出数据所在的分析步名称。File_Variable_Label
为待提取场输出变量的名称,为了保证场输出变量被正确读取,必须与Abaqus中场变量的名称保持一致,如应力用S表示,应变用E表示。Frame_Start
和Frame_End
为待提取场输出数据所在增量步的起始编号和终止编号,该参数允许提取多个增量步中的场输出数据。
首先,程序将通过openOdb
方法以只读方式打开用户指定的Odb文件。然后,程序将基于用户指定的单元集名称,尝试在Odb文件中读取对应的单元集。如果没有找到同名的单元集,则程序将输出错误信息。
如果对应的单元集被找到,则对应于该单元集的elementSets
对象将被存放于My_Elem_Set
变量中。在elementSets
对象中,单元编号存放于子对象elementSets.elements.label
中。因此,程序将会遍历所有子对象,并将读取到的单元编号存放于变量My_Elem_Labels
中。
待程序读取到用户指定的单元编号后,下一步即可根据单元编号获取该单元在指定分析步和增量步上的场输出数据。为了能够顺利找到单元对应的场输出数据,需要用户对于Abaqus的输出数据库对象的构成有一定了解。下图展示了Abaqus中数据库对象构成的示意图。
实现提取减缩积分单元在积分点上的场输出数据的程序片段如下所示。
#------------------------------读取单元集中单元场输出变量值-----------------------
#读取指定分析步
My_Step=My_Odb.steps[Step_Name]
#读取指定分析步的增量步(遍历所有增量步)
print('\n'*100)
for Frame_Index in range(Frame_Start,Frame_End+1):
My_Frame=My_Step.frames[Frame_Index]
#获取场输出值所在的全部对象(所有单元)
Field_Value=My_Frame.fieldOutputs[File_Variable_Label].values
#创建快速查询字典 建立单元号与对象索引的关系(键:单元号 值:对象)
Element_Map={}
for Val in Field_Value:
Element_Map[Val.elementLabel]=Val
#读取单元集中单元场并格式化输出变量值
print('\n'*2)
for Current_Label in My_Elem_Labels:
#格式化输出增量步号(9位右对齐整型)
Formatted_Frame='%9d' % int(Frame_Index)
#格式化输出单元号(9位右对齐整型)
Formatted_Label='%9d' % int(Current_Label)
#格式化输出场输出数据(12位对齐科学计数法)
Formatted_Values=[]
for Val in Element_Map[Current_Label].data:
Formatted_Val='%12.5e' % float(Val)
Formatted_Values.append(Formatted_Val)
#拼接单元号及输出数据
Output_Line=Formatted_Frame+' '+Formatted_Label +' ' + ' '.join(Formatted_Values)
#输出数据行至屏幕
print(Output_Line)
#------------------------------------------------------------------------------
在上述程序片段中,My_Odb.steps[Step_Name]
用于访问用户指定分析步的step
对象,并将其存储在变量My_Step
中。然后,My_Step.frames[Frame_Index]用于访问当前指定分析步中frame
对象,Frame_Index
代表当前指定分析步中frame
对象的索引值,例如取值为0时代表初始增量步,取值为-1时代表最后一个增量。通过遍历所有的frame
对象,即可访问所有增量步下场输出数据的取值。
My_Frame.fieldOutputs[File_Variable_Label].values
代表用户指定的场变量的取值。需要注意的是,该对象包含的是整个模型中所有节点或单元的每个积分点在当前增量步下的场变量数据。对于采用减缩的单元,并且如果输出的场变量定义在单元的积分点上,如应力或应变等,则该对象包含的是所有单元的积分点在当前增量步下的场变量数据。如果用户需要获取指定单元集中所有单元的场变量数据,则需要首先访问其子对象 My_Frame.fieldOutputs[File_Variable_Label].values.elementLabel
以获取当前对象所对应的单元号。通过判断其单元号是否与指定单元集中的单元号匹配来判断是否需要输出其场变量数据。为此,本文首先遍历所有对象,通过创建字典结构,来建立单元号与场变量对象之间的关系。其中字典Element_Map
的键为单元号,键值为单元号所对应的场变量对象。这样,通过提供单元号即可快速获得该单元所对应的场变量对象。最后,通过访问子对象My_Frame.fieldOutputs[File_Variable_Label].values.data
即可获得指定单元的场变量值。在本文中,这些场变量值被格式化输出至屏幕,在实际应用中,也可以将其以文本形式的输出。
以下是基于Python批量输出Abaqus场变量的完整程序:
#-* - coding:UTF-8 -*-
#导入Abaqus模块
from odbAccess import *
from abaqusConstants import *
#提取参数定义
Odb_Path='C:/Users/Lenovo/Desktop/Field_Output_Extract/' #Odb文件路径
Odb_Name='Plate.odb' #Odb文件名称
Elem_Set_Name='Stress_Elem' #单元集 合名称
Step_Name='Step-1' #待提取分析步名称(与Odb文件中分析步名称一致)
File_Variable_Label='E' #待提取场变量(与Abaqus中定义一致)
Frame_Start=0 #待提取增量步的起始编号
Frame_End=5 #待提取增量步的终止编号
#------------------------------读取待提取的单元集中的单元号-----------------------
#以只读方式打开odb文件
My_Odb=openOdb(path=Odb_Path+Odb_Name,readOnly=True)
#读取用户指定的单元集 合
try:
My_Elem_Set=My_Odb.rootAssembly.elementSets[Elem_Set_Name]
except:
print('\n'*2)
print("Error:The specified element set does not exist!")
#读取单元集 合中的单元号
My_Elem_Labels=[]
for Element in My_Elem_Set.elements:
for Sub_Element in Element:
My_Elem_Labels.append(Sub_Element.label)
#------------------------------------------------------------------------------
#------------------------------读取单元集中单元场输出变量值-----------------------
#读取指定分析步
My_Step=My_Odb.steps[Step_Name]
#读取指定分析步的增量步(遍历所有增量步)
print('\n'*100)
for Frame_Index in range(Frame_Start,Frame_End+1):
My_Frame=My_Step.frames[Frame_Index]
#获取场输出值所在的全部对象(所有单元)
Field_Value=My_Frame.fieldOutputs[File_Variable_Label].values
#创建快速查询字典 建立单元号与对象索引的关系(键:单元号 值:对象)
Element_Map={}
for Val in Field_Value:
Element_Map[Val.elementLabel]=Val
#读取单元集中单元场并格式化输出变量值
print('\n'*2)
for Current_Label in My_Elem_Labels:
#格式化输出增量步号(9位右对齐整型)
Formatted_Frame='%9d' % int(Frame_Index)
#格式化输出单元号(9位右对齐整型)
Formatted_Label='%9d' % int(Current_Label)
#格式化输出场输出数据(12位对齐科学计数法)
Formatted_Values=[]
for Val in Element_Map[Current_Label].data:
Formatted_Val='%12.5e' % float(Val)
Formatted_Values.append(Formatted_Val)
#拼接单元号及输出数据
Output_Line=Formatted_Frame+' '+Formatted_Label +' ' + ' '.join(Formatted_Values)
#输出数据行至屏幕
print(Output_Line)
#------------------------------------------------------------------------------