许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  ABAQUS内核及GUI方法的代理接口(Proxy Interface)

ABAQUS内核及GUI方法的代理接口(Proxy Interface)

阅读数 6
点赞 0
article_banner

概述

随着 CAE 的广泛应用,CAE 用户的水平日渐提高,新需求日渐增多,CAE 软件的二次开发逐渐成为工程师的必备技能。Python 语言简单易懂、开源包众多,是非常流行的 编程语言 。Abaqus 作为一款以 Python 语言为前后处理内核的 CAE 软件,兼具 CAD 软件基于特征建模的方法,还提供了内核与 GUI 二次开发接口,所以基于 Abaqus 进行二次开发的自由度非常大。

Abaqus 的内核脚本二次开发可以从学习日志文件 abaqus.rpy 起步,GUI 脚本二次开发可以从 GUI 用户手册起步。熟悉之后,简单问题可以直接用脚本编写。但是 Abaqus 毕竟不是专业的集成开发环境(IDE),代码补全、参数提示功能较弱,借助专业 IDE 可提高开发效率。由于 Abaqus 的 Python 解释器  无法被专业 IDE 直接调用,需要创建代理模块模拟 Abaqus 各种方法的接口。

本文从学习研究的角度探讨了创建 Abaqus 代理接口的方法,提供了有关脚本及生成的代理文件下载链接(欢迎打赏下载币)。

Abaqus内核及GUI代理的应用效果

在pyCharm中,内核脚本的快捷文档(光标在方法后、括号前,按Ctrl+Q)如下:
内核脚本的快捷文档

   在 pyCharm 中,GUI 脚本的方法提示如下:
GUI脚本的成员提示

   在 pyCharm 中,内核脚本的参数提示(Ctrl+P)如下:
内核脚本的方法参数提示

pyCharm 配置说明

  1. 下载上述文件,从“推荐使用的代理组合”目录下,复制 abaqus.py, abaqusConstants.py, abaqusGui.py 复制到 Python 解释器的 Lib/site-packages目录下,例如: C:\ProgramData\Anaconda2\Lib\site-packages
  2. 修改 pyCharm 设置,Help–>Edit Custom Properties,在 idea.properties 文件中添加一行

        idea.max.intellisense.filesize=99999【#默认是2500kb】,解决 pyCharm 中 File size exceeds configured limit 文件大小不够的问题。原文链接
  3. 重启 pyCharm即可

开发相关背景

Abaqus 自身的 CLI   (command line interface) 窗口具有代码补全功能,补全快捷键为 Tab,其核心模块为 completerABQ.pyc(实现自动补全功能) 和 docstringLookup.pyc(多个字典,保存了方法的路径、参数及说明)。自动补全只支持 CLI 窗口的内核脚本,不支持 GUI 脚本。

Abaqus 的 GUI 二次开发较为繁琐,无法直接调试,查找方法非常不方便。pyCham 的代码补全、参数提示功能很棒,Ctrl+P 参数提示, Ctrl+Q 查看函数、方法文档,很方便。Abaqus 的 python 2.x 解释器经过订制,无法(未找到方法)用于 pyCharm 调试 Abaqus 脚本。

通过生成 Abaqus 代理模块,模拟 Abaqus 各种方法的接口定义,可在通用 Python 解释器中“简单调试”(参数提示、查看文档、语法检查) Abaqus 内核脚本及 GUI 脚本。

开发脚本说明

1. gen_Abaqus_Agent_from_2020_docs.py

   运行环境: Python3  

   脚本说明:通过解析 htm 文件,将 Abauqs 2020 的脚本参考手册转化为代理模块 abaqus.py,输入参数、返回值都有类型及说明。因为部分 htm 文件的编码为 utf-8,为便于处理,选用 python3。
2. gen_AbaqusConstants_Agent.py

   运行环境:Abaqus CAE

   脚本说明:将 abaqusConstants 模块转为代理模型 abaqusConstants.py。调用内置模块,必须在 Abaqus 环境执行。
3. getAbaquStructure.py

   运行环境:Abaqus CAE

   脚本说明:(不推荐)借助 docstringLookup 模块生成代理 abaqus.py, xyPlot.py 等,输入参数无类型,无返回值。 调用内置模块,必须在 Abaqus 环境执行。
