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

时间:2017-10-04 20:51:14

标签: python abaqus

我有一个名为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查询/秒),我需要2个小时才能为我的模型提取200,000个元素的数据。这为什么需要这么长时间?我怎样才能加速这个?

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

3 个答案:

答案 0 :(得分:2)

我发现每次我想要一个应变时,我不得不重新打开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()

答案 1 :(得分:2)

我会在这里使用bulkDataBlocks。这比使用value方法快得多。使用泡菜通常也很慢,没有必要。请查看FieldBulkData对象的C ++手册http://abaqus.software.polimi.it/v6.14/books/ker/default.htm。 Python方法是相同的,但至少在Abaqus 6.14中没有记录在Python-Scripting-Reference中(从6.13开始提供)。

例如:

System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = arguments;
process.StartInfo = startInfo;
process.Start();

请注意,如果您有多个元素类型,则可能有多个bulkDataBlock。

答案 2 :(得分:1)

派对迟到了,但我觉得在这种情况下使用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

,那就更好了