首页/文章/ 详情

【HyperMesh宝典】二次开发之问问HyperMesh

7月前浏览2231

本文摘要(由AI生成):

文章主要介绍了HyperMesh API的三大类:数据查询、模型修改和用户界面。获取输入分为让用户输入、从文件输入、通过命令从HyperMesh数据库中查询。其中,通过命令从HyperMesh数据库中查询是最重要的一种输入数据获取方式。文章还介绍了一些常用的命令,如*createmark、*findmark、hm_entitylist、hm_entityinfo等,并给出了一些示例。

万众期待的 HyperMesh 宝典的二次开发系列又出新教程了!


 


上一期,有用户希望我们加快更新速度,没问题!我们从月更变成了周更,方老师实在太给力啦~

还有用户希望我们把前几期的链接一起贴出来,没问题!链接在此(点击链接可以直接跳转阅读):

   
     
     
         

第一期:你也可以来做二次开发

   
     
     
         

第二期:二次开发之命令的解析

  
   
     
     
         

第三期:二次开发之 Tcl 中的变量




计算机程序就是一个获取输入进行加工处理然后产生输出(或动作)的过程(如图)。

 

 HyperMesh 的 API 主要分为数据查询,模型修改和用户界面三大类,其中大部分 API 属于模型修改命令,好消息是当你执行特定的操作时 HyperMesh 就会自动把相关的命令记录在 command.tcl 。本讲要介绍的就是 “获取输入” 这一部分。

获取输入大致可以分为三大类:让用户输入、 从文件输入、 通过命令从 HyperMesh 数据库中查询。下面让我们来看看这三种分别要怎么实现吧~


01

让用户输入

让用户通过键盘或者鼠标进行输入通常是给用户一个界面然后提示用户选择或者输入, Tk 中有很多这类工具,不过我们还是先看一下 HyperMesh 直接可用的几个。

 

例如想快速创建多个 components,输入空字符串结束。我们可以使用下面这几句命令。

 
 

(点击图片可查看高清大图)


TIPS:上文中的 ne 用于字符串的比较,如果是数值比较记得要换成 == 或者 != ,因为在字符串的范畴内 “9”  不等于 “9.0” ,因为使用的频率非常高,大家千万要留心这个坑。

 


02

从文件输入

如果上例中输入的量很大,我们经常希望直接从文件中读取这些 components 的名称,csv 文件的内容如下(共 59 行):

 

我们可以写一个简短的脚本来进行自动创建 : 

 

程序说明:

第一行:让用户选择一个文件,返回全路径

第二行:打开文件,将文件的通道号保存在变量ch中

第三行:eof $ch 是一个表达式,如已经读到文件结尾,返回1,否则返回0

第四行:gets 命令每次读取一行并保存到变量 line 里,下次再执行时自动读取下一行

第五行:判断以 $line 为名字的 comp 是否已经存在

第六行:创建一个 comp


 


二次开发的过程经常需要检查某个对象在 HyperMesh 数据库中是否存在,比如你要创建一个 component 或者 load collecotor 时需要先查询该对象是否已经在系统中存在,确定不存在时才能创建。否则 HyperMesh 将创建失败并导致程序崩溃。

判断一个对象是否在存在可以有多种办法,可以使用 HyperMesh 提供的 API ,或者直接判断某个 id 号是否在列表中。

例如下面的代码查询一个模型中是否存在 230000 号的单元(这里故意选了个不存在的 id 号,这是最糟糕的情况)。使用 HyperMesh 提供的 API 可以获得巨大的性能优势(因为这些通常是 C/C++ 写的)。

 

输出如下:

 


03

通过命令从HyperMesh数据库中查询

这是最重要的一种输入数据获取方式

二次开发中最常见的命令之一就是获取对象 id 号的命令,通常 id 号分成有顺序和无顺序两种情况。在创建 set,RBE2,施加载荷时通常不需要考虑节点顺序,但是在用 ruled 划分网格,通过节点创建曲线等情况下就必须考虑节点的顺序。

►不需要考虑顺序时最关键的命令是先使用 *createmark 和 *createmarkpanel 创建一个id号的集 合,然后使用 hm_getmark 获取集 合中的 id 号。

