Rainyboy 发表于 2010-10-14 22:24

利用[宏]功能定制ANSYS工具栏的一种方法(In C/C++)

本帖最后由 Rainyboy 于 2010-10-14 22:35 编辑

    不知大家有没有这样的经验,有些时候接了某研究所的课题,要求分析某个结构的强度或者寿命,或者再进一步形成这种结构的设计方法。合同中要求我们提供一个【界面程序】,在这个【界面程序】中,设计者只需要输入最原始的【几何参数】、【材料参数】、【载荷参数】,由该【界面程序】直接调用ANSYS进行计算和后处理。
    整个过程中不需要直接接触APDL代码,完全是由“点鼠标”和“输入数据”完成。这样的【界面程序】有一个好处,就是使用者不必担心直接修改APDL源程序带来的版本混乱、功能出错等风险,而且比较方便。

0)先看一个【界面程序】的例子吧(为某单位开发的某结构计算软件,合同中有保密条款,所以作了些处理):

其他功能不提,当用户按下【开始计算】便会弹出如下对话框:

用户再次按下【确定】后,就会在程序当前运行的目录下生成一个与输入JobName相同的文件夹,并在此文件夹中载入ANSYS,运行后,其工具栏上会出现一些定制的功能按钮,点击这些按钮,就可以执行这些定制功能了(比如“建模”“分网”“求解”和“后处理”),而且还可以根据需要显示对话框:



    这种【界面程序】的核心,在于外部程序中实现对ANSYS的调用和定制,这正是我想在这里和大家分享和探讨的问题。

1)定制ANSYS工具栏的流程(也许不是唯一的实现方法):
    a) 准备好APDL(这一步通常希望由用户通过【界面程序】设置参数后完成,其实就是在指定的目录按照用户输入的参数生成文件,不是本帖的重点),将后缀名改为.MAC,存放在某个工作目录下。例如有建模代码MODEL.MAC和求解代码SOLU.MAC存放在目录d:/ansyswork下
    b) 找到.../ANSYS INC/V110/ANSYS/APDL 中的start110.ans文件,在文件的最后加入:
          /PSEARCH,
          *ABBR,MODEL,MODEL
          *ABBR,SOLU,SOLU
   c)启动ANSYS11,设置工作目录为d:/ansyswork,那么ANSYS11启动完毕之后,就会在工具栏上出现MODEL和SOLU的按钮了,点击相应的按钮就相当于执行了对应文件中的APDL代码。
   d)将start110.ans所增加的内容删除,避免对其它工作产生影响。
2)编程过程中的几个关键:
   a)获得ANSYS的安装目录

char *pAnsysDir;//ANSYS文件目录
if(!(pAnsysDir=getenv("ANSYS100_DIR")))//由环境变量得到ANSYS文件目录
return 0;   b)以命令行方式调用ANSYS并指定JobName

void CallANSYS(char *pAnsysDir,const char *pANSYSName)//调用ANSYS
{
char pLoadDir;
char t[]="\"";
char temp;
StrLink(t,temp,pAnsysDir);
StrLink(temp,pLoadDir,"\\bin\\intel\\ansys100\" -g -j ");
StrLink(pLoadDir,pLoadDir,pANSYSName);
system(pLoadDir);
return;
}3)程序源代码(CallAnsysSpeci.h头文件):

#ifndef ASSUME_CALL_ANSYS_SPECI_RAINYBOY_20090310
#define ASSUME_CALL_ANSYS_SPECI_RAINYBOY_20090310
/************************************************************************/
/*                      在指定的目录载入指定的文件调用ANSYS             */
/*                      范雨 2009年3月23日调试完毕                            */
/************************************************************************/
//在之前应该在程序的工作目录中准备:
//名字为APDLMAC文件夹
//名字为APDLMAC文件夹,下有宏文件以及PSEARCH.txt文件
//PSEARCH.txt文件的格式为:
/*********************************************/
/*          /PSEARCH,
/*          *ABBR,******,******
/*          *ABBR,******,******
/**********************************************/
//宏文件的内容为APDL代码
//后缀为.MAC
//安装ANSYS10
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#define DIRNAMEBUFFER 100
void StrLink(char * pBase,char * pTarget,char *pAdd);//增长字符串
void StrLink(char * pBase,char * pTarget,const char *pAdd);
void SetAPDL(const char * pWorkDir,char * pApdlDir);//设置APDL宏:通过改写start文件
void CallANSYS(char *pAnsysDir,const char *pANSYSName);//调用ANSYS
void ClearAPDL(const char * pWorkDir,char * pApdlDir);//恢复APDL宏:通过恢复start文件
int LoadAnsysFrom(const char *pWorkDir,const char *pANSYSName);
void LoadANSYSNamed(const char *ANSYSName);//入口函数
#endif4)程序代码(CallAnsysSpeci.cpp文件)

