Скрипт Abaqus Python Чтение данных «TENSOR_3D_FULL» из файла *.odb

Что я хочу: значения деформации LE11, LE22, LE12 в узловых точках
Мой сценарий:

#!/usr/local/bin/python
# coding: latin-1

# making the ODB commands available to the script
from odbAccess import*
import sys
import csv

odbPath = "my *.odb path"   
odb = openOdb(path=odbPath)    
assembly = odb.rootAssembly

# count the number of frames    
NumofFrames = 0
for v in odb.steps["Step-1"].frames:
    NumofFrames = NumofFrames + 1

# create a variable that refers to the reference (undeformed) frame    
refFrame = odb.steps["Step-1"].frames[0]  

# create a variable that refers to the node set ‘Region Of Interest (ROI)’    
ROINodeSet = odb.rootAssembly.nodeSets["ROI"]

# create a variable that refers to the reference coordinate ‘REFCOORD’    
refCoordinates = refFrame.fieldOutputs["COORD"]

# create a variable that refers to the coordinates of the node 
# set in the test frame of the step        
ROIrefCoords = refCoordinates.getSubset(region=ROINodeSet,position= NODAL)

# count the number of nodes    
NumofNodes =0
for v in ROIrefCoords.values:
    NumofNodes = NumofNodes +1


# looping over all the frames in the step
for i1 in range(NumofFrames):

# create a variable that refers to the current frame
currFrame = odb.steps["Step-1"].frames[i1+1]

# looping over all the frames in the step    
for i1 in range(NumofFrames):

    # create a variable that refers to the strain 'LE'    
    Str = currFrame.fieldOutputs["LE"]                
    ROIStr = Str.getSubset(region=ROINodeSet, position= NODAL)

    # initialize list
    list = [[]]

    # loop over all the nodes in each frame
    for i2 in range(NumofNodes):

        strain = ROIStr.values [i2]

        list.insert(i2,[str(strain.dataDouble[0])+";"+str(strain.dataDouble[1])+\
        ";"+str(strain.dataDouble[3]))

    # write the list in a new *.csv file (code not included for brevity)


odb.close()

Я получаю сообщение об ошибке:
напряжения = ROIStr.values ​​[i2]
IndexError: Индекс последовательности вне допустимого диапазона

Дополнительная информация:
Подробная информация о ROIStr:

ROIStr.name
'LE'
ROIStr.type
TENSOR_3D_FULL
OIStr.description
'Логарифмические компоненты деформации'
ROIStr.componentLabels
('LE11', 'LE22' , 'LE33', 'LE12', 'LE13', 'LE23')
ROIStr.getattribute
'getattribute of openOdb(r'путь к .odb').steps['Шаг-1' ].frames[1].fieldOutputs['LE'].getSubset(position=INTEGRATION_POINT, region=openOdb(r'путь к.odb').rootAssembly.nodeSets['ROI'])'

Когда я использую один и тот же код для объектов VECTOR, например 'U' для узлового смещения или 'COORD' для узловых координат, все работает без проблем.
Ошибка возникает в первом цикле. Таким образом, это не тот случай, когда он выполняет несколько циклов, прежде чем произойдет ошибка.

Вопрос. Кто-нибудь знает, что вызывает ошибку в приведенном выше коде?


person Mechanician    schedule 07.08.2017    source источник
comment
Какова цель (без отступа) первого цикла for? Здесь у вас также будет IndexError, так как вы перебираете количество шагов с индексом i1+1. Также обратите внимание, что NumofFrames = 0 for v in odb.steps["Step-1"].frames: NumofFrames = NumofFrames + 1 можно сократить до NumofFrames = len(odb.steps["Step-1"].frames).   -  person David    schedule 08.08.2017
comment
Второй цикл ‹# по всем кадрам на шаге для i1 в диапазоне (NumofFrames)› является избыточным. Он попал туда во время копирования-вставки кода.   -  person Mechanician    schedule 08.08.2017
comment
В качестве шага к отладке попробуйте распечатать результаты strain = ROIStr.values[0], где индекс 0 жестко запрограммирован.   -  person Matt P    schedule 08.08.2017
comment
@Mechanician Вы должны получить свои результаты, используя позицию ELEMENT_NODAL   -  person David    schedule 09.08.2017
comment
@ Дэвид Спасибо; Использование ELEMENT_NODAL сработало.   -  person Mechanician    schedule 10.08.2017


Ответы (1)


Вот причина, по которой вы получаете IndexError. Деформации (очевидно) рассчитываются в точках интегрирования; согласно Справочному руководству по сценариям ABQ:

SymbolicConstant, определяющий позицию вывода в элементе. Возможные значения:

NODAL, указав значения, рассчитанные в узлах.

INTEGRATION_POINT, указав значения, рассчитанные в точках интегрирования.

ELEMENT_NODAL, указав значения, полученные путем экстраполяции результатов, рассчитанных в точках интегрирования.

CENTROID, указав значение в центре тяжести, полученное путем экстраполяции результатов, рассчитанных в точках интегрирования.

Таким образом, чтобы использовать ваш код, вы должны получить результаты, используя position= ELEMENT_NODAL

ROIrefCoords = refCoordinates.getSubset(region=ROINodeSet,position= ELEMENT_NODAL)

С

ROIStr.values[0].data

Затем вы получите массив, содержащий 6 независимых компонентов вашего тензора.


Альтернативное решение

Для чтения временных рядов результатов для набора узлов вы можете использовать функцию xyPlot.xyDataListFromField(). Я заметил, что эта функция намного быстрее, чем использование odbread. Код также короче, единственный недостаток в том, что для его использования необходимо получить лицензию abaqus (в отличие от odbread, который работает с abaqus python, для которого требуется только установленная версия abaqus и не нужно получать сетевую лицензию).

Для вашего приложения вы должны сделать что-то вроде:

from abaqus import *
from abaqusConstants import *
from abaqusExceptions import *
import visualization
import xyPlot
import displayGroupOdbToolset as dgo


results = session.openOdb(your_file + '.odb')
# without this, you won't be able to extract the results
session.viewports['Viewport: 1'].setValues(displayedObject=results) 
xyList = xyPlot.xyDataListFromField(odb=results, outputPosition=NODAL, variable=((
        'LE', INTEGRATION_POINT, ((COMPONENT, 'LE11'), (COMPONENT, 'LE22'), (
        COMPONENT, 'LE33'), (COMPONENT, 'LE12'), )), ), nodeSets=(
        'ROI', ))

(Конечно, вы должны добавить LE13 и т. д.)

Вы получите список xyData

type(xyList[0])
<type 'xyData'>

Содержит нужные данные для каждого узла и каждого выхода. Поэтому его размер будет

len(xyList)
number_of_nodes*number_of_requested_outputs

Где первые number_of_nodes элементов списка — это LE11 в каждом узле, затем LE22 и так далее.

Затем вы можете преобразовать это в массив NumPy:

LE11_1 = np.array(xyList[0])

будет LE11 в первом узле с размерами:

LE.shape
(NumberTimeFrames, 2)

То есть для каждого временного шага у вас есть время и выходная переменная. Массивы NumPy также очень легко записывать в текстовые файлы (посмотрите numpy.savetxt).

person David    schedule 08.08.2017