凡亿专栏 | 利用Python与HFSS联合仿真设计微带天线(全文共附260多行代码)
利用Python与HFSS联合仿真设计微带天线(全文共附260多行代码)

我们知道HFSS是一款电磁仿真商用软件,用其进行天线的设计十分方便。而该软件也预留了可以运行脚本的接口,使用者可以使用脚本对软件进行控制,实现模型的建立、求解等等。由于后期可能会用到联合仿真,而大多数联合仿真的脚本都是使用的Matlab进行编程,网上也有不少现成的api,因为对python比较熟悉,且python除了数值计算其他的功能也相当强大,并且免费开源,于是决定用python写一个建模的脚本(其实是我matlab学得太烂了),折腾了两天,终于把微带天线的模型建立与仿真的过程搞定了,当然是基于有Matthew Radway这位大牛的基础上。这个例子也是接触HFSS时手绘天线做的第一个例子,现在用代码做一遍,也是很有意思的事情。下面分享给大家。


1、连接软件


GetAppDesktop

Use:     GetAppDesktopis a function of    oAnsoftApp. This function does not take an input and it returns an object. The object is assigned to the variable   oDesktop.

Syntax:              GetAppDesktop()

Return Value:    Object.

Parameters:      None

Example:     

Set oDesktop = oAnsoftApp.GetAppDesktop()


给出了函数名,参数值,返回值,以及一个实例(这个帮助文档写得很不错,但是后面阅读过程中也发现了一些小错误,当然很可能是因为我用的是daoban)。这个返回值oAnsoftApp就是后面进行一系列操作要使用的对象,所有的操作的形式都是下面这样:oAnsoftApp.


python中编写了一个接口函数把这个函数封装在里面。代码如下:


  1. from __future__ import division, print_function, unicode_literals, absolute_import


  2. import win32com.client


  3. def setup_interface():

  4.     """

  5.     Set up the COM interface to the running HFSS process.


  6.     Returns

  7.     -------

  8.     oAnsoftApp : pywin32 COMObject

  9.         Handle to the HFSS application interface

  10.     oDesktop : pywin32 COMObject

  11.         Handle to the HFSS desktop interface


  12.     Examples

  13.     --------

  14.     >>> import Hyphasis as hfss

  15.     >>> [oAnsoftApp, oDesktop] = hfss.setup_interface()


  16.     """

  17.     # I'm still looking for a better way to do this.  This attaches to an 

  18.     # existing HFSS process instead of creating a new one.  I would highly 

  19.     # prefer that a new process is created.  Apparently 

  20.     # win32com.client.DispatchEx() doesn't work here either.

  21.     oAnsoftApp = win32com.client.Dispatch('AnsoftHfss.HfssScriptInterface')


  22.     oDesktop = oAnsoftApp.GetAppDesktop()


  23.     return [oAnsoftApp, oDesktop]


作者用了win32com.client.Dispatch()这个函数,这个函数是专门用来连接接口的,返回值中的那个oDesktop就是生成的对象。


实际调用代码:[oAnsoftApp, oDesktop] = hfss.setup_interface()


2、新建一个project


oProject = hfss.new_project(oDesktop)


这里就是用了上面生成的oDesktop对象新建了一个object,具体查阅help文档和编写api的工作和上一步一致,并且平时使用时直接使用接口调用即可。注意,下面进行的操作都在这个project中,所以下面操作的对象就是oProject了。这个时候HFSS里应该长这样了。


2270d1d0b2dbc6b01c848e18d99ce8.png


3、保存project


养成良好习惯,新建的文件之后先保存,在编写过程中因为没有先保存,生成了一堆临时文件,挺讨厌的。这个传人的参数可以包含路径。

hfss.save_as_project(oDesktop,"E:/dj/test/microstrip_antenna.hfss")


4、新建一个design


这里传人的参数为design的名字,设计模式。

oDesign = hfss.insert_design(oProject, "HFSSDesign1", "DrivenModal")

新建完成后发现和我们手动操作是一样的。


428ed7704fc6f8396668313cec7c9f.png


5、建立模型

教程中首先新建了一个地板,并设置为PEC。这里也分别调用了这两个函数,尺寸可以用字符串输入,很方便灵活,不需要自己转换为一堆小数点的数字。设置PEC表面首先需要获得平面的faceid,再给这个表面设置边界条件。

  1. raw_input('Press "Enter" to draw a ground plane>')


  2. ground = hfss.create_rectangle(

  3.     oEditor,   

  4.     "-45mm", 

  5.     "-45mm", 

  6.     0,

  7.     "90mm", 

  8.     "90mm",

  9.     Name='ground',

  10.     Transparency=0.8)


  11. raw_input('Press "Enter" to assign a PerfectE boundary condition on the ground.>')

  12. ground_faceid=[]

  13. ground_faceidnum = hfss.get_face_by_position(oEditor, ground, 0, 0, 0)

  14. print ground_faceidnum

  15. ground_faceid.append(ground_faceidnum)

  16. hfss.assign_perfect_e(oDesign, "ground", ground_faceid)