#include "CallAnsysSpeci.h"
//流程的具体实现
void StrLink(char * pBase,char * pTarget,char *pAdd)//增长字符串
{
int i,len;
for(i=0;1;++i)
{
if(pBase=='\0')
   break;
pTarget=pBase;
}
len=i;
//在末尾加上pAdd
for(i=0;pAdd!='\0';++i)
pTarget=pAdd;
//封口
pTarget='\0';
return;
}
void StrLink(char * pBase,char * pTarget,const char *pAdd)//增长字符串
{
int i,len;
for(i=0;1;++i)
{
if(pBase=='\0')
   break;
pTarget=pBase;
}
len=i;
//在末尾加上pAdd
for(i=0;pAdd!='\0';++i)
pTarget=pAdd;
//封口
pTarget='\0';
return;
}
void SetAPDL(const char * pWorkDir,char * pApdlDir)//设置APDL宏:通过改写start文件
{
SetCurrentDirectory(pApdlDir);//将工作目录改为ADPL宏目录
ifstream oldfile;
ifstream datafile;
ofstream newfile;
char pBuff;
oldfile.open("start100.ans",ios::in);
newfile.open("BB.ans",ios::out);
//复制内容即可
while (!oldfile.eof())
{
oldfile.getline(pBuff,DIRNAMEBUFFER);
newfile<<pBuff<<endl;
}
oldfile.close();
SetCurrentDirectory(pWorkDir);//恢复工作目录
datafile.open("PSEARCH.txt",ios::in);
//在第一行加上工作目录
datafile.getline(pBuff,DIRNAMEBUFFER);
newfile<<"/PSEARCH,"<<pWorkDir<<endl;
//处理剩下的内容
while(!datafile.eof())
{
datafile.getline(pBuff,DIRNAMEBUFFER);
newfile<<pBuff<<endl;
}
datafile.close();
newfile.close();
SetCurrentDirectory(pApdlDir);//再次将工作目录改为ADPL宏目录
system("ren start100.ans start100.bak");//备份
system("ren BB.ans start100.ans");//替换
SetCurrentDirectory(pWorkDir);//恢复工作目录
return;
}
void CallANSYS(char *pAnsysDir,const char *pANSYSName)//调用ANSYS
{
char pLoadDir;
char t[]="\"";
char temp;
StrLink(t,temp,pAnsysDir);
StrLink(temp,pLoadDir,"\\bin\\intel\\ansys100\" -g -j ");
StrLink(pLoadDir,pLoadDir,pANSYSName);
system(pLoadDir);
return;
}
void ClearAPDL(const char * pWorkDir,char * pApdlDir)//恢复APDL宏:通过恢复start文件
{
SetCurrentDirectory(pApdlDir);//再次将工作目录改为ADPL宏目录
system("del start100.ans");//备份
system("ren start100.bak start100.ans");//替换
SetCurrentDirectory(pWorkDir);//恢复工作目录
return;
}
int LoadAnsysFrom(const char *pWorkDir,const char *pANSYSName)
{
char *pAnsysDir;//ANSYS文件目录
char pApdlDir;//APDL的宏设置目录
if(!(pAnsysDir=getenv("ANSYS100_DIR")))//由环境变量得到ANSYS文件目录
return 0;
StrLink(pAnsysDir,pApdlDir,"\\apdl");//修正得到APDL的宏设置目录
SetAPDL(pWorkDir,pApdlDir); //改写start100.ans文件
CallANSYS(pAnsysDir,pANSYSName);//调用ANSYS
ClearAPDL(pWorkDir,pApdlDir);//恢复APDL宏设置
return 1;
}
void LoadANSYSNamed(const char *ANSYSName)//入口函数
{
string AdditionCmd(ANSYSName);
TCHAR _tCurrDir;
GetCurrentDirectory(DIRNAMEBUFFER,_tCurrDir);
string CurrDir(_tCurrDir);//指向创建的文件夹
string APDLMAC_Dir("\\APDLMAC");//指向APDLMAC
string AdditionDir("\\");
string ComLineCreatDir("md ");//创建文件夹的命令行
string ComLineCopyFile("copy *.* ");//拷贝文件的命令行
//构造各个字符串
APDLMAC_Dir=CurrDir+APDLMAC_Dir;
AdditionDir+=AdditionCmd;
ComLineCreatDir+=AdditionCmd;
CurrDir+=AdditionDir;
ComLineCopyFile+=CurrDir;
//创建文件夹
system(ComLineCreatDir.c_str());
//设置当前文件夹为APDLMAC
SetCurrentDirectory(APDLMAC_Dir.c_str());
//复制文件
system(ComLineCopyFile.c_str());
//设置当前文件夹为用户指定文件夹
SetCurrentDirectory(CurrDir.c_str());
//调用ANSYS
LoadAnsysFrom(CurrDir.c_str(),ANSYSName);
//恢复用户文件夹
SetCurrentDirectory(_tCurrDir);
}5)(最后再啰嗦一下……)如何使用该源代码:
    以VC 为例,将如下文件放在一个文件夹中:
    CallAnsysSpeci.h
    CallAnsysSpeci.cpp
    main.cpp
    前两个文件是本帖提供的源代码,main.cpp视你所需要的场合而定,例如,可以很简单:

