Преобразование макроса Abaqus в скрипт Python

Я использую Abaqus (6.13) для запуска теплового моделирования FEM. Мне нужно получить общий внешний тепловой поток, применяемый к этой модели. Мои поиски показали, что единственный способ получить это — суммировать выходные данные истории RFLE по всей модели, и это работает нормально. Проблема в том, что у меня модель из ~300 000 элементов и простое открытие окна Report/XY занимает пару часов.

Чтобы упростить мой экспорт, я сделал макрос экспорта с помощью менеджера макросов Abaqus. Запись начинается перед импортом odb в abaqus и заканчивается после экспорта отчета, содержащего данные X/Y. Этот сгенерированный макрос большой (~900 000 строк), поэтому я привожу его урезанную версию:

# -*- coding: mbcs -*-
# Do not delete the following import lines
from abaqus import *
from abaqusConstants import *
import __main__

def OdbMacro1():
    import section
    import regionToolset
    import displayGroupMdbToolset as dgm
    import part
    import material
    import assembly
    import step
    import interaction
    import load
    import mesh
    import optimization
    import job
    import sketch
    import visualization
    import xyPlot
    import displayGroupOdbToolset as dgo
    import connectorBehavior
    import os
    os.chdir(r"C:\FolderPath")
    session.mdbData.summary()
    o1 = session.openOdb(name='C:\FolderPath\odb.odb')
    session.viewports['Viewport: 1'].setValues(displayedObject=o1)
    odb = session.odbs['C:\FolderPath\odb.odb']
    xy0 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Nodal temperature: NT11 PI: PAD-1 Node 10 in NSET PADSURF_BACK', 
        steps=('Step-2', ), suppressQuery=True)
    xy1 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Nodal temperature: NT11 PI: PAD-1 Node 10053 in NSET PADSURF_BACK', 
        steps=('Step-2', ), suppressQuery=True)
    xy2 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Nodal temperature: NT11 PI: PAD-1 Node 10054 in NSET PADSURF_BACK', 
        steps=('Step-2', ), suppressQuery=True)
    xy3 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Nodal temperature: NT11 PI: PAD-1 Node 10055 in NSET PADSURF_BACK', 
        steps=('Step-2', ), suppressQuery=True)
    xy4 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Nodal temperature: NT11 PI: PAD-1 Node 10056 in NSET PADSURF_BACK', 
        steps=('Step-2', ), suppressQuery=True)
    xy5 = avg((xy0, xy1, xy2, xy3, xy4, ), )
    session.XYData(name='x0.nt11', objectToCopy=xy5, 
        sourceDescription='avg((Nodal temperature: NT11 PI: PAD-1 Node 10 in NSET PADSURF_BACK, Nodal temperature: NT11 PI: PAD-1 Node 10053 in NSET PADSURF_BACK, Nodal temperature: NT11 PI: PAD-1 Node 10054 in NSET PADSURF_BACK, Nodal temperature: NT11 PI: PAD-1 Node 10055 in NSET PADSURF_BACK, Nodal temperature: NT11 PI: PAD-1 Node 10056 in NSET PADSURF_BACK, ),)')
    odb = session.odbs['C:\FolderPath\odb.odb']
    xy0 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='RFLE11: RFLE11 PI: PAD-1 Node 1', steps=('Step-2', 
        ), suppressQuery=True)
    xy1 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='RFLE11: RFLE11 PI: PAD-1 Node 2', steps=('Step-2', 
        ), suppressQuery=True)
    xy2 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='RFLE11: RFLE11 PI: PAD-1 Node 3', steps=('Step-2', 
        ), suppressQuery=True)
[...]
    xy280068 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='RFLE11: RFLE11 PI: SLIDER-1 Node 210034', steps=(
        'Step-2', ), suppressQuery=True)
    xy280069 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='RFLE11: RFLE11 PI: SLIDER-1 Node 210035', steps=(
        'Step-2', ), suppressQuery=True)
    xy280070 = sum((xy0, xy1, xy2, xy3, xy4, xy5, xy6, xy7, xy8, xy9, xy10, xy11, 
        xy12, xy13, xy14, xy15, xy16, xy17, xy18, xy19, xy20, xy21, xy22, xy23, 
        xy24, xy25, xy26, xy27, xy28, xy29, xy30, xy31, xy32, xy33, xy34, xy35, 
[...]
        xy280057, xy280058, xy280059, xy280060, xy280061, xy280062, xy280063, 
        xy280064, xy280065, xy280066, xy280067, xy280068, xy280069, ), )
    session.XYData(name='model.RFLE', objectToCopy=xy280070, 
        sourceDescription='sum((RFLE11: RFLE11 PI: PAD-1 Node 1, RFLE11: RFLE11 PI: PAD-1 Node 2, RFLE11: RFLE11 PI: PAD-1 Node 3,
[...]
 RFLE11: RFLE11 PI: SLIDER-1 Node 210033, RFLE11: RFLE11 PI: SLIDER-1 Node 210034, RFLE11: RFLE11 PI: SLIDER-1 Node 210035, ),)')
    odb = session.odbs['C:\FolderPath\odb.odb']
    xy0 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 5', 
        steps=('Step-2', ), suppressQuery=True)
    xy1 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 6', 
        steps=('Step-2', ), suppressQuery=True)
    xy2 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12
