找回密码
 注册
Simdroid-非首页
查看: 12379|回复: 141

[二次开发] python后处理详解:手把手教你用python读数据

[复制链接]
发表于 2011-6-10 13:25:19 | 显示全部楼层 |阅读模式 来自 欧洲
本帖最后由 JingheSu 于 2011-8-1 13:39 编辑

    本来这个打算发在一个针对python初学者的帖子http://forum.simwe.com/thread-988814-1-1.html里面,作为后处理的部分的,但是鉴于它比较重要所以单独列出来,希望用abaqus的都能看到,都可以根据这个里面的描述了解odb文件的数据结构,都能根据自己的要求读出自己需要的数据。如果能跟着我的这个流程走一遍,我相信这两个目的都不是问题。关键是自己要在自己的电脑上照这个流程运行一遍,看看结果,然后再根据自己的要求试着对自己的一个odb文件读一下数据,下一步就可以进一步扩展,把这些数据写入文本文件或者是excel了。


1

Odb结构如图上所示(来自于doc),可以很明显地分成两部分:Model DataResult Data。所以要获取节点信息,材料信息,part信息以及截面信息得用到odb.Assembly, odb.material, odb.parts, odb.sections;而要提取应力,应变等结果就得用到odb.steps。我们先一步步看看如何查看odb中的信息,最后汇总一下就知道如何写一个有特定功能的脚本了。
用的是例子中的odb,在abaqus command命令行下输入:abaqus fetch job=viewer_tutorial,在你的abaqus工作目录下就会有viewer_tutorial.odb文件。下面都是利用这个odb来进行解释说明的。


2
abaqus\CAE的命令行如上

首先我们需要用到读取odb文件的python包,得用到import
  1. from odbAccess import *
复制代码

打开你要读的文件,这里就是viewer_tutorial.odb
  1. odb=openOdb(r'c:\sujinghe\viewer_tutorial.odb')
复制代码


1_______________________________________________________________________________________


查看这个odb文件的具体信息:
  1. print odb
复制代码

输出如下:
({'analysisTitle': ' DYNAMIC LOADING OF AN ELASTOMERIC, VISCOELASTIC', 'closed': False, 'customData': python object wrapper, 'description': 'DDB object', 'diagnosticData': 'OdbDiagnosticData object', 'isReadOnly': False, 'jobData': 'JobData object', 'materials': 'Repository object', 'name': 'c:/sujinghe/viewer_tutorial.odb', 'parts': 'Repository object', 'path': 'c:/sujinghe/viewer_tutorial.odb', 'profiles': 'Repository object', 'readInternalSets': False, 'rootAssembly': 'OdbAssembly object', 'sectionCategories': 'Repository object', 'sections': 'Repository object', 'sectorDefinition': None, 'steps': 'Repository object', 'userData': 'UserData object'})
可以显示各种数据的储存格式,其中可以看到OdbAssembly object存放当前odbAssembly 相关信息, 而其他的Repository object表示当前对象存储在类似字典类型的数据结构中。整体用()括起来表示这应该是一个对象,而后面{}里面的都是这个对象的成员(members),他们可以用odb.XXX来获得引用,下面逐一查看。

察看analysisTitle
  1. print odb.analysisTitle
复制代码
即可

2________________________________________________________________________________________________



察看rootAssembly
  1. assembly=odb.rootAssembly
  2. print assembly
复制代码

输出如下:
({'connectorOrientations': 'ConnectorOrientationArray object', 'datumCsyses': 'Repository object', 'elementSets': 'Repository object', 'elements': 'OdbMeshElementArray object', 'instances': 'Repository object', 'name': 'Assembly-1', 'nodeSets': 'Repository object', 'nodes': 'OdbMeshNodeArray object', 'pretensionSections': 'OdbPretensionSectionArray object', 'rigidBodies': 'OdbRigidBodyArray object', 'sectionAssignments': 'SectionAssignmentArray object', 'surfaces': 'Repository object'})
继续:print assembly.name,即可得到assembly的名字Assembly-1
我们详细查看几个数据:nodesinstancesnodeSets