►如果需要考虑顺序,一种方法是同 lsort 对 *createmark 得到的 id 号进行自定义排序(如果忘记了,可以划到文章最顶端复习一下上一讲~),另外一种方法是直接通过 *createlist 命令直接得到有顺序的列表。

由于 *createmark 命令得到的 id 号是无序的,因此,返回的 id 号列表和对象被选择的先后顺序无关。每种对象类型可以有两个 mark 分别是1和2,可以进行集 合运算。

求差: *markdifference

求交: *markintersection

异或: *marknotintersection

此外,还可以使用 *appendmark 对已选择区进行扩展,比如 by face,by attached 等等。

另外,我们也可以通过不同类型对象之间的关联关系进行选择,比如先选择一些节点,然后再顺藤摸瓜间接地选中与这些节点相连的单元。这时候需要的命令是 *findmark 命令,命令使用方法可以参考一下 HyperMesh 界面下的 find 面板。

例如我们希望选择与某个节点相连的所有单元,在 find 面板选择节点操作过程如下:

 
 

记录的命令如下:

*createmark nodes 1 6957

*findmark nodes 1 257 1 elements 0 2

然后我们可以提取得到的单元 id 号,类似的命令在二次开发过程中经常用到

 

除非需要和用户进行交互,通常我们都是用 *createmark 命令,该命令选项非常之多。为了降低大家学习该命令的难度,我们已将视频教程上传至Altair百度网盘,大家可以自行下载学习~

 

点我下载

某些选择方法只能针对特定的对象类型才有效,比如你可以用 “by path” 的方法去选择一串节点,但是你不能用这个方法来选择单元。你可以使用 “by adjacent” 选择单元,但是不能用这个方法选择节点。很多按照空间位置进行选择的命令对几何对象都无法使用。

例如在选择 elems、nodes、surfaces 的时候,在 HyperMesh 界面下会有不同的可用选项。

 
 
 

*createmark 命令的部分选项如下:

 

TIPS:这个命令对于二次开发至关重要,建议大家自己亲自去实践一下。


除了查询具体的某些对象的id,我们还可以直接得到某类对象的完整id号列表

hm_entitylist comps name 得到所有comp的名字;

hm_entitylist nodes id 得到所有节点的 id;

hm_entityinfo 还可以查询大量和某个对象类型相关的信息,比如查询某类对象的最大id号的命令如下:

hm_entityinfo maxid entity_type

或者通过两个给定点找到一条路径上的所有节点: 

 
 


是不是觉得文章干货太多,看不过来呢? 别急,休息下~ 我们再来学习一个新的知识点~

 


dataname

除了 id 号,我们还经常需要查询和某个具体对象相关的信息,每一种对象都有大量的相关数据可供查询,我们把这些属性称为 dataname 。

到底什么是 dataname 呢?

简单的说 dataname 就是对象的属性(如果你了解面向对象编程的话,这里的属性和面向对象编程中的对象的属性是类似的),比如节点的属性有 id 号,x,y,z 的坐标等。通常每一种对象的属性都非常的多,我们无法全部记住,所以编程的时候经常需要查询。强烈建议把 dataname 查询的网址收藏到浏览器的收藏夹里方便随时查看。一些经常用到的 dataname 可以猜得出来,比如 components 可能有 id,name,color,propid 等。熟能生巧,用多了自然就记住了。

 

用来获取 dataname 的最关键的命令就只有一条 hm_getvalue,语法如下:

  

使用 hm_getvalue 命令可以轻松返回同一类型的一系列对象的某一个 dataname,比如一百万个节点的 x坐标组成的列表。

hm_getvalue nodes mark=1 dataname=globalx

由于 hm_getvalue 可以使用 mark 作为输入,所以我们可以先把一系列对象先用 *createmark 进行打包然后再在 hm_getvalue 中进行统一查询,或者我们也可以通过一个循环的方式每次查询一个对象的一个 dataname,两者的效果是一样的。

下面例子对两种的效率做了比较,都在可接受的范围:

 

输出如下:

 

我们有时需要对不同的列表进行重新组装,比如将 {x1 x2 x3} {y1 y2 y3} {z1 z2 z3} 三个列表重新组装为 {{x1 y1 z1} {x2 y2 z2} {x3 y3 z3}} 的形式。当然可以像下面的例子一样使用 foreach 循环。

 