[................................................................]
=True)
    xy6000 = xyPlot.XYDataFromHistory(odb=odb, 
        outputVariableName='Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18048', 
        steps=('Step-2', ), suppressQuery=True)
    xy6001 = sum((xy0, xy1, xy2, xy3, xy4, xy5, xy6, xy7, xy8, xy9, xy10, xy11, 
        xy12, xy13, xy14, xy15, xy16, xy17, xy18, xy19, xy20, xy21, xy22, xy23, 

[................................................................]
        xy5991, xy5992, xy5993, xy5994, xy5995, xy5996, xy5997, xy5998, xy5999, 
        xy6000, ), )
    session.XYData(name='surf.hfla', objectToCopy=xy6001, 
        sourceDescription='sum((Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 5, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 6, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12050, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12051, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12052, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12053, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12054, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12055, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12056, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12057, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12058, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12059, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12060, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12061, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 12062, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/
[................................................................]
37, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18038, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18039, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18040, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18041, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18042, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18043, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18044, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18045, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18046, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18047, Heat flux: HFLA     ASSEMBLY_SLIDERSURF/ASSEMBLY_PADSURF PI: SLIDER-1 Node 18048, ),)')
    x0 = session.xyDataObjects['surf.hfla']
    x1 = session.xyDataObjects['model.RFLE']
    x2 = session.xyDataObjects['x0.nt11']
    session.xyReportOptions.setValues(interpolation=ON)
    session.writeXYReport(fileName='C:\FolderPath\report.rpt', 
        appendMode=OFF, xyData=(x0, x1, x2))

OdbMacro1()

Я добавил вызов OdbMacro1 в конце, следуя результатам поиска, которые я получил здесь и там.

Я хочу запустить этот макрос (или, по крайней мере, полезную часть) вне графического интерфейса из файла python. Когда я это делаю (с "C:\Path\to\python\file\folder>abaqus python macro.py"), я получаю сообщение об ошибке:

Traceback (most recent call last):
  File "macro.py", line 3, in <module>
    from abaqus import *
  File "SMAPyaModules\SMAPyaAbqPy.m\src\abaqus.py", line 15, in <module>
ImportError: abaqus module may only be imported in the Abaqus kernel process

. Я не понимаю, в чем проблема. Я попытался добавить «import odbAccess» в начало файла, но получаю ту же ошибку. Я думаю, что я должен добавить некоторый код в начале, но я не могу обойти это. Не могли бы вы помочь мне?

Кстати, это второстепенно, но я чувствую, что мог бы упростить функцию:

  • Среди кучи импорта в начале функции я не уверен, что все нужны, могу ли я удалить некоторые?
  • Все узлы, выходные данные истории которых суммируются (или усредняются) в одной и той же операции, образуют набор. Разве нет способа использовать это, чтобы избежать использования каждого отдельного вывода истории в макросе?

Спасибо за любой ответ. :)


person Aoi_Tan    schedule 23.09.2016    source источник
comment
см. здесь stackoverflow.com/a/28374118/1004168   -  person agentp    schedule 24.09.2016
comment
на ваш другой вопрос, да, вы можете удалить ненужный импорт. Если вам нужно, чтобы он запускался из командной строки с помощью nogui, обязательно протестируйте его таким образом, поскольку вы удаляете импорт, который, по вашему мнению, вам не нужен.   -  person agentp    schedule 24.09.2016
comment
Спасибо, agentp, за оба ваших ответа. Ссылка, которую вы разместили, действительно ответила на мой главный вопрос. Я уже пробовал этот метод из другого источника, но скопированный код не работал (отсутствовал = после noGUI). Что касается второстепенных, я думаю, я буду методом проб и ошибок импортировать (теперь, когда я могу запустить свой скрипт), но знаете ли вы, есть ли способ работать с наборами вместо отдельных узлов? Это значительно уменьшит размер макроса. Наконец, если вы ответите через функцию ответа вместо комментария, я могу отметить ваш ответ как лучший ответ (думаю, это мой единственный пост)   -  person Aoi_Tan    schedule 24.09.2016


Ответы (1)


вот скрипт, который делает то, что вы хотите: (и вы видите, что нам нужны только три импорта)

from abaqus import *
from abaqusConstants import *
import visualization
odb=session.openOdb(name='/full/path/Job-1.odb')
session.viewports['Viewport: 1'].setValues(displayedObject=odb)
session.xyDataListFromField(odb=odb, outputPosition=NODAL,
          variable=(('NT11', NODAL),  ),
                   nodeSets=('PART-1-1.SETNAME', ))
keyname='From Field Data: NT11  at part instance PART-1-1'
# run this to see what the keys look like:
# [ o.description for o in session.xyDataObjects.values() ]
temp=[o for o in session.xyDataObjects.values() if
         o.description.find(keyname)==0]
#note if you only have requested one data type you could just do:
#temp=session.xyDataObjects.values()
session.writeXYReport(fileName='test.rpt', xyData=temp)
#alternate way to directly write data instead of using writexyreport:
f=open('test.dat','w')
for o in temp: f.write('%i %g\n'%
     (int(o.description.split()[-1]),o.data[-1][-1]))
f.close()

запустить с abaqus cae -noGUI script.py или abaqus cae noGUI=script.py

person agentp    schedule 26.09.2016
comment
Спасибо. Итак, если я правильно понимаю код, этот сценарий экспортирует (в test.rpt) данные NT11 (из вывода поля) в наборе SETNAME части-1-1. Но, похоже, он не выполняет никаких операций с данными набора. Возьмем в качестве примера экспорт RFLE, так как он самый проблемный: макрос сейчас делает следующее: resultRFLE(t)=sum on set[nodal.RFLE(t)]. для значений NT11 это resultNT11(t)=average on set[nodal.NT11(t)]. Не похоже, что эта операция выполняется в вашем коде. Я ошибаюсь? - person Aoi_Tan; 27.09.2016
comment
правильно, мой пост представляет собой довольно простой шаблон. После того, как вы извлекли данные, вы можете легко выполнять любые манипуляции в python. Например, средняя температура при последнем приращении равна sum(temp)[-1][-1]/len(temp). - person agentp; 27.09.2016