2017-10-04 3 views
1

Ich habe eine ODB-Datei namens plate2.odb, die ich die Stammdaten aus extrahieren möchte. Dazu habe ich den folgenden einfachen Code erstellt, der die Feldausgabe E (Dehnung) für jedes Element durchläuft und in einer Liste speichert.Beschleunigen Sie eine langsame Schleife in Abaqus-Python-Code zum Extrahieren von Stammdaten aus ODB-Datei

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

Die Ausgabe ist, die for-Schleife, die die Dehnungswerte in eine Liste lädt wird eine lange Zeit (35 Sekunden 1000 Elemente) nehmen. Bei dieser Rate (0,035 Abfragen/Sekunde) würde ich 2 Stunden brauchen, um die Daten für mein Modell mit 200.000 Elementen zu extrahieren. Warum dauert das so lange? Wie kann ich das beschleunigen?

Wenn ich eine Single-Strain-Abfrage außerhalb von Python lool mache dauert es 0,04 Sekunden, also weiß ich, dass dies kein Problem mit der Python-Schleife ist.

Antwort

2

Ich fand heraus, dass ich die Unterverzeichnisse im ODB-Wörterbuch jedes Mal wieder öffnen musste, wenn ich eine Belastung wollte. Um das Problem zu beheben, habe ich daher das ODB-Objekt als ein kleineres Objekt gespeichert. Mein aktualisierter Code, der einen Bruchteil einer Sekunde zum Lösen benötigt, ist unten.

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

Hinweis Sie können dies noch kompakter schreiben mit Listenverständnis 'E = [v.data für v in EE.values]' (vielleicht auch ein wenig Leistungssteigerung) – agentp

+1

Nizza. Übrigens kann diese Technik (die auch im Abaqus Scripting Benutzerhandbuch unter "Erstellen von Objekten zum Speichern temporärer Variablen" erwähnt wird) in jedem Python-Skript verwendet werden, in dem Sie wiederholte Rekonstruktionen einer Folge von Objekten vermeiden möchten. –

2

Ich würde hier BulkDataBlocks verwenden. Dies ist viel schneller als die Verwendung der Wertmethode. Auch die Verwendung von Pickle ist in der Regel langsam und nicht notwendig. Sehen Sie im C++ - Handbuch http://abaqus.software.polimi.it/v6.14/books/ker/default.htm am FieldBulkData-Objekt nach. Die Python-Methode ist die gleiche, aber zumindest in Abaqus 6.14 ist sie nicht in der Python-Scripting-Referenz dokumentiert (sie ist seit 6.13 verfügbar).

Zum Beispiel:

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

Denken Sie daran, dass, wenn Sie mehrere Elementtypen es kann mehr als ein bulkDataBlock sein.

+0

Ich habe auch die seltsame Leistung von 'bulkDataBlacks' gefunden, ich werde sehen, ob' np.copy' die Dinge verbessert. –

+0

Ich habe bei der Verwendung der Methode "bulkDataBlocks" keine Leistungsprobleme festgestellt. Es sollte viel schneller als die Wertmethode sein. Ich habe Probleme festgestellt, wenn ich das von der Methode "bulkDataBlocks" zurückgegebene numpy-Array neu formt oder zerschneide. Aber mit dem Array sollte alles in Ordnung sein. – max9111

+0

Ich meinte mehr die zufälligen Ergebnisse von der Manipulation der 'bulkDataBlocks'. Ich hatte nicht daran gedacht, die Blöcke einfach irgendwo im Speicher zu kopieren. –

1

wenig spät zur Party, aber ich finde mit operator.attrgetter viel schneller zu sein als eine for Schleife oder Liste Verständnis in diesem Fall

Also statt @AustinDowney

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

dies tun:

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

Dies ist etwa die gleiche Geschwindigkeit wie Listenverständnis, aber ist viel besser, wenn Sie mehrere Attribute haben, die Sie extrahieren möchten t sofort (sagen coordinates oder elementId)

Verwandte Themen