但是如果可以去掉这个循环,程序会变得更简洁。和前一讲一样,我们可以再发明一个 zip 函数。该 zip 函数用于将多个数组组成一个新的列表,因为这个过程就像拉链一样进行互相配对,所以用 zip 这个名字非常贴切。

 

该函数使用列表变量的名字作为参数,这就免去了调用函数时的数据复 制,对于大型列表处理时可以节约一些计算资源。

接下来我们希望得到一个这样的列表,列表的每一项节点的坐标值 {{1 2 3} {4 5 6} {7 8 9}},我们先用土方法来看看怎么处理。

 

也不复杂,再看看用zip怎么处理:

 

TIPS:大家可以看到,foreach 里面的东西简单多了,因为需要的数据都已经事先准备好了。

上面用到一个新的语法 {*}$coord ,意思是进行序列解包。{*}{ 1 2 3} 等价于 1 2 3 三个值,利用这个语法可以替代很多命令中的 eval 强制再解析。

还记得上一讲中的 lmap 吗?也可以用在这里呀~

 

一个没有循环的脚本实在是太简单了。不过用在这里未免有点太花哨了点,把变量名变成变量导致程序的可读性下降了(如果改用数组变量,可读性会好一些,下一讲会介绍),性能也没有什么提升。用或不用,看你自己的爱好吧。

有一些对象的属性使用得非常频繁,有一些专门的 API ,查询节点的坐标可以使用 hm_nodevalue 。

下面这两句的效果是一样的:

set x [lindex [hm_nodevalue 76226] 0 1];注意:这里很容易犯错,因为HyperMesh多返回了一层{}!

set x [hm_getentityvalue nodes id=76226 dataname=x]

查询单元的节点 id 号使用 hm_nodelist,下面这两句的效果是一样的。 

hm_nodelist 200

hm_getentityvalue elems id=200 dataname=nodes

如果你查询的是求解器的卡片,那么 dataname 就无法在帮助中直接查询了。

比如查询 OptiStruct 的 PSHELL 卡片中的厚度项T 的数值可以使用命令:

hm_getvalue props id=2 dataname=95


Q:但是95这个dataname是哪里跑出来的呢?


►方法一:

在HyperMesh界面下手工修改一下这个数值,然后就可以在 command.tcl 文件中看到一条命令

*setvalue props id=1 STATUS=1 95=3

这个 3 就是我输入的新的厚度数值,那前面那个 95 自然就是我们要找的 dataname 了。对于一些复杂的情况,一个界面修改操作可能会生成一系列的命令记录,那么你可以使用一个方便鉴别的数值,比如 3.1415 或者 54321,更详细的方法后面的讲座还会讲到。


►方法二:

直接在对应的输出模板文件里查找,比如刚刚我们用的厚度属性的dataname定义文件位于: 安装目录\Altair\2017\templates\feoutput\common_nas_os\attribs

 

由于方法二比方法一麻烦很多,所以,我几乎不用方法二。


很多时候我们不仅仅要查询某些对象的具体信息,我们还需要查询关于 HyperMesh 的一些信息。比如工作目录,当前 hm文件的文件名,当前的求解器模板,当前 component/loadcollector 等。比如我们写的脚本只能用于 OptiStruct 求解器,那么我们就需要在脚本里加上判断求解器模板的命令。

 

结果可以在 global 面板中查看(快捷键g):

 


►散场前的话:

Q:HyperMesh 一共有多少条查询命令?

A:在 2017.2 版本中是 525条,你想好好学习的大家非常有必要从头到尾看一下,一定会有收获的。


 


这一讲就到这里啦~下一期我们讲学习二次开发中数组、字典和字符串数据类型,敬请期待~ 喜欢教程的小伙伴请给我们点赞或者留言哟~


来源:Altair澳汰尔
OptiStructHyperMesh二次开发Altair
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2024-03-25
最近编辑:7月前
Altair澳汰尔
澳汰尔工程软件(上海)有限公司
获赞 142粉丝 475文章 743课程 4
点赞
收藏
未登录
1条评论
Seesea
签名征集中
4月前
您好,请问为什么我在软件界面的操作不会被记录在tcl中呢
回复
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