首页/文章/ 详情

利用Python批量提交inp文件

11月前浏览1471

最近,笔者在使用Abaqus的过程中遇到了需要重复计算多种工况的问题,并且需要提取每一个工况下的时间历程数据。如果采用手动提交的方式,则提交过程非常繁琐,并且只能等到前一个模型计算完成之后才能进行后续的计算。因此,笔者很快想到能否在Abaqus中实现inp文件的批量提交。

通过查阅相关资料,笔者发现目前inp文件的批量运算主要有两种实现方法:Bat文件提交方法和Python提交方法。Bat文件提交方法主要是利用了Abaqus Command中的任务提交语句。例如,一个最简单的inp文件提交格式如下所示:

    abaqus job=case1.inp cpus=4 inter

    为了批量提交inp文件,可以将多个inp文件的提交语句汇总到一个批处理文件(.bat)中,通过执行该bat文件即可完成计算。一个包含多个inp文件的提交命令如下所示:

      cmd/c abaqus job=case1.inp cpus=4 intercmd/c abaqus job=case2.inp cpus=4 intercmd/c abaqus job=case3.inp cpus=4 inter

      注意,为了保证inp文件顺序提交,必须使用cmd/c而非call关键字,并且需要使用int关键字(int为interactive的缩写,int关键字用于在运行过程中反馈进程,在隐式计算中输出log文件,还可以保证inp文件顺序提交,防止同时提交时导致计算机资源耗尽)。

      Bat文件提交方法使用较为简单,但在计算过程中无法实现其他交互式操作。另一种方法为采用Python脚本批量提交inp文件进行计算,一个最简单的计算脚本如下所示:

        # -*- coding: UTF-8 -*-from abaqus import *from abaqusConstants import *#inp文件列表Jobs_list = ['case1', 'case2', 'case3']#利用for循环批量提交计算for i in Jobs_list:    mdb.JobFromInputFile(name = i,                         inputFileName = i + '.inp',                         numCpus = 4,                         numDomains = 4)    mdb.jobs[i].submit()    mdb.jobs[i].waitForCompletion()

        上述脚本的计算原理为将inp文件名存放在一个名为Jobs_list的列表中,随后通过mdb对象中的JobFromInputFile方法读取inp文件并创建一个jobs对象,并利用jobs对象中的submit方法提交任务进行计算。注意在提交之后必须使用waitForCompletion方法保证只有当计算完成之后才执行后续语句,否则程序将直接进入下一轮循环,导致inp文件被同时提交计算。

        在Abaqus中,Python脚本可以通过两种方式被执行:一种为在打开Abaqus/CAE的情况下,通过菜单栏中的File→Run Script直接运行脚本;另一种方式为在Abaqus Command中执行如下语句:

          abaqus cae noGUI=xxx.py

          该语句可以在不打开Abaqus/CAE的情况下执行Python脚本。

          尽管上述语句给出了利用python批量提交inp文件的实现原理,但在使用过程中仍存在一定的局限性。例如在计算队列中若某一个计算任务意外终止,则会导致整个计算队列终止,无法完成后续计算。此外,笔者还需要在计算完成后顺序输出每一个模型中的时间历程数据。为了解决上述问题,本文拟通过Python脚本实现下述功能:

          • 基于inp文件名顺序提交计算,并检测计算状态,当计算意外终止时自动开始后续任务的计算;

          • 每次计算完成后实时输出该模型对应的时间历程数据。

          1. 时间历程数据提取方法

          利用Python批量处理Abaqus时间历程数据一文中,笔者详细介绍了通过Abaqus中的Session对象获取时间历程数据的实现原理。在本文中,笔者将介绍提取时间历程数据的另一种方法:通过Odb对象直接获取时间历程数据或场输出结果。为了对Odb对象有一个更为清楚的认识,本文给出了输出数据库(Output database)对象的模型图,如图1.1所示。通过该模型图,可以帮助我们理解模型中父对象与子对象之间的关系。

          图1.1 输出数据库对象模型图

          例如,当我们打开或创建一个输出数据库(.odb文件)时,Abaqus会自动创建一个Odb对象。从图1.1中可以看出,Odb对象中包含有模型数据(Model Data)和结果数据(Results Data)。模型数据包含有用于组成装配的部件(Part)和部件实例(Part instance),如节点坐标和单元类型等;结果数据则包含有模型的分析结果,如应力、应变和位移等数据,本文需要提取的时间历程数据同样包含在结果数据中。从图1.1中可以看出,所有的结果数据都包含在Odb对象的成员——Step对象中,而Step对象又同时拥有Frame对象和historyRegion对象,分别用于存储场输出结果和时间历程输出结果。

          为了对Abaqus中的Odb对象有更为清晰的认识,本文依照利用Python批量处理Abaqus时间历程数据一文中的方法,通过对象名.__members__命令来输出对象中的所有成员。首先,通过如下命令打开数据库文件(.odb),并输出Odb对象的所有成员:

            # -*- coding: UTF-8 -*-from odbAccess import *Work_directory = 'C:/Users/Desktop/'Job_name = 'Model_Case'odb = openOdb(path = Work_directory + Job_name + '.odb')odb.__members__>>['analysisTitle', 'closed', 'customData','description', 'diagnosticData','isReadOnly', 'jobData', 'materials', 'name','parts', 'path', 'profiles', 'readInternalSets','rootAssembly', 'sectionCategories', 'sections','sectorDefinition', 'steps', 'userData']
            除了使用Odb对象中的__members__方法来输出对象所有成员,还可以使用print(对象名)来获得更为全面的信息: 
              print(odb)>>({'analysisTitle': '', 'closed': False, 'customData': None, 'description': 'DDB object', 'diagnosticData': 'OdbDiagnosticData object', 'isReadOnly': False, 'jobData': 'JobData object', 'materials': 'Repository object', 'name': 'C:/Users/xutian/Desktop/batch analysis/input file/Model_Case1.odb','parts': 'Repository object','path': 'C:/Users/xutian/Desktop/batch analysis/input file/Model_Case1.odb','profiles': 'Repository object', 'readInternalSets': False,'rootAssembly': 'OdbAssembly object','sectionCategories': 'Repository object','sections': 'Repository object', 'sectorDefinition': None, 'steps': 'Repository object', 'userData': 'UserData object'})
              从上面的输出结果可以看出,Odb对象中的一些成员属于成员变量,而另一些成员则属于库对象(Repository object),即图1.1中以灰色表示的对象。这些库对象往往由多个具有相似类型的对象构成(例如,Step库对象由定义在模型中的多个分析步构成),若要访问库中某个对象方法,只能使用如下所示的语句:
                库名['结构生成的对象名称']

                在上面的语句中,结构生成的对象名称可以看作是一个键(key,通常是一个字符串),用于匹配相应的键值(通常是Abqus对象对象,Abaqus object object),这一点与Python的字典数据类型非常类似。

                由于模型所有的结果数据均包含在名为steps的库对象中,因此本文继续输出steps对象的相关信息:

                  print(odb.steps)>>{'Step-1': 'OdbStep object', 'Step-2': 'OdbStep object'}
                  注意,由于库对象没有__members__方法,因此只能通过print命令来输出steps对象中的相关信息。从输出信息可以看出,该库对象由名为Step-1Step-2odbstep对象构成,显然该对象名称与模型中定义的分析步名称是一一对应的。根据前面的介绍,我们需要匹配键名才能调用该对象:
                    MyStep1 = odb.steps['Step-1']MyStep2 = odb.steps['Step-1']
                    当然,如果我们并不清楚结构生成的对象名称,也可以使用下面的方法来获取该名称:
                      odb.steps.keys()>>['Step-1', 'Step-2']odb.steps.keys()[-1]>>'Step-2'odb.steps.values()>>[openOdb(r'C:/Users/Desktop/Model_Case.odb').steps['Step-1'], openOdb(r'C:/Users/Desktop/Model_Case.odb').steps['Step-2']]odb.steps.values()[-1]>>openOdb(r'C:/UsersDesktop/Model_Case.odb').steps['Step-2']odb.steps.values()[-1].name>>'Step-2'
                      通过上述的两种方法,均可以最终拿到表示对象名称的字符串,并用于调用库对象中该对象的方法。基于该方法,本文继续输出名为Step-2odbstep对象中的相关信息:
                        Step_name = odb.steps.keys()[-1]      #获取模型中最后一个分析步的名称MyStep = odb.stpes[Step_name]print(MyStep)>>({'acousticMass': -1.0, 'acousticMassCenter': (), 'description': '', 'domain': TIME, 'eliminatedNodalDofs': 'NodalDofsArray object', 'frames': 'OdbFrameArray object', 'historyRegions': 'Repository object', 'inertiaAboutCenter': (), 'inertiaAboutOrigin': (), 'loadCases': 'Repository object', 'mass': -1.0, 'massCenter': (), 'name': 'Step-2', 'nlgeom': False, 'number': 2, 'previousStepName': 'Step-1', 'procedure': '*STATIC', 'retainedEigenModes': (), 'retainedNodalDofs': 'NodalDofsArray object', 'timePeriod': 1.0, 'totalTime': 1.0})
                        结合图1.1可以看出,模型中的场输出数据存放在名为framesodbFrameArray对象中,而本文待提取的时间历程数据则存放在名为historyRegions的库对象中。由于这是一个库对象,因此本文同样通过keys方法首先获取所有的对象名称:
                          MyStep.historyRegions.keys()>>['Assembly ASSEMBLY', 'Node PLATE-1.294']
                          从输出信息可以看出,该库对象由两个对象构成,从第二个对象的命名看出,该对象应该包含有在PLATE-1实例的第294号节点上定义的时间历程数据,这与本文所使用的模型在时间历程数据中的定义是一致的。这里本文继续输出第一个对象上的相关信息:
                            MyRegion=MyStep.historyRegions['Assembly ASSEMBLY']print(MyRegion)>>({'description': 'Output at assembly ASSEMBLY', 'historyOutputs': 'Repository object', 'loadCase': None, 'name': 'Assembly ASSEMBLY', 'point': 'HistoryPoint object', 'position': WHOLE_MODEL})
                            由于historyoutputs为一个库对象,因此继续打印对象名称,并输出相关信息:
                              MyRegion.historyOutputs.keys()>>['ALLAE', 'ALLCCDW', 'ALLCCE', 'ALLCCEN', 'ALLCCET', 'ALLCCSD', 'ALLCCSDN', 'ALLCCSDT', 'ALLCD', 'ALLDMD', 'ALLDTI', 'ALLEE', 'ALLFD', 'ALLIE', 'ALLJD', 'ALLKE', 'ALLKL', 'ALLPD', 'ALLQB', 'ALLSD', 'ALLSE', 'ALLVD', 'ALLWK', 'ETOTAL']
                              从上面的输出信息可以看出,实际上Assembly ASSEMBLY中包含的是所有系统默认输出的时间历程数据,例如ALLAE代表系统的伪应变能变化,这里利用print即可打印输出对应的时间历程数据:
                                MyOutput=MyRegion.historyOutputs['ALLAE']print(MyOutput)>>({'conjugateData': None, 'data': ((0.0, 0.00181813980452716), (1.0, 0.00181813980452716)), 'description': 'Artificial strain energy', 'name': 'ALLAE', 'type': SCALAR})MyOutput.data>>((0.0, 0.00181813980452716), (1.0, 0.00181813980452716))MyOutput.data[0]>>(0.0, 0.00181813980452716)MyOutput.data[0][1]>>0.00181813980452716
                                从上述语句可以看出,通过访问名为ALLAE的对象中的成员变量data,最终我们可以获取得到系统中该分析步任意时刻对应的伪应变能值。利用同样的方法,也可以获取另一个对象中的时间历程数据,这里不再赘述。
                                2. Abaqus inp文件批量提交方法

                                在Abaqus中inp文件的批量提交方法主要参考了前面给出的脚本,同时,为了防止因部分任务出错而导致整个计算队列终止,本文将利用MonitorMgr对象实现对计算任务的检测,在计算成功时实时输出当前任务的时间历程数据,在计算出错时输出错误信息,并直接开始下一次计算。这一部分的实现语句如下所示:

                                  # -*- coding: UTF-8 -*-from abaqus import *from abaqusConstants import *from odbAccess import *from jobMessage import *CPU_num = 4         #并行计算使用的CPU数量Job_num = 5         #待求解inp文件的数量Work_directory = 'C:/UsersDesktop/'  #inp和py文件所在文件路径Base_job_name = 'Model_Case'   #inp文件的公共名称部分#创建列表用于存储Job名称Job_name = ['']*(Job_num+1)for i in range(1,Job_num+1):    Job_name[i] = Base_job_name + str(i)##创建状态文件用于输出求解inp文件和读取odb文件中的状态信息file_status_info = open('Status_info.txt','w')file_status_info.write('%-30s' % 'Input file name')file_status_info.write('%-30s' % 'Analysis status')file_status_info.write('%-30s\n' % 'Postprocess status')#创建结果文件用于存储时间历程数据file_hist_data = open('Hist_output.txt','w')file_hist_data.write('%-30s' % 'Input file name')file_hist_data.write('%-30s\n' % 'results')#利用循环批量提交inp文件进行求解for i in range(1,Job_num+1):    #创建job    mdb.JobFromInputFile(name = Job_name[i],                         inputFileName = Work_directory + Job_name[i] + '.inp',                         numCpus = CPU_num, numDomains = CPU_num)    #监控job    #当求解器收到messageType中指定的消息时将会触发回调函数    #常用的消息类型有:ANY_MESSAGE_TYPE,ABORTED,COMPLETED,ERROR    #这里选择ANY_MESSAGE_TYPE意味着任何消息类型都将触发回调函数    #将当前模型的基本信息(模型名称和工作路径)通过userData传递到回调函数中    Model_info = [Job_name[i], Work_directory]    monitorManager.addMessageCallback(jobName = Job_name[i],                                      messageType = ANY_MESSAGE_TYPE,                                      callback = jobMonitorCallback,                                      userData = Model_info)    #执行job    mdb.jobs[Job_name[i]].submit()    #为了保证inp文件提交运算后可以被顺序执行 需要等到当前计算完成后再进行后续操作    mdb.jobs[Job_name[i]].waitForCompletion()#关闭文本文件file_status_info.close()file_hist_data.close()

                                  这一部分语句主要定义了参与计算的inp文件名称和数量,以及求解文件所在的工作路径。同时还定义了Status_info和Hist_output两个文本文件,分别用于输出每个计算任务的状态信息以及时间历程数据。与前面给出的批量计算脚本有所不同的是,这里用到了monitorManager对象和其对应的函数来实现对计算任务的检测,并在收到检测任务的反馈信息后执行相应的回调函数,完成对反馈信息的响应。例如,在本文的示例中,当收到任务计算完成的反馈信息后,即开始提取该任务的时间历程数据,并将反馈信息和结果输出到文本文件。

                                  用于设定回调函数的addMessageCallback方法至少需要输入3个参数:

                                    monitorManager.addMessageCallback(jobName, messageType, callback, userData)

                                    其中jobName为需要检测的任务名称,当需要检测所有任务时,可以使用Abaqus常量ANY_JOBmessageType是指定的反馈信息类型,常用的类型有:ABORTEDANY_JOBANY_MESSAGE_TYPECOMPLETED等,只有当收到对应的反馈信息类型时,才会执行回调函数,为了响应所有的反馈信息,这里可以将其设为ANY_MESSAGE_TYPEcallback参数需要传入一个回调函数,即响应对应信息的函数;userData可以是任意的Abaqus对象,主要用于将一些用户自定义的额外信息传递到回调函数中,例如,在本例中,我们将当前执行计算的inp文件名和文件路径传递到了回调函数,便于读取计算完成后的odb文件。

                                    在Abaqus中,对应的回调函数也有一定的接口要求:

                                      def functionName(jobName, messageType, data, userData)

                                      这里jobNamemessageTypeuserDataaddMessageCallback方法中的参数是相同的,而data为Abaqus传入的数据对象。在本例中,回调函数的实现语句如下所示:

                                        def jobMonitorCallback(jobName, messageType, data, userData):    if (messageType == ABORTED) or (messageType == ERROR):     #计算终止或报错        # 将错误信息输出到状态文件        file_status_info = open('Status_info.txt', 'a')        file_status_info.write('%-30s' % userData[0])        file_status_info.write('%-30s' % 'ERROR')        file_status_info.write('%-30s\n' % 'ERROR')        #写入无效值到结果文件        file_hist_data = open('Hist_output.txt', 'a')        file_hist_data.write('%-30s' % userData[0])        file_hist_data.write('%-30s\n' % 'NaN')        #移除对job的监控        #回调函数将不再被执行        monitorManager.removeMessageCallback(jobName = userData[0],                                             messageType = ANY_MESSAGE_TYPE,                                             callback = jobMonitorCallback,                                             userData = userData)    elif messageType == JOB_COMPLETED:        # 移除对job的监控        #回调函数将不再被执行        monitorManager.removeMessageCallback(jobName=userData[0],                                             messageType=ANY_MESSAGE_TYPE,                                             callback=jobMonitorCallback,                                             userData=userData)        #读取odb文件进行数据后处理        Hist_extract(userData)

                                        这一部分语句的实现功能为判断计算任务为失败或成功。当收到计算任务失败的反馈信息时,将字符串ERROR写入到状态文件中,同时将无效值NaN写入到结果文件,并通过removeMessageCallback方法移除对当前任务的监控;若收到计算任务成功的反馈信息,则移除对当前任务的监控,并执行Hist_extract()函数开始提取时间历程数据。Hist_extract()函数的实现语句如下所示:

                                          def Hist_extract(Model_data):    # 通过异常处理(exception handing)来读取odb文件  防止读取失败导致整个计算终止    Current_job_name = Model_data[0]    Work_path = Model_data[1]    try:        odb = openOdb(path=Work_path + Current_job_name + '.odb')  # 打开当前计算完成的odb文件        #写入信息到状态文件        file_status_info = open('Status_info.txt', 'a')        file_status_info.write('%-30s' % Model_data[0])        file_status_info.write('%-30s' % 'Complete')        file_status_info.write('%-30s\n' % 'Successful')    except:        #打开失败写入错误信息到状态文件        file_status_info = open('Status_info.txt', 'a')        file_status_info.write('%-30s' % Model_data[0])        file_status_info.write('%-30s' % 'Complete')        file_status_info.write('%-30s\n' % 'Failed')        #写入无效值到结果文件        file_hist_data = open('Hist_output.txt', 'a')        file_hist_data.write('%-30s' % Model_data[0])        file_hist_data.write('%-30s\n' % 'NaN')        return    #查询模型中的分析步名称    Step_name = odb.steps.values()[-1].name     #获取模型中最后一个分析步的名称    Step = odb.steps[Step_name]    region = Step.historyRegions['Node PLATE-1.294']    u1data = region.historyOutputs['U1'].data             #获取节点294沿x方向的位移值    #输出时间历程数据到结果文件    file_hist_data =open('Hist_output.txt','a')    file_hist_data.write('%-30s' % Current_job_name)    file_hist_data.write('%-30.4f\n' % u1data[-1][1])

                                          上面的语句实现的功能为首先通过userData传入的当前求解任务的文件名以及工作路径,尝试读取求解任务的odb文件,若读取失败则写入错误信息到状态文件,并直接开始进行下一轮计算;读取成功则开始提取时间历程数据,并将模型中最后一个分析步的最后一个时刻的数据结果文件中。

                                          本文创建了6个inp文件,并通过修改关键字时其中3个无法 正常计算,通过在Abaqus/CAE中运行上述语句得到状态文件和结果文件的输出结果如图2.1所示。

                                          图2.1 状态文件和结果文件输出结果

                                          从输出结果可以看出,本文编写的脚本能够顺序批量执行计算任务,并当计算错误时输出错误信息,并自动开始下一个计算任务,不会使得整个计算队列终止。但似乎当前程序无法输出第一个inp文件的计算结果,并且脚本文件只能在Abaqs/CAE中执行,如果在Abaqus Command中执行脚本将触发未知错误,目前这些问题仍有待进一步研究。

                                          参考文献

                                          [1]    苏景鹤, 江丙云. ABAQUS Python二次开发攻略[M]. 
                                          [2]    曹金凤, 王旭春, 孔亮. Python语言在Abaqus中的应用[M]. 
                                          [3]    Gautam Puri. PYTHON SCRIPT FOR ABAQUS.
                                          [4]    Abaqus Scripting Reference Guide.
                                          [5]    Abaqus Scripting User's Guide.

                                          Python批量提交inp文件完整程序:

                                            # -*- coding: UTF-8 -*-#Author: Tian#Date: 2020-11-15from abaqus import *from abaqusConstants import *from odbAccess import *from jobMessage import *CPU_num = 4         #并行计算使用的CPU数量Job_num = 3         #待求解inp文件的数量Work_directory = 'C:/Users/xutian/Desktop/batch analysis/input file/'  #inp和py文件所在文件路径Base_job_name = 'Model_Case'   #inp文件的公共名称部分#******************************************************************#定义回调函数用于监控Job执行情况def jobMonitorCallback(jobName, messageType, data, userData):    if (messageType == ABORTED) or (messageType == ERROR):     #计算终止或报错        # 将错误信息输出到状态文件        file_status_info = open('Status_info.txt', 'a')        file_status_info.write('%-30s' % userData[0])        file_status_info.write('%-30s' % 'ERROR')        file_status_info.write('%-30s\n' % 'ERROR')        #写入无效值到结果文件        file_hist_data = open('Hist_output.txt', 'a')        file_hist_data.write('%-30s' % userData[0])        file_hist_data.write('%-30s\n' % 'NaN')        #移除对job的监控        #回调函数将不再被执行        monitorManager.removeMessageCallback(jobName = userData[0],                                             messageType = ANY_MESSAGE_TYPE,                                             callback = jobMonitorCallback,                                             userData = userData)    elif messageType == JOB_COMPLETED:        # 移除对job的监控        #回调函数将不再被执行        monitorManager.removeMessageCallback(jobName=userData[0],                                             messageType=ANY_MESSAGE_TYPE,                                             callback=jobMonitorCallback,                                             userData=userData)        #读取odb文件进行数据后处理        Hist_extract(userData)#******************************************************************#******************************************************************#定义函数体用于读取odb文件并提取时间历程数据def Hist_extract(Model_data):    # 通过异常处理(exception handing)来读取odb文件  防止读取失败导致整个计算终止    Current_job_name = Model_data[0]    Work_path = Model_data[1]    try:        odb = openOdb(path=Work_path + Current_job_name + '.odb')  # 打开当前计算完成的odb文件        #写入信息到状态文件        file_status_info = open('Status_info.txt', 'a')        file_status_info.write('%-30s' % Model_data[0])        file_status_info.write('%-30s' % 'Complete')        file_status_info.write('%-30s\n' % 'Successful')    except:        #打开失败写入错误信息到状态文件        file_status_info = open('Status_info.txt', 'a')        file_status_info.write('%-30s' % Model_data[0])        file_status_info.write('%-30s' % 'Complete')        file_status_info.write('%-30s\n' % 'Failed')        #写入无效值到结果文件        file_hist_data = open('Hist_output.txt', 'a')        file_hist_data.write('%-30s' % Model_data[0])        file_hist_data.write('%-30s\n' % 'NaN')        return    #查询模型中的分析步名称    Step_name = odb.steps.values()[-1].name     #获取模型中最后一个分析步的名称    Step = odb.steps[Step_name]    region = Step.historyRegions['Node PLATE-1.294']    u1data = region.historyOutputs['U1'].data             #获取节点294沿x方向的位移值    #输出时间历程数据到结果文件    file_hist_data =open('Hist_output.txt','a')    file_hist_data.write('%-30s' % Current_job_name)    file_hist_data.write('%-30.4f\n' % u1data[-1][1])#******************************************************************#创建列表用于存储Job名称Job_name = ['']*(Job_num+1)for i in range(1,Job_num+1):    Job_name[i] = Base_job_name + str(i)##创建状态文件用于输出求解inp文件和读取odb文件中的状态信息file_status_info = open('Status_info.txt','w')file_status_info.write('%-30s' % 'Input file name')file_status_info.write('%-30s' % 'Analysis status')file_status_info.write('%-30s\n' % 'Postprocess status')#创建结果文件用于存储时间历程数据file_hist_data = open('Hist_output.txt','w')file_hist_data.write('%-30s' % 'Input file name')file_hist_data.write('%-30s\n' % 'results')#利用循环批量提交inp文件进行求解for i in range(1,Job_num+1):    #创建job    mdb.JobFromInputFile(name = Job_name[i],                         inputFileName = Work_directory + Job_name[i] + '.inp',                         numCpus = CPU_num, numDomains = CPU_num)    #监控job    #当求解器收到messageType中指定的消息时将会触发回调函数    #常用的消息类型有:ANY_MESSAGE_TYPE,ABORTED,COMPLETED,ERROR    #这里选择ANY_MESSAGE_TYPE意味着任何消息类型都将触发回调函数    #将当前模型的基本信息(模型名称和工作路径)通过userData传递到回调函数中    Model_info = [Job_name[i], Work_directory]    monitorManager.addMessageCallback(jobName = Job_name[i],                                      messageType = ANY_MESSAGE_TYPE,                                      callback = jobMonitorCallback,                                      userData = Model_info)    #执行job    mdb.jobs[Job_name[i]].submit()    #为了保证inp文件提交运算后可以被顺序执行 需要等到当前计算完成后再进行后续操作    mdb.jobs[Job_name[i]].waitForCompletion()#关闭文本文件file_status_info.close()file_hist_data.close()
                                            来源:FEM and FEA
                                            Abaqus二次开发pythonOrigin
                                            著作权归作者所有,欢迎分享,未经许可,不得转载
                                            首次发布时间:2023-05-30
                                            最近编辑:11月前
                                            追逐繁星的Mono
                                            硕士 签名征集中
                                            获赞 41粉丝 61文章 59课程 0
                                            点赞
                                            收藏
                                            未登录
                                            还没有评论

                                            课程
                                            培训
                                            服务
                                            行家

                                            VIP会员 学习 福利任务 兑换礼品
                                            下载APP
                                            联系我们
                                            帮助与反馈