2017-10-04 58 views
1

我有一個.odb文件,名爲plate2.odb,我想從中提取應變數據。爲此,我構建了下面的簡單代碼,通過每個元素的字段輸出E(應變)循環並將其保存到列表中。加速Abaqus-python代碼中的緩慢循環以從.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 = [] 
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個小時才能提取20萬個元素的模型數據。爲什麼這需要這麼長時間?我怎樣才能加速這個?

如果我在任何Python lool之外進行單個應變查詢,它需要0.04秒,所以我知道這不是Python循環的問題。

回答

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() 
+2

請注意,您可以使用列表理解'E = [v.v.data for v in EE.values]'(也許性能也有所提高) – agentp

+1

不錯。順便說一句,這種技術(在Abaqus腳本用戶手冊的「創建保存臨時變量的對象」一節中也提到過)可用於任何Python腳本中,您希望避免重複重建一系列對象。 –

2

我會在這裏使用bulkDataBlocks。這比使用值方法快得多。也使用酸菜通常是緩慢的,沒有必要。查看FieldBulkData對象的C++手冊http://abaqus.software.polimi.it/v6.14/books/ker/default.htm。 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() 

請記住,如果你有多個單元類型可能有不止一個bulkDataBlock。

+0

我也遇到過'bulkDataBlacks'的奇怪表現,我會看看'np.copy'是否改善了一些事情。 –

+0

使用bulkDataBlocks方法時,我遇到沒有性能問題。它應該比價值法快得多。當我重塑或切片bulkDataBlocks方法返回的numpy數組時,我遇到了問題。但與copiing陣列一切都應該沒問題。 – max9111

+0

我的意思是操縱'bulkDataBlocks'的隨機結果。我沒有想過只是在內存中的其他地方複製塊。 –

1

小遲到了,但我覺得用operator.attrgetter是在這種情況下

for循環或列表理解快得多所以不是@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) 

這與列表理解的速度大致相同,但如果您有多個屬性需要extrac (例如coordinateselementId