#include "CallAnsysSpeci.h"
//主函数
int main()
{
LoadANSYSNamed("Rainyboy");
return 0;
}编译后会得到一个应用程序,假设名字为test.exe。要运行此程序,还应按照头文件注释的要求(也是帖子开头的说明)准备如下东西:
//在之前应该在程序的工作目录中准备:
//名字为APDLMAC文件夹
//名字为APDLMAC文件夹,下有宏文件以及PSEARCH.txt文件
//PSEARCH.txt文件的格式为:
/*********************************************/
/*   /PSEARCH,
/*          *ABBR,******,******
/*          *ABBR,******,******
/**********************************************/
//宏文件的内容为APDL代码
//后缀为.MAC
//安装ANSYS10
万事俱备之后,就会在程序运行的目录下运行ANSYS,并在其工具栏上显示定制的按钮,当你退出ANSYS时,test.exe程序会自动为你清除对ANSYS的定制。

6)回到开头,那个【界面程序】的流程图:


即对于各个问题的界面程序,生成APDL代码的方式有很多种,但是最后总会逃不了调用ANSYS并定制按钮,这就是我在这里仅仅讨论这一部分内容的原因。

不知道把问题说清楚没有,代码是一年前写的了,有一些冗长,如果用C#或者VB重写,应该要简单一些。

有梦的人 发表于 2010-10-20 17:53

楼主很厉害...,希望能和你交流这方面的技术啊,能留个联系方式吗?

Rainyboy 发表于 2010-10-20 18:31

回复 有梦的人 的帖子

咱们论坛不就是联系方式么{:{02}:}

有梦的人 发表于 2010-10-20 18:36

可是即时交流不行啊,呵呵,坛子是会来的,要做的项目和你做得差不多,多多指教

Rainyboy 发表于 2010-10-20 18:44

回复 有梦的人 的帖子

那你可以先把代码存下来用用,如果不能直接为你的场合所用的话,再根据你的实际情形做一些修改。在使用中有涉及ANSYS相关的问题你可以在这个分区发帖,如果纯粹是编码实现的问题可以到算法与编程语言区探讨。

有梦的人 发表于 2010-10-20 18:49

已经COPY了,不过想问个ANSYS的,ANSYS10.0进行流固耦合分析时候,怎么找不到FSI相关命令的工具啊,看了帮助说是被其它的代替了,能不能支个招啊

16443 发表于 2010-10-20 19:54

回复 Rainyboy 的帖子

如果没有版权问题,可以把源程序也给分享了,好让别人参考你的程序。

Rainyboy 发表于 2010-10-20 20:08

回复 16443 的帖子

整个界面程序是有版权的,按合同不得向第三方转让。但是这篇帖子所涉及的方法分享给大家没有问题,相应的源代码在文中都贴出来了。之所以不采用附件,是因为代码本身不长,大家即时能看到的话可以提提意见。谢谢你对这部分工作的肯定{:{40}:}

bingo_1124 发表于 2010-11-6 21:38

这个真的很厉害啊

linderman 发表于 2010-11-9 21:49

啧啧~~((em:01))

有梦的人 发表于 2010-11-15 18:01

Rainyboy 发表于 2010-10-14 22:24 static/image/common/back.gif
不知大家有没有这样的经验,有些时候接了某研究所的课题,要求分析某个结构的强度或者寿命,或者再进一 ...

感觉你的这个程序是对ANSYS的显式调用,为什么 不做成隐式的啊,那样不是更好吗?不用直接在ANSYS窗口界面,只需要对话框输入就行了啊,望赐教啊

Rainyboy 发表于 2010-11-15 19:23

回复 11 # 有梦的人 的帖子

你说得对,后台调用有后台调用的好处,这种情况下用户完全可以不知道他在使用ANSYS进行计算(当然他得装ANSYS,有点纠结哈……),界面程序需要为用户提供非常全面的后处理,满足所有的需求;我贴出来的这个程序运行之后计算结果最终还是在ANSYS里呈现,要说比后台调用好的话就在于用户可以爱怎么做后处理就怎么做后处理,在使用定制化的按钮功能的同时也不妨碍使用ANSYS本身提供的功能,当然,最大的好处就是界面程序不需要提供特别多的后处理功能了。
实际上哪个更好我想得看使用场合吧,用户需要什么,咱们就做什么{:{46}:}

有梦的人 发表于 2010-11-15 20:07

嗯,是这样的,不过你的程序有的地方我还是有些看不懂,呵呵...,但很想请教你

Rainyboy 发表于 2010-11-15 20:50

回复 13 # 有梦的人 的帖子

恩,是流程的问题还是语言的问题?

有梦的人 发表于 2010-11-15 21:11

以前看一些介绍二次开发的,都是用CREATEPROCESS,或者是WinExec等函数实现,你的这个,以命令行,也就是说可以显式的调用吗?整个函数都要自己写的吗?
页: [1] 2 3 4
查看完整版本: 利用[宏]功能定制ANSYS工具栏的一种方法(In C/C++)