3. Abaqus脚本接口与对象模型
在Abaqus Python二次开发中,几乎所有脚本都围绕三个顶层对象展开:session、mdb和odb。它们分别对应“当前会话环境”“模型数据库”和“输出数据库”三类不同性质的数据容器。理解这三者的职责边界与访问路径,是写出可维护脚本的第一步。很多初学者脚本报错,并非语法问题,而是访问了错误的对象层级,或在错误的时机访问了尚未生成的对象。
三大顶层对象的职责划分
session代表当前Abaqus/CAE会话本身,它管理的是“界面与交互状态”,例如视口(viewport)、视图(view)、显示组、颜色映射、会话级选项以及一些与GUI相关的操作。通过session可以控制视图缩放、截图、打开/关闭视口、设置显示选项等。它不保存有限元模型本身,关闭CAE后session状态通常不保留。
mdb是Model Database(模型数据库)的缩写,它保存的是“建模阶段”的全部数据:模型(Model)、部件(Part)、材料(Material)、截面(Section)、装配(Assembly)、分析步(Step)、载荷与边界条件(Load/BoundaryCondition)、网格(Mesh)、作业(Job)等。mdb是脚本建模的核心入口,所有“创建模型、定义属性、提交计算”的操作几乎都从mdb出发。
odb是Output Database(输出数据库)的缩写,它保存的是“求解结果”数据:节点位移、单元应力、应变、反力、历史输出等。odb通常在作业完成后由Abaqus生成,脚本通过openOdb()打开后读取结果。它不参与建模,只负责结果的后处理与数据提取。
模型数据库mdb的层级结构与访问路径
mdb内部是严格的树状层级结构。最典型的一条建模路径是:mdb.models['Model-1'].parts['Part-1']。其中mdb.models是一个容器(repository),通过模型名称字符串索引到具体模型对象;模型对象下再通过parts、materials、sections、steps、assembly等容器访问子对象。容器支持keys()、values()、items()等类似字典的方法,便于遍历和检查。
需要特别注意的是,Abaqus对象模型中的容器(repository)与Python字典相似但不完全相同:它支持按名称索引,也支持keys(),但不能直接用for k in repo迭代,通常要写成for name in repo.keys():。此外,对象一旦创建,其名称就是访问键,重命名后旧键失效。
下面是一段典型的建模访问示例,展示了从mdb逐级向下访问并创建对象的路径:
from abaqus import *
from abaqusConstants import *
# 访问默认模型
myModel = mdb.models['Model-1']
# 在模型中创建部件
myPart = myModel.Part(name='Plate', dimensionality=TWO_D_PLANAR,
type=DEFORMABLE_BODY)
# 访问装配并实例化
myAssembly = myModel.rootAssembly
myAssembly.Instance(name='Plate-1', part=myPart, dependent=ON)
# 创建材料并赋给截面
myModel.Material(name='Steel')
myModel.materials['Steel'].Elastic(table=((210000.0, 0.3),))
# 创建分析步
myModel.StaticStep(name='Step-1', previous='Initial')
这段代码体现了mdb访问的两个关键点:一是先有父对象才能创建子对象,例如必须先有模型才能创建部件;二是创建方法通常挂在父对象上,如myModel.Part(...)、myModel.Material(...),而访问已有对象则通过容器索引,如myModel.materials['Steel']。
session与odb的典型访问方式
session的访问通常用于视图控制与结果展示。例如session.viewports['Viewport: 1'].setValues(...)可以设置视口参数,session.viewports['Viewport: 1'].odbDisplay.display.setValues(...)用于控制odb显示。session对象不需要“创建”,CAE启动后即存在。
odb的访问则分为两步:先打开,再读取。典型写法是:
from odbAccess import openOdb
myOdb = openOdb('Job-1.odb')
step = myOdb.steps['Step-1']
frame = step.frames[-1]
disp = frame.fieldOutputs['U']
nodeDisp = disp.values[0].data
myOdb.close()
这里openOdb()返回的odb对象,其层级为odb.steps[...].frames[...].fieldOutputs[...]。读取完成后应调用close()释放文件句柄,否则在批量处理多个odb时容易出错。
对象访问中的常见陷阱与判断依据
第一,访问时机错误。例如在作业尚未完成时访问odb,会得到空结果或报错。判断依据是:mdb.jobs['Job-1'].status为COMPLETED后再打开odb。第二,名称拼写与大小写。Abaqus对象名称区分大小写,'Model-1'与'model-1'不同。第三,容器迭代方式。如前所述,应使用keys()而非直接迭代。第四,对象引用失效。删除模型或部件后,之前保存的引用可能变为无效,再次访问会抛出异常。
一个实用的排查习惯是:在脚本中插入print(mdb.models.keys())或print(myModel.parts.keys()),先确认当前层级下有哪些对象,再决定访问路径。这比盲目猜测名称要高效得多。
mdb.models['Model-1'].rootAssembly与mdb.models['Model-1'].assembly。前者是根装配对象,后者是装配容器,实际访问实例时应使用rootAssembly.instances['Plate-1']。三者的协同关系
一个完整的脚本流程通常体现为:用mdb建模 → 提交作业 → 作业完成后用odb读取结果 → 用session控制视图显示或截图。三者各司其职,脚本中应明确当前操作属于哪个顶层对象,避免跨层误用。例如,不能用session去创建材料,也不能用mdb去读取场输出。掌握这条边界,脚本的结构就会清晰很多。
建议在编写较复杂脚本时,先在注释中写出访问路径,例如“mdb → models → Model-1 → parts → Part-1”,再逐级实现。这样既能减少错误,也便于后续维护和他人阅读。