由于建模过程比较类似,这里就不逐个给出了,模型建立完毕如下图(包括了设置边界条件和设置端口):

f11c72f5e3eb0ac15cf427aaf55991.jpg


6、设置求解和扫频

这里求解函数传人了中心频点;扫频传入了扫频方式,起始频率和终止频率,频率间隔。

  1. raw_input('Press "Enter" to insert analysis setup.>')  


  2. setuplist=[]


  3. setupname = hfss.insert_analysis_setup(oDesign, 2.45)


  4. setuplist.append(setupname) 


  5. raw_input('Press "Enter" to insert frequency sweep.>')  


  6. hfss.insert_frequency_sweep(oDesign,

  7.                             setupname,

  8.                             "Sweep1",

  9.                             1.5,

  10.                             3.5,

  11.                             0.1,

  12.                             IsEnabled=True,

  13.                             SetupType="LinearStep",

  14.                             Type="Discrete",

  15.                             SaveFields=True,

  16.                             ExtrapToDC=False)


7、求解

对于每个setup进行求解。是不是和手动操作是一样的?

hfss.solve(oDesign,setuplist)

c098696c1010d7144e9b78651a0dbd.png


8、退出HFSS

hfss.quit_application(oDesktop)

结束语:

今天暂时研究到这儿,还有很多比如查看求解完成后的驻波、增益曲线等等还有设置主从边界啦很多的api还没有编写,有时间会继续完善。

做了个有趣的小玩意儿,分享给大家~