2.1
  1. node=assembly.nodes
  2. print len(node)
复制代码

看到输出为0odbnode信息应该单独存在每个instance中的。

2.2
  1. inst=assembly.instances
  2. print inst
复制代码

输出:{'PART-1-1': 'OdbInstance object'}
  1. inst=inst['PART-1-1']
  2. print inst
复制代码

输出:({'analyticSurface': None, 'beamOrientations': 'BeamOrientationArray object', 'elementSets': 'Repository object', 'elements': 'OdbMeshElementArray object', 'embeddedSpace': AXISYMMETRIC, 'materialOrientations': 'MaterialOrientationArray object', 'name': 'PART-1-1', 'nodeSets': 'Repository object', 'nodes': 'OdbMeshNodeArray object', 'rebarOrientations': 'RebarOrientationArray object', 'rigidBodies': 'OdbRigidBodyArray object', 'sectionAssignments': 'SectionAssignmentArray object', 'surfaces': 'Repository object', 'type': DEFORMABLE_BODY})
可以看到上面列出了这个instance的各种信息

2.2.1 instance上面定义的elementSet

  1. print inst.elementSets
复制代码

输出:{'CENT': 'OdbSet object', 'ETOP': 'OdbSet object', 'FOAM': 'OdbSet object', 'PMASS': 'OdbSet object', 'UPPER': 'OdbSet object'}
只有{},这个表示这个对象是一个字典类型的数据,得用XXX[‘YYY’]来获得引用,比如
  1. print inst.elementSets['CENT']
复制代码

输出:({'elements': 'OdbMeshElementArray object', 'faces': None, 'instances': None, 'isInternal': False, 'name': 'CENT', 'nodes': None})
  1. print inst.elementSets['CENT'].elements
复制代码

输出:({'elements': 'OdbMeshElementArray object', 'faces': None, 'instances': None, 'isInternal': False, 'name': 'CENT', 'nodes': None})
  1. print inst.elementSets['CENT'].elements
复制代码

