萬眾期待的 HyperMesh 寶典的二次開發系列又出新教程了!

 

【HyperMesh寶典】二次開發之問問HyperMesh 2020-01

 

 

 

廢話不多說,我們趕緊開始這一期的教程吧~

 

【HyperMesh寶典】二次開發之問問HyperMesh 2020-02

 

電腦程式就是一個獲取輸入進行加工處理然後產生輸出(或動作)的過程(如圖)。

 

HyperMesh API 主要分為資料查詢,模型修改和使用者介面三大類,其中大部分 API 屬於模型修改命令,好消息是當你執行特定的操作時 HyperMesh 就會自動把相關的命令記錄在 command.tcl 。本講要介紹的就是 “獲取輸入” 這一部分。

 

獲取輸入大致可以分為三大類:讓用戶輸入、 從檔輸入、 通過命令從 HyperMesh 資料庫中查詢。下面讓我們來看看這三種分別要怎麼實現吧~

 

 

01

讓用戶輸入

 

讓使用者通過鍵盤或者滑鼠進行輸入通常是給使用者一個介面然後提示使用者選擇或者輸入, Tk 中有很多這類工具,不過我們還是先看一下 HyperMesh 直接可用的幾個。

 

例如想快速創建多個 components,輸入空字串結束。我們可以使用下面這幾句命令。

 

 

 

【HyperMesh寶典】二次開發之問問HyperMesh 2020-03

點擊圖片可查看高清大圖

 

TIPS上文中的 ne 用於字串的比較,如果是數值比較記得要換成 == 或者 != ,因為在字串的範疇內 “9”  不等於 “9.0” ,因為使用的頻率非常高,大家千萬要留心這個坑。

 

 

02

從檔輸入

 

如果上例中輸入的量很大,我們經常希望直接從檔中讀取這些 components 的名稱,csv 檔的內容如下(共 59 行):

 

我們可以寫一個簡短的腳本來進行自動創建 : 

 

程式說明:

第一行:讓使用者選擇一個檔,返回全路徑

第二行:打開檔,將檔的通道號保存在變數ch中

第三行:eof $ch 是一個運算式,如已經讀到檔結尾,返回1,否則返回0

第四行:gets 命令每次讀取一行並保存到變數 line 裡,下次再執行時自動讀取下一行

第五行:判斷以 $line 為名字的 comp 是否已經存在

第六行:創建一個 comp

 

【HyperMesh寶典】二次開發之問問HyperMesh 2020-04

 

二次開發的過程經常需要檢查某個物件在 HyperMesh 資料庫中是否存在,比如你要創建一個 component 或者 load collecotor 時需要先查詢該物件是否已經在系統中存在,確定不存在時才能創建。否則 HyperMesh 將創建失敗並導致程式崩潰。

判斷一個物件是否在存在可以有多種辦法,可以使用 HyperMesh 提供的 API ,或者直接判斷某個 id 號是否在列表中。

例如下面的代碼查詢一個模型中是否存在 230000 號的單元(這裡故意選了個不存在的 id 號,這是最糟糕的情況)。使用 HyperMesh 提供的 API 可以獲得巨大的性能優勢(因為這些通常是 C/C++ 寫的)。

 

輸出如下:

 

 

03

通過命令從HyperMesh資料庫中查詢

 

這是最重要的一種輸入資料獲取方式

二次開發中最常見的命令之一就是獲取物件 id 號的命令,通常 id 號分成有順序和無順序兩種情況。在創建 setRBE2,施加載荷時通常不需要考慮節點順序,但是在用 ruled 劃分網格,通過節點創建曲線等情況下就必須考慮節點的順序。

不需要考慮順序時最關鍵的命令是先使用 *createmark *createmarkpanel 創建一個id號的集合,然後使用 hm_getmark 獲取集合中的 id 號。

如果需要考慮順序,一種方法是同 lsort *createmark 得到的 id 號進行自訂排序(如果忘記了,可以劃到文章最頂端複習一下上一講~),另外一種方法是直接通過 *createlist 命令直接得到有順序的清單。