完整主函数源码(api部分还不是很完整,哦,相当不完整,就先不给出了):


  1. # -*- coding: utf-8 -*-

  2. """

  3. Created on Fri Apr 22 14:29:38 2016

  4. @author: DJ

  5. """


  6. from __future__ import division


  7. import hycohanz as hfss


  8. raw_input('Press "Enter" to connect to HFSS.>')


  9. [oAnsoftApp, oDesktop] = hfss.setup_interface()


  10. raw_input('Press "Enter" to create a new project.>')


  11. oProject = hfss.new_project(oDesktop)


  12. raw_input('Press "Enter" to save the project.>') 


  13. hfss.save_as_project(oDesktop,"E:/dj/test/microstrip_antenna.hfss")


  14. raw_input('Press "Enter" to insert a new DrivenModal design named HFSSDesign1.>')


  15. oDesign = hfss.insert_design(oProject, "HFSSDesign1", "DrivenModal")


  16. raw_input('Press "Enter" to set the active editor to "3D Modeler" (The default and only known correct value).>')


  17. oEditor = hfss.set_active_editor(oDesign)


  18. raw_input('Press "Enter" to draw a ground plane>')


  19. ground = hfss.create_rectangle(

  20.     oEditor,   

  21.     "-45mm", 

  22.     "-45mm", 

  23.     0,

  24.     "90mm", 

  25.     "90mm",

  26.     Name='ground',

  27.     Transparency=0.8)


  28. raw_input('Press "Enter" to assign a PerfectE boundary condition on the ground.>')

  29. ground_faceid=[]

  30. ground_faceidnum = hfss.get_face_by_position(oEditor, ground, 0, 0, 0)

  31. print ground_faceidnum

  32. ground_faceid.append(ground_faceidnum)

  33. hfss.assign_perfect_e(oDesign, "ground", ground_faceid)


  34. raw_input('Press "Enter" to insert some substrate properties into the design.>')


  35. hfss.add_property(oDesign, "w", hfss.Expression("80mm"))

  36. hfss.add_property(oDesign, "h", hfss.Expression("5mm"))


  37. raw_input('Press "Enter" to draw a substrate using the properties.>')


  38. substrate = hfss.create_box(

  39.     oEditor,   

  40.     -hfss.Expression("w")/2, 

  41.     -hfss.Expression("w")/2, 

  42.     0,

  43.     hfss.Expression("w"), 

  44.     hfss.Expression("w"),

  45.     hfss.Expression("h"),

  46.     Name='substrate',

  47.     Transparency=0.8)


  48. raw_input('''Press "Enter" to change the substrate's material to Rogers 4003>''')


  49. hfss.assign_material(oEditor, [substrate], MaterialName="Rogers RO4003 (tm)")


  50. raw_input('Press "Enter" to insert some patch properties into the design.>')


  51. hfss.add_property(oDesign, "w_p", hfss.Expression("31.0mm"))

  52. hfss.add_property(oDesign, "l_p", hfss.Expression("41.4mm"))


  53. raw_input('Press "Enter" to draw a patch>')


  54. patch = hfss.create_rectangle(

  55.     oEditor,   

  56.     -hfss.Expression("w_p")/2, 

  57.     -hfss.Expression("l_p")/2, 

  58.     hfss.Expression("h"),

  59.     hfss.Expression("w_p"), 

  60.     hfss.Expression("l_p"),

  61.     Name='patch',

  62.     Transparency=0.8)


  63. raw_input('Press "Enter" to assign a PerfectE boundary condition on the patch.>')

  64. patch_faceid=[]

  65. print hfss.Expression("h")

  66. patch_faceidnum = hfss.get_face_by_position(oEditor, patch, 0, 0, 0.005) #hardcode!!

  67. #print ground_faceidnum

  68. patch_faceid.append(patch_faceidnum)

  69. hfss.assign_perfect_e(oDesign, "patch", patch_faceid)


  70. raw_input('Press "Enter" to draw a Coaxial core>')


  71. Coaxial_core = hfss.create_cylinder(

  72.     oEditor,   

  73.     "9.5mm", 

  74.     0, 

  75.     0,

  76.     "0.5mm", 

  77.     "5mm",

  78.     Name='Coaxial_core',

  79.     Transparency=0.8)


  80. raw_input('''Press "Enter" to change the Coaxial_core's material to copper>''')


  81. hfss.assign_material(oEditor, [Coaxial_core], MaterialName="copper")


  82. raw_input('Press "Enter" to draw a Signal transmission port>')


  83. port = hfss.create_circle(

  84.     oEditor,   

  85.     "9.5mm", 

  86.     0, 

  87.     0,

  88.     "1.5mm", 

  89.     Name='port',

  90.     Transparency=0.8)


  91. raw_input('Press "Enter" to subtract the transmission port from the ground.>')


  92. hfss.subtract(oEditor, [ground], [port], KeepOriginals=True)


  93. raw_input('Press "Enter" to draw an air box>')


  94. air = hfss.create_box(

  95.     oEditor,   

  96.     '-80mm', 

  97.     '-80mm', 

  98.     0,

  99.     '160mm', 

  100.     '160mm',

  101.     '75mm',

  102.     Name='air',

  103.     Transparency=0.8)


  104. raw_input('Press "Enter" to assign a Radiation boundary condition for the air box.>')

  105. air_objectid=[]

  106. air_objectidnum = hfss.get_object_id_by_name(oEditor, "air")

  107. #print ground_faceidnum

  108. air_objectid.append(air_objectidnum)

  109. print air_objectid

  110. hfss.assign_radiation(oDesign, objectname=['air'], Name='Air')


  111. raw_input('Press "Enter" to assign a lumped port on the port.>')


  112. port_faceid=[]


  113. port_faceidnum = hfss.get_face_by_position(oEditor, port, "9.5mm", 0, 0) #hardcode!!

  114. #print port_faceidnum

  115. port_faceid.append(port_faceidnum)

  116. hfss.assign_lumpedport_multimode(oDesign, "port", port_faceid,["10mm","0mm","0mm"],["11mm","0mm","0mm"])


  117. raw_input('Press "Enter" to insert analysis setup.>')  


  118. setuplist=[]


  119. setupname = hfss.insert_analysis_setup(oDesign, 2.45)


  120. setuplist.append(setupname) 


  121. raw_input('Press "Enter" to insert frequency sweep.>')  


  122. hfss.insert_frequency_sweep(oDesign,

  123.                             setupname,

  124.                             "Sweep1",

  125.                             1.5,

  126.                             3.5,

  127.                             0.1,

  128.                             IsEnabled=True,

  129.                             SetupType="LinearStep",

  130.                             Type="Discrete",

  131.                             SaveFields=True,

  132.                             ExtrapToDC=False)


  133. raw_input('Press "Enter" to solve the setup.>') 


  134. hfss.solve(oDesign,setuplist)


  135. raw_input('Press "Enter" to quit HFSS.>')


  136. hfss.quit_application(oDesktop)


  137. del oEditor

  138. del oDesign

  139. del oProject

  140. del oDesktop

  141. del oAnsoftApp

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表凡亿课堂立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。
相关阅读
进入分区查看更多精彩内容>
精彩评论

暂无评论