加速 Abaqus 中的慢循环-python 代码,用于从 .odb 文件中提取应变数据

Accelerate a slow loop in Abaqus-python code for extracting strain data from .odb file

我有一个名为 plate2.odb 的 .odb 文件,我想从中提取应变数据。为此,我构建了下面的简单代码,循环遍历每个元素的字段输出 E(应变)并将其保存到列表中。

from odbAccess import openOdb
import pickle as pickle

# import database
odbname = 'plate2'
path = './'
myodbpath = path + odbname + '.odb'
odb = openOdb(myodbpath)

# load the strain values into a list
E = []
for i in range(1000):
    E.append(odb.steps['Step-1'].frames[0].fieldOutputs['E'].values[i].data)   

# save the data
with open("mises.pickle", "wb") as input_file:
    pickle.dump(E, input_file)

odb.close()

问题是将应变值加载到列表中的 for 循环需要很长时间(1000 个元素需要 35 秒)。按照这个速度 (0.035 queries/second),我需要 2 个小时才能为包含 200,000 个元素的模型提取数据。为什么要花这么长时间?我怎样才能加速这个?

如果我在任何 Python 循环之外执行单个应变查询,则需要 0.04 秒,所以我知道这不是 Python 循环的问题。

我发现每次我想要一个菌株时都必须重新打开 odb 字典中的子目录。因此,为了解决这个问题,我将 odb 对象保存为一个较小的对象。下面是我更新的代码,只需几分之一秒即可解决。

from odbAccess import openOdb
import pickle as pickle

# import database
odbname = 'plate2'
path = './'
myodbpath = path + odbname + '.odb'
odb = openOdb(myodbpath)

# load the strain values into a list
E = []
EE = odb.steps['Step-1'].frames[0].fieldOutputs['E']
for i in range(1000):
    E.append(EE.values[i].data)  

# save the data
with open("mises.pickle", "wb") as input_file:
    pickle.dump(E, input_file)

odb.close()

我会在这里使用 bulkDataBlocks。这比使用值方法快得多。另外使用 Pickle 通常很慢而且没有必要。查看 C++ 手册 http://abaqus.software.polimi.it/v6.14/books/ker/default.htm 中的 FieldBulkData 对象。 Python 方法是相同的,但至少在 Abaqus 6.14 中它没有记录在 Python-Scripting-Reference(自 6.13 起可用)。

例如:

from odbAccess import openOdb
import numpy as np

# import database
odbname = 'plate2'
path = './'
myodbpath = path + odbname + '.odb'
odb = openOdb(myodbpath)

# load the strain values into a numpy array
EE = odb.steps['Step-1'].frames[0].fieldOutputs['E']

# get a numpy array with your data 
# Not using np.copy here may work also, but sometimes I encountered some weird bugs
Strains=np.copy(EE.bulkDataBlocks[0].data)

# save the data
np.save('OutputPath',Strains)

odb.close()

请记住,如果您有多种元素类型,可能会有不止一个 b​​ulkDataBlock。

晚会有点晚,但我发现在这种情况下使用 operator.attrgetterfor 循环或列表理解快得多

所以不是@AustinDowney

E = []
EE = odb.steps['Step-1'].frames[0].fieldOutputs['E']
for i in range(1000):
    E.append(EE.values[i].data) 

这样做:

from operator import attrgetter
EE = odb.steps['Step-1'].frames[0].fieldOutputs['E']
E = map(attrgetter('data'), EE.values)

这与列表理解的速度大致相同,但如果您要一次提取多个属性(例如 coordinateselementId),则速度会好得多