输出:['OdbMeshElement object', 'OdbMeshElement object', 'OdbMeshElement object', 'OdbMeshElement object', 'OdbMeshElement object', 'OdbMeshElement object', 'OdbMeshElement object', 。。。。
继续深入:
  1. Ele= inst.elementSets['CENT'].elements[0]
  2. print Ele
复制代码

输出:({'connectivity': (3, 43, 41, 1), 'instanceName': 'PART-1-1', 'instanceNames': ('PART-1-1', 'PART-1-1', 'PART-1-1', 'PART-1-1'), 'label': 1, 'sectionCategory': 'SectionCategory object', 'type': 'CAX4'})
可以看到单元集合中每个单元的详细数据,编号,节点,单元类型等,注意这个也是一个对象(用()括起来的),必须用XXX.XXX 来引用,如Ele.connectivity

2.2.2 instance上面定义的nodeset

  1. nodeset=inst.nodeSets
  2. print nodeset
复制代码

输出:{'ALLN': 'OdbSet object', 'BOT': 'OdbSet object', 'CENTER': 'OdbSet object', 'N1': 'OdbSet object', 'N19': 'OdbSet object', 'N481': 'OdbSet object', 'N499': 'OdbSet object', 'PUNCH': 'OdbSet object', 'TOP': 'OdbSet object'}
我们也可以用类似上面读elementSets的方法读取nodeset中的每一个具体set的信息

2.2.3 instancenode信息


  1. node=inst.nodes
  2. node1= node[0]
  3. print node1
复制代码

输出:({'coordinates': array([0.0, 300.0, 0.0], 'd'), 'instanceName': 'PART-1-1', 'label': 1})
这是这个instance的第一个节点的信息,节点编号、初始坐标、所属instance它是用()括起来的所以的用XXX.XXX来获得引用,比如
  1. coord=node1. coordinates
  2. coordx=coord[0]
  3. print coord,coordx
复制代码

通过上面的方法就可以得到model中的node信息,用类似的方法也可以看到Model中的element信息。


2.3 assembly上面定义的nodeset

  1. nodeset=assembly.nodeSets
  2. print nodeset
复制代码

输出:{' ALL NODES': 'OdbSet object'},看来他也没有特别定义什么节点集合。
  1. nodeset=nodeset[' ALL NODES']
  2. print nodeset
复制代码

输出很多:
({'elements': None, 'faces': None, 'instances': (({'analyticSurface': None, 'beamOrientations': 'BeamOrientationArray object', 'elementSets': 'Repository object', 'elements': 'OdbMeshElementArray object', 'embeddedSpace': THREE_D, 'materialOrientations': 'MaterialOrientationArray object', 'name': 'PART-1-1', 'nodeSets': 'Repository object', 'nodes': 'OdbMeshNodeArray object', 'rebarOrientations': 'RebarOrientationArray object', 'rigidBodies': 'OdbRigidBodyArray object', 'sectionAssignments': 'SectionAssignmentArray object', 'surfaces': 'Repository object', 'type': DEFORMABLE_BODY}),), 'isInternal': False, 'name': ' ALL NODES', 'nodes': (['OdbMeshNode object', 'OdbMeshNode object', 'OdbMeshNode object',。。。。。
重点看nodes注意它的形式:([],[])其实是元组套列表的形式
  1. nodeset=nodeset.nodes[0]
  2. print nodeset
复制代码

输出:['OdbMeshNode object', 'OdbMeshNode object', 'OdbMeshNode object', 'OdbMeshNode object', 'OdbMeshNode object', 'OdbMeshNode object', 'OdbMeshNode object',。。。。
深入一层:
  1. node1=nodeset[0]
  2. print node1
复制代码

输出:({'coordinates': array([0.0, 300.0, 0.0], 'd'), 'instanceName': 'PART-1-1', 'label': 1})
这个时候我们就可以看到这个nodeset中的第一个节点信息了。下面的语句可以提取具体信息:
  1. print node1.coordinates
复制代码
得到节点坐标[
0.
300.
0.]

  1. print node1.label
复制代码
得到节点编号1



3 ______________________________________________________________________________________________



查看material信息
  1. mat=odb.materials
  2. print mat
复制代码

输出:{'FOAM': 'Material object'}
可以看见这个模型中唯一的材料类型FOAM{}XXX[‘XXX’]
继续查看:
  1. mat=mat['FOAM']
  2. print mat
复制代码

输出:({'density': 'Density object', 'description': '', 'hyperfoam': 'Hyperfoam object', 'materialIdentifier': '', 'name': 'FOAM', 'viscoelastic': 'Viscoelastic object'})
可以看到这个模型中定义了densityviscoelastichyperfoam等属性
继续深入,()用XXX.XXX
  1. dens=mat. Density
  2. print dens
复制代码

输出:({'dependencies': 0, 'table': ((1e-11,),), 'temperatureDependency': OFF})
继续:
  1. values= dens.table[0][0]
  2. print values
复制代码

得到密度值:1e-11
用同样的方法可以得到其他想要的材料定义值
_________________________________________________________________________________________________________________________
4_______________________________________________________________________________________________________


查看step信息,这其中储藏了odb单元应力应变以及节点位移等等值。首先得说明的是应力应变时基于积分点的,只能在单元上查询;而位移以及反力都是基于节点的,必须在节点上查询。


4.1


  1. step=odb.steps
  2. print step
复制代码

输出:{'Step-1': 'OdbStep object', 'Step-2': 'OdbStep object', 'Step-3': 'OdbStep object'}
可以看到一共有三个step,这里我们示范看一下step-3的计算数据
  1. step3=step['Step-3']
  2. print step3
复制代码

输出:({'acousticMass': 0.0, 'acousticMassCenter': (), 'description': ' Remove load.', 'domain': TIME, 'eliminatedNodalDofs': 'NodalDofsArray object', 'frames': 'OdbFrameArray object', 'historyRegions': 'Repository object', 'inertiaAboutCenter': (), 'inertiaAboutOrigin': (), 'loadCases': 'Repository object', 'mass': 0.0, 'massCenter': (), 'name': 'Step-3', 'nlgeom': True, 'number': 3, 'previousStepName': 'Step-2', 'procedure': '*DYNAMIC', 'retainedEigenModes': (), 'retainedNodalDofs': 'NodalDofsArray object', 'timePeriod': 10.0, 'totalTime': 6.0})
可以看到这一步的具体信息,可以把它打印出来
  1. print step3.timePeriod
复制代码

指的是当前步的time,而totalTime指的是该步以前的所有步所经历的总时间。


4.2

frames中储藏的才是我们的计算结果
  1. frame=step3.frames
  2. print len(frame)
复制代码

输出27
可以看出,这一步总共有26个增量步(另外一个是初始时刻)我们现在看第24步时候的计算结果:
  1. frame24=frame[24]
  2. print frame24
复制代码

输出:({'cyclicModeNumber': None, 'description': 'Increment
240: Step Time =
4.906', 'domain': TIME, 'fieldOutputs': 'Repository object', 'frameId': 240, 'frameValue': 4.90593481063843, 'frequency': None, 'incrementNumber': 240, 'isImaginary': False, 'loadCase': None, 'mode': None})

其中记录了该增量步的具体信息:incrementNumberframeValue(指的是该分析步的时间),可以通过XXX.XXX来获得引用,比如
  1. print frame24. frameValue
复制代码
就输出:4.90593481063843

查看计算结果数据:
  1. output=frame24. fieldOutputs
  2. print output
复制代码

输出:{'A': 'FieldOutput object', 'AR3': 'FieldOutput object', 'COPEN
TARGET/IMPACTOR': 'FieldOutput object', 'CPRESS
TARGET/IMPACTOR': 'FieldOutput object', 'CSHEAR1
TARGET/IMPACTOR': 'FieldOutput object', 'CSLIP1
TARGET/IMPACTOR': 'FieldOutput object', 'LE': 'FieldOutput object', '': 'FieldOutput object', 'RM3': 'FieldOutput object', 'S': 'FieldOutput object', 'U': 'FieldOutput object', 'UR3': 'FieldOutput object', 'V': 'FieldOutput object', 'VR3': 'FieldOutput object'}

可以看到这里面AAR3CPRESSCSHEAR1RFSVU等等数据
我们查看一下US两个最常用的
  1. uu=output['U']
  2. ss=output['S']
  3. print uu
复制代码

输出:({'baseElementTypes': (), 'componentLabels': ('U1', 'U2'), 'description': 'Spatial displacement', 'isComplex': OFF, 'locations': 'FieldLocationArray object', 'name': 'U', 'type': VECTOR, 'validInvariants': (MAGNITUDE,), 'values': 'FieldValueArray object'})
  1. print ss
复制代码

输出:({'baseElementTypes': ('CAX4',), 'componentLabels': ('S11', 'S22', 'S33', 'S12'), 'description': 'Stress components', 'isComplex': OFF, 'locations': 'FieldLocationArray object', 'name': 'S', 'type': TENSOR_2D_PLANAR, 'validInvariants': (MISES, MAX_INPLANE_PRINCIPAL, MIN_INPLANE_PRINCIPAL, OUTOFPLANE_PRINCIPAL, MAX_PRINCIPAL, MID_PRINCIPAL, MIN_PRINCIPAL, TRESCA, PRESS, INV3), 'values': 'FieldValueArray object'})
具体的值都储存在values里面
  1. u=uu.values
  2. print u[0]
复制代码

输出:({'baseElementType': '', 'conjugateData': None, 'conjugateDataDouble': 'unknown', 'data': array([3.8507681799646e-42, -76.8765869140625], 'd'), 'dataDouble': 'unknown', 'elementLabel': None, 'face': None, 'instance': 'OdbInstance object', 'integrationPoint': None, 'inv3': None, 'localCoordSystem': None, 'localCoordSystemDouble': 'unknown', 'magnitude': 76.8765869140625, 'maxInPlanePrincipal': None, 'maxPrincipal': None, 'midPrincipal': None, 'minInPlanePrincipal': None, 'minPrincipal': None, 'mises': None, 'nodeLabel': 1, 'outOfPlanePrincipal': None, 'position': NODAL, 'precision': SINGLE_PRECISION, 'press': None, 'sectionPoint': None, 'tresca': None, 'type': VECTOR})
这是1号节点(注意'position': NODAL表明该数据位于节点上)上的位移值,XXX.XXX可以读取具体数据:
  1. print u[0].data
复制代码
得到[
3.85076818e-42
-7.68765869e+01]

  1. print u[0]. Magnitude
复制代码
得到76.8765869141

  1. s=ss.values
  2. print s[0]
复制代码

输出:({'baseElementType': 'CAX4', 'conjugateData': None, 'conjugateDataDouble': 'unknown', 'data': array([0.00423928024247289, -0.0423013754189014, 0.00300560519099236, 0.000305930589092895], 'd'), 'dataDouble': 'unknown', 'elementLabel': 1, 'face': None, 'instance': 'OdbInstance object', 'integrationPoint': 1, 'inv3': -0.0459018871188164, 'localCoordSystem': ((0.999767363071442, 0.0215687770396471, 0.0), (-0.0215687770396471, 0.999767363071442, 0.0), (0.0, 0.0, 1.0)), 'localCoordSystemDouble': 'unknown', 'magnitude': None, 'maxInPlanePrincipal': 0.00424129096791148, 'maxPrincipal': 0.00424129096791148, 'midPrincipal': 0.00300560519099236, 'minInPlanePrincipal': -0.0423033870756626, 'minPrincipal': -0.0423033870756626, 'mises': 0.0459393002092838, 'nodeLabel': None, 'outOfPlanePrincipal': 0.00300560519099236, 'position': INTEGRATION_POINT, 'precision': SINGLE_PRECISION, 'press': 0.0116854961961508, 'sectionPoint': None, 'tresca': 0.0465446785092354, 'type': TENSOR_2D_PLANAR})这是1号单元处应力信息,注意看'position': INTEGRATION_POINT表明这是位于积分点,也就是基于单元的量,读取的时候要用单元的编号,通位移相同,我们可以用XXX.XXX可以读取具体数据:
  1. print s[0].mises
  2. print s[0].data
复制代码


到这里,只要你再了解一点python编程流程,你就可以完成一个自己的后处理程序了。到那时候就可以对你说:祝贺你,pythoner~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

3

查看全部评分

发表于 2011-6-11 12:18:46 | 显示全部楼层 来自 新疆乌鲁木齐
Simdroid开发平台
非常感谢,楼主讲的这么详细,我受益匪浅。
可是我在实践的时候,发现我的单元和节点信息都在rootAssembly中,而不是在instance中,不知为什么,望给以指点。不胜感激。
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-11 12:37:48 | 显示全部楼层 来自 江苏南京
本帖最后由 JingheSu 于 2011-6-11 12:39 编辑

是我这个例子:viewer_tutorial.odb
回复 不支持

使用道具 举报

发表于 2011-6-11 13:33:25 | 显示全部楼层 来自 新疆乌鲁木齐
不是的,是我自己做的一个例子的odb文件
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-11 13:57:03 | 显示全部楼层 来自 江苏南京
node信息应该都是在rootAssembly下面的instance里面。instance也是rootAssembly的一个成员。
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-11 14:00:21 | 显示全部楼层 来自 江苏南京
4# wanglunatic
其实按照上面的流程你就可以知道你要的东西(节点或者单元信息)到底在哪里存放(rootAssembly 层次还是在他下面的instance里面),可能不同的计算odb结构会有所不同吧。
回复 不支持

使用道具 举报

发表于 2011-6-11 20:30:22 | 显示全部楼层 来自 新疆乌鲁木齐
非常感谢楼主的详细解释。
回复 不支持

使用道具 举报

发表于 2011-6-14 11:15:18 | 显示全部楼层 来自 重庆沙坪坝区
非常感谢楼主的无私,受教了,接着学习
回复 不支持

使用道具 举报

发表于 2011-6-14 11:20:53 | 显示全部楼层 来自 陕西西安
写得这么详细的python教程,尚属首次,楼主威武!
回复 不支持

使用道具 举报

发表于 2011-6-14 21:02:25 | 显示全部楼层 来自 德国
太有用的帖子,太棒了,谢谢楼主!~
回复 不支持

使用道具 举报

发表于 2011-6-15 00:50:10 | 显示全部楼层 来自 河北秦皇岛
楼主你的前两段代码怎么不能用呀,还有就是读取odb文件的python包,这是什么意思,怎么找到odbaccess呀 ,请楼主指教 1# JingheSu
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-15 08:34:07 | 显示全部楼层 来自 上海
错误信息是什么?不知道你是在CAE下面的命令行里面提交的命令么?
from odbAccess import * 这个命令就是声明程序要引用odbAccess系统包里面的模块。
回复 不支持

使用道具 举报

发表于 2011-6-15 13:05:33 | 显示全部楼层 来自 河北秦皇岛
谢谢楼主,我还想向您请教一个问题,我是做金属塑性变形的,由于变形量非常大,网格变形严重,我想在变形后提取一个面,然后再将这个面进行拉伸,但是这个面上要保留所有的信息,再进行以后的分析,请问该怎么做呀
12# JingheSu
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-15 13:19:08 | 显示全部楼层 来自 上海
变形后提取一个面?提取一个截面么?
你是平面问题么?
回复 不支持

使用道具 举报

发表于 2011-6-15 16:32:53 | 显示全部楼层 来自 河北秦皇岛
不是平面问题,是三维问题,只是网格变形严重,想找到一个变形好的面,然后再进行拉伸,拉伸成三维的,可以用python编写吗 14# JingheSu
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-15 16:43:44 | 显示全部楼层 来自 上海
你是仅仅想得到变形比较好的那个平面的具体形状,还是把那个平面上的应力应变数据导入到你的新模型里面?
回复 不支持

使用道具 举报

发表于 2011-6-15 17:12:36 | 显示全部楼层 来自 河北秦皇岛
我想得到好的那个平面然后进行拉伸,得到三维模型,同时把应力应变导入新的模型,然后用到下一步,继续进行分析 16# JingheSu
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-15 17:32:42 | 显示全部楼层 来自 上海
不知道你那个平面规则么?
如果规则,可以读出特定点的数据,根据这些数据建立变形后的模型,然后import或者map solution吧
如果不规则,就没有什么好方法了。还是想想用hypermesh等从网格得到变形后的形状,然后import或者map solution吧
回复 不支持

使用道具 举报

发表于 2011-6-15 17:53:28 | 显示全部楼层 来自 河北秦皇岛
我用import可以得到变形后的形状,然后对网格进行了新的编辑,就是不知道怎么得到这个面上的应力应变值,也不知道怎么将应力应变赋予给这个面上 18# JingheSu
回复 不支持

使用道具 举报

 楼主| 发表于 2011-6-15 18:18:21 | 显示全部楼层 来自 江苏镇江
import 不是也可以把旧的结果导入到新的模型中吗?
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-27 01:43 , Processed in 0.054358 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表