由於 *createmark 命令得到的 id 號是無序的,因此,返回的 id 號清單和物件被選擇的先後順序無關。每種物件類型可以有兩個 mark 分別是12,可以進行集合運算。

求差: *markdifference

求交: *markintersection

異或: *marknotintersection

此外,還可以使用 *appendmark 對已選擇區進行擴展,比如 by faceby attached 等等。

另外,我們也可以通過不同類型物件之間的關聯關係進行選擇,比如先選擇一些節點,然後再順藤摸瓜間接地選中與這些節點相連的單元。這時候需要的命令是 *findmark 命令,命令使用方法可以參考一下 HyperMesh 介面下的 find 面板。

例如我們希望選擇與某個節點相連的所有單元,在 find 面板選擇節點操作過程如下:

記錄的命令如下:

*createmark nodes 1 6957

*findmark nodes 1 257 1 elements 0 2

然後我們可以提取得到的單元 id 號,類似的命令在二次開發過程中經常用到

 

除非需要和使用者進行交互,通常我們都是用 *createmark 命令,該命令選項非常之多。為了降低大家學習該命令的難度,我們已將視頻教程上傳,大家可以自行觀看學習~

    

某些選擇方法只能針對特定的物件類型才有效,比如你可以用 “by path” 的方法去選擇一串節點,但是你不能用這個方法來選擇單元。你可以使用 “by adjacent” 選擇單元,但是不能用這個方法選擇節點。很多按照空間位置進行選擇的命令對幾何物件都無法使用。

例如在選擇 elemsnodessurfaces 的時候,在 HyperMesh 介面下會有不同的可用選項。

 
 
 

*createmark 命令的部分選項如下:

 

TIPS這個命令對於二次開發至關重要,建議大家自己親自去實踐一下。

 

除了查詢具體的某些物件的id,我們還可以直接得到某類物件的完整id號清單

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

hm_entitylist nodes id 得到所有節點的 id

hm_entityinfo 還可以查詢大量和某個物件類型相關的資訊,比如查詢某類物件的最大id號的命令如下:

hm_entityinfo maxid entity_type

或者通過兩個給定點找到一條路徑上的所有節點:

 
 

 

是不是覺得文章乾貨太多,看不過來呢? 別急,休息下~ 我們再來學習一個新的知識點~

 

【HyperMesh寶典】二次開發之問問HyperMesh 2020-05

 
 
 
 
 
 

dataname

 

除了 id 號,我們還經常需要查詢和某個具體物件相關的資訊,每一種物件都有大量的相關資料可供查詢,我們把這些屬性稱為 dataname

到底什麼是 dataname 呢?

簡單的說 dataname 就是物件的屬性(如果你瞭解物件導向程式設計的話,這裡的屬性和物件導向程式設計中的物件的屬性是類似的),比如節點的屬性有 id 號,x,y,z 的座標等。通常每一種物件的屬性都非常的多,我們無法全部記住,所以程式設計的時候經常需要查詢。強烈建議把 dataname 查詢的網址收藏到流覽器的我的最愛裡方便隨時查看。一些經常用到的 dataname 可以猜得出來,比如 components 可能有 idnamecolorpropid 等。熟能生巧,用多了自然就記住了。

 

用來獲取 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):

 

 

散場前的話:

QHyperMesh 一共有多少條查詢命令?

A 2017.2 版本中是 525條,你想好好學習的大家非常有必要從頭到尾看一下,一定會有收穫的。

 

【HyperMesh寶典】二次開發之問問HyperMesh 2020-06

 

這一講就到這裡啦~下一期我們講學習二次開發中陣列、字典和字串資料型別,敬請期待~ 喜歡教程的小夥伴請給我們點讚或者留言唷~

arrow
arrow

    Altair Taiwan 發表在 痞客邦 留言(0) 人氣()