4. transferAbaquGUIFunctionFromDocumentation.py

   运行环境:Python

   脚本说明:GUI 参考手册的结构比较复杂(或者说比较混乱),很多类型没有介绍,无法程序自动识别。此脚本只起辅助作用,从 GUI 参考手册的网页中手动复制内容到文本文件,然后用脚本解析文本文件,生成单个类型,然后手动添加到 abaqusGui.py 中,需要注意类型的创建顺序。

脚本内容

1.gen_Abaqus_Agent_from_2020_docs.py

#-*- coding:gbk -*-
from bs4 import BeautifulSoup
import re,os,pickle
'''This script transfers "Abaqus 2020 Scripting Reference Documentatation" to an Agent Model File : abaqus.py

The generated agent "abaqus.py" can be used in pycham for code completion 

1.replace pathDir in __main__   eg:
    pathDir = r'C:\Program Files\Dassault Systemes\SIMULIA2020doc\English\SIMACAEKERRefMap'

2. run this scipt in python3  get "abaqus.py"

3. run gen_AbaqusConstants_Agent.py in abaqus to get 'abaqusConstants.py'

by alienwxy 2020-05-05

'''

def cutInfo(info):
    info = info.strip()
    return  info
    cutLen = 50
    rst = re.findall('[A-Z][A-Z_0-9]+',info)
    if rst and info.startswith('A SymbolicConstant'):
        return ', '.join(rst)
    else:
        if len(info)>cutLen*2:
            return info[:cutLen]+' ... '+info[-cutLen:]
        else:
            return info
#解析目录所有htm文件
def partseDir(dirPath):
    modules = {
   
   } #'moduleName': methods, constructs, members
    objects = {
   
   }
    failed = []

    # 先更新所有方法
    for fname in os.listdir(dirPath):
        if fname.endswith('.pkl'):
            try:
                with open(os.path.join(dirPath, fname), 'rb') as fp:
                    titleList, methodDict, constructDict, memberList = pickle.load(fp)

                titletype,titlename,titleintro = titleList
                if titletype == 'object':
                    if titlename in objects: #对象已经存在,忽略标题,合并方法,合并成员变量
                        dic =objects[titlename] #对象字典
                        if methodDict:
                            mtddic = dic['methodDict']
                            for name,body in methodDict.items():
                                if name in mtddic: #方法名已存在
                                    if mtddic[name] == body:
                                        continue
                                    else:
                                        pname = name[:-1] if name[-1].isdigit() else name #不含结尾数字的名称
                                        name = pname+str(len([n for n in mtddic.keys() if n.startswith(pname)])) #新名称
                                mtddic[name] = body
                        if memberList:
                            mmblst = dic['memberList']
                            mmblst.extend(memberList)
                    else: #对象不存在,创建标题,方法字典、成员变量列表
                        objects[titlename] = {
   
   
                            'intro':titleintro, #''
                            'methodDict':methodDict,#intro reqargs, optArgs, returns
                            'memberList':memberList, #[[n,i,v],[n,i,v]]  []
                        }

                elif titletype =='module':
                    if titlename in modules:  # 对象已经存在,忽略标题,合并方法,合并成员变量
                        dic = modules[titlename]  # 对象字典
                        if methodDict:
                            mtddic = dic['methodDict']
                            for name, body in methodDict.items():
                                if name in mtddic:  # 方法名已存在
                                    if mtddic[name] == body:
                                        continue
                                    else:
                                        pname = name[:-1] if name[-1].isdigit() else name  # 不含结尾数字的名称
                                        name = pname + str(len([n for n in mtddic.keys() if n.startswith(pname)]))  # 新名称
                                mtddic[name] = body
                        if memberList:
                            mmblst = dic['memberList']
                            mmblst.extend(memberList)
                    else:  # 对象不存在,创建标题,方法字典、成员变量列表
                        modules[titlename] = {
   
   
                            'intro': titleintro,  # ''
                            'methodDict': methodDict,  # intro reqargs, optArgs, returns
                            'memberList': memberList,  # [[n,i,v],[n,i,v]]  []
                        }
                else:
                    continue

            except:
                print(fname)
                failed.append(os.path.join(dirPath,fname))

    # 更新所有构造器--只针对 objects
    for fname in os.listdir(dirPath):
        if fname.endswith('.pkl'):
            # try:
            with open(os.path.join(dirPath, fname), 'rb') as fp:
                titleList, methodDict, constructDict, memberList = pickle.load(fp)

            titletype, titlename, titleintro = titleList

            if constructDict:
                for name,body in constructDict.items():
                    if body['paths']:
                        for path in body['paths']:
                            objectName = recoverObjectFromPathString(path)
                            if not objectName: continue
                            if objectName in objects:  # 对象已经存在,添加方法
                                dic = objects[objectName]  # 对象字典
                                mtddic = dic['methodDict']
                                if name in mtddic: # 方法名已存在
                                    if mtddic[name] == body:
                                        pass
                                    else:
                                        pname = name[:-1] if name[-1].isdigit() else name  # 不含结尾数字的名称
                                        name = pname + str(len([n for n in mtddic.keys() if n.startswith(pname)]))  # 新名称
                                mtddic[name] = body

                            else:  # 对象不存在,创建标题,方法字典、成员变量列表
                                objects[objectName] = {
   
   
                                    'intro': '',  # ''
                                    'methodDict': {
   
   name:body},  # intro reqargs, optArgs, returns
                                    'memberList': [],  # [[n,i,v],[n,i,v]]  []
                                }
            # except:
            #     pass

    modules = list(modules.items())
    objects = list(objects.items())
    modules.sort()
    objects.sort()

    writeObjects(objects)
    # writeModules(modules)

    if failed:
        with open('failed.txt','w') as fp:
            for i in failed:
                fp.write('%s\n' % i)

