基于Python输出Abaqus场变量数据

简介


 

在有限元软件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_PathOdb_Name分别代表了Odb文件所在路径和Odb文件名。Elem_Set_Name代表用户定义的单元集 合名称。Step_Name为待提取场输出数据所在的分析步名称。File_Variable_Label为待提取场输出变量的名称,为了保证场输出变量被正确读取,必须与Abaqus中场变量的名称保持一致,如应力用S表示,应变用E表示。Frame_StartFrame_End为待提取场输出数据所在增量步的起始编号和终止编号,该参数允许提取多个增量步中的场输出数据。

首先,程序将通过openOdb方法以只读方式打开用户指定的Odb文件。然后,程序将基于用户指定的单元集名称,尝试在Odb文件中读取对应的单元集。如果没有找到同名的单元集,则程序将输出错误信息。

如果对应的单元集被找到,则对应于该单元集的elementSets对象将被存放于My_Elem_Set变量中。在elementSets对象中,单元编号存放于子对象elementSets.elements.label中。因此,程序将会遍历所有子对象,并将读取到的单元编号存放于变量My_Elem_Labels中。

待程序读取到用户指定的单元编号后,下一步即可根据单元编号获取该单元在指定分析步和增量步上的场输出数据。为了能够顺利找到单元对应的场输出数据,需要用户对于Abaqus的输出数据库对象的构成有一定了解。下图展示了Abaqus中数据库对象构成的示意图。

从图中可以看到,Abaqus数据库对象包含模型数据(Model Data)和结果数据(Results Data)两部分。其中模型数据包含部件、截面和材料等定义信息,而场输出(fieldOutputs)和时间历程输出(historyOutputs)则包含在结果数据中。需要注意的是,场输出对象的父对象为增量步(frames)对象,而增量步对象的父对象为分析步(steps)对象。这意味着,如果需要访问场输出数据,则需要首先确定待提取场输出数据所在的分析步和增量步。并且,如果需要获取多个增量步下的场输出数据,这需要逐个访问其对应的增量步对象,这是比较繁琐的地方。需要注意的是,在实际操作中笔者还发现,每个场输出对象只对应了在某个积分点或节点上的场输出数据,这取决于你需要提取的场变量类型。例如,对于应力或应变数据,由于是在积分点上获得的,因此每个单元的每个积分点对应一个场输出对象。而对于位移数据,由于是在节点上获得的,因此每个单元节点对应一个场输出对象。这意味着,对于采用全积分的单元,你必须访问不同的场输出对应来获得某个单元在所有积分点上的场输出数据。这里,本文的提取程序只讨论最简单的情况,即提取采用减缩积分单元在积分点上的场输出数据。如果需要提取全积分单元在多个积分点或者节点上的数据,则需要对本文提供的程序进行适当修改。

 实现提取减缩积分单元在积分点上的场输出数据的程序片段如下所示。

#------------------------------读取单元集中单元场输出变量值-----------------------
#读取指定分析步
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)
#------------------------------------------------------------------------------
 


来源:易木木响叮当
2025-04-19 同步
1条评论
仿真秀0723214418
每天进步一点点
16小时前
学习学习
回复
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