#写入函数
def writeFunction2file(fp, funcName,funcBody):
    intro = funcBody['intro']
    reqArgs = funcBody['reqArgs']
    optArgs = funcBody['optArgs']
    returns = funcBody['returns']

    if reqArgs:
        reqstr = ', '.join([i[0] for i in reqArgs])
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = ', '.join([reqstr, optstr])
        else:
            argstr = reqstr
    else:
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = optstr
        else:
            argstr = ''

    if funcName in ('print','import','class','def'):
        funcName = funcName + '_'
    fp.write('def %s(%s):\n' % (funcName, argstr))
    fp.write('    """\n')
    fp.write('    %s\n\n' % cutInfo(intro))
    if reqArgs:
        for arg, info in reqArgs:
            fp.write('    :param %s: %s\n' % (arg, cutInfo(info)))
    if optArgs:
        for arg, info, value in optArgs:
            fp.write('    :param %s: %s\n' % (arg, cutInfo(info)))
    if returns:
        value, info = returns
        fp.write('    :return %s: %s\n' % (value, cutInfo(info)))

    fp.write('    """\n')

    if returns:
        value, info = returns
        fp.write('    return %s\n' % (value,))
#写入方法
def writeMethod2file(fp,funcName,funcBody):
    intro = funcBody['intro']
    reqArgs = funcBody['reqArgs']
    optArgs = funcBody['optArgs']
    returns = funcBody['returns']

    if reqArgs:
        reqstr = ', '.join([i[0] for i in reqArgs])
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = ', '.join(['self',reqstr, optstr])
        else:
            argstr = ', '.join(['self',reqstr])
    else:
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = ', '.join(['self', optstr])
        else:
            argstr = 'self'
    if funcName in ('print','import','class','def'):
        funcName = funcName + '_'
    fp.write('    def %s(%s):\n' % (funcName, argstr))
    fp.write('        """\n')
    fp.write('        %s\n\n' % cutInfo(intro))
    if reqArgs:
        for arg, info in reqArgs:
            fp.write('        :param %s: %s\n' % (arg, cutInfo(info)))
    if optArgs:
        for arg, info, value in optArgs:
            fp.write('        :param %s: %s\n' % (arg, cutInfo(info)))
    if returns:
        value, info = returns
        fp.write('        :return %s: %s\n' % (value, cutInfo(info)))

    fp.write('        """\n')

    if returns:
        value, info = returns
        fp.write('        return %s\n' % (value,))
def _writeRepositoryClass2file(fp,className,classBody,objects):
    intro = classBody['intro']
    methodDict = classBody['methodDict']
    memberList = classBody['memberList']
    fp.write('class %s(tuple):\n' % className)
    fp.write('    def __init__(self, rtype="", *args, **kwargs):\n'
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删
相关文章
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空