摘要:本节主要介绍波导查值模块,以及HFSS调用模块的编写。

波导查值模块

该部分要实现的功能主要是根据输入的工作频率,自动选择合适的标准波导尺寸,免去翻资料的麻烦,实现起来逻辑很简单,也就是单纯地根据条件来查值,查值方法有两种:根据工作频点来判断;

根据波导名直接查询;

两种方式均可用简单的函数来实现,代码如下所示(wg.py):

"""波导尺寸查询"""

# 标准波导尺寸表

wg_list = (

('BJ3', 0.32, 0.49, 584.2, 292.1),

('BJ4', 0.35, 0.53, 533.4, 266.7),

('BJ5', 0.41, 0.62, 457.2, 228.6),

('BJ6', 0.49, 0.75, 381.0, 190.5),

('BJ8', 0.64, 0.98, 292.1, 146.05),

('BJ9', 0.76, 1.15, 247.65, 123.82),

('BJ12', 0.96, 1.46, 195.58, 97.79),

('BJ14', 1.13, 1.73, 165.10, 82.55),

('BJ18', 1.45, 2.20, 129.54, 64.77),

('BJ22', 1.72, 2.61, 109.22, 54.61),

('BJ26', 2.17, 3.30, 86.36, 43.18),

('BJ32', 2.60, 3.35, 72.14, 34.04),

('BJ40', 3.22, 4.90, 58.17, 29.08),

('BJ48', 3.94, 5.99, 47.549, 22.149),

('BJ58', 4.64, 7.05, 40.386, 20.193),

('BJ70', 5.38, 8.17, 34.849, 15.799),

('BJ84', 6.57, 9.99, 28.499, 12.624),

('BJ100', 8.20, 12.5, 22.86, 10.160),

('BJ120', 9.84, 15.0, 19.050, 9.525),

('BJ140', 11.9, 18.0, 15.799, 7.899),

('BJ180', 14.5, 22.0, 12.954, 6.477),

('BJ220', 17.6, 26.7, 10.668, 4.318),

('BJ260', 21.7, 33.0, 8.636, 4.318),

('BJ320', 26.3, 40.0, 7.112, 3.556),

('BJ400', 32.9, 50.1, 5.690, 2.845),

('BJ500', 39.2, 59.6, 4.775, 2.388),

('BJ620', 49.8, 75.8, 3.759, 1.880),

)

def check_by_freq(freq):

"""通过输入频点查找标准波导尺寸:param freq: 频点,GHz:return: 波导的宽边a和短边b,mm"""

a, b = None, None

for i in wg_list:

if i[1] <= freq <= i[2]:

a, b = i[3], i[4]

break

return a, b

def check_by_name(name):

"""通过名称来查找标准波导尺寸:param name: 波导名,如‘BJ100’:return: 波导的宽边a和短边b,mm"""

a, b = None, None

for i in wg_list:

if i[0] == name:

a, b = i[3], i[4]

break

return a, b

if __name__ == '__main__':

a1, b1 = check_by_freq(25)

a2, b2 = check_by_name('BJ320')

print(a1, b1)

print(a2, b2)

实际使用中第一种“自动判断”的场景要多一些,但有时候也会特别指定波导型号,故两者皆写好供调用。

HFSS调用模块

这一部分是稍微比较麻烦的,需要用到HFSS自己的“代码录制”功能和Python的win32com模块。

首先,众所周知,HFSS支持脚本控制,可将操作录制为一段脚本,便于自动化运行以及实现较为复杂的建模功能,该功能位于Tools——Record Script to File中,支持vbs和python两种格式(早期版本仅支持vbs)。

因此,要调用HFSS建模,自然会想到先用“代码录制”功能将建模操作录制下来,再进行简单修改,最后再想办法用python直接运行调用。

顺着这个思路,首先梳理下角锥喇叭的建模步骤,以及对应步骤抽象出来的封装函数(注:建模方法当然不止一种,以下仅为个人习惯方式):

设置变量。个人习惯先把变量建好,这一步操作应抽象并封装成函数:设置变量(set_variable)——1建喇叭天线内腔。画两个同尺寸矩形,connect而成立方体;再画两个不同尺寸矩形,connect而成锥台;两者unite而成联合体。这一步操作有:画一个矩形(create_centered_rectangle)——2

联合两个面(connect)——3

布尔和(unite)——4建喇叭天线体并设为金属。采用同上方法画一个更大一些的联合体,然后与第一步得到的联合体相减,最后设置材料为PEC,新操作有:复制(copy_and_paste)——5

布尔差(subtract)——6

设置材料属性(set_material)——7建空气盒子和辐射边界。操作有:画一个区域(create_region)——8

设置辐射边界(assign_radiation_region)——9

插入方向图设置(insert_radiation_setup)——10画端口并设置解算参数。操作有:画一个端口(assign_port)——11

设置解算参数(insert_analysis_setup)——12保存工程后仿真并生成报告。操作有:保存(save_prj)——13

仿真(run)——14

生成仿真报告(create_reports)——15

梳理以后发现,完成一个喇叭建模,竟然大概要写15个函数。。。感觉不知比直接建模要麻烦到哪儿去了,但考虑到这些函数写好了,以后可以被大量复用,相当在于写一个小型API,故是一种先难后易的做法。

对于每一个封装函数的实现,操作步骤为先用HFSS录制脚本,在进行修改。以实现并封装set_variable这个函数为例,首先在HFSS中设一个名为w1,值为20mm的变量,把这段操作录制为py程序,打开后如下所示:

# ----------------------------------------------

# Script Recorded by ANSYS Electronics Desktop Version 2018.0.0

# 10:13:34 十一月 17, 2018

# ----------------------------------------------

import ScriptEnv

ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")

oDesktop.RestoreWindow()

oProject = oDesktop.SetActiveProject("Project2")

oDesign = oProject.SetActiveDesign("HFSSDesign1")

oDesign.ChangeProperty(

[

"NAME:AllTabs",

[

"NAME:LocalVariableTab",

[

"NAME:PropServers",

"LocalVariables"

],

[

"NAME:NewProps",

[

"NAME:w1",

"PropType:=" , "VariableProp",

"UserDef:=" , True,

"Value:=" , "20mm"

]

]

]

])

这段原始代码有以下几点要注意:

一个HFSS专属坑。一定得要先删除注释中的中文和中文符号!!!这点特别坑爹,HFSS不能正确识别任何带中文字符的路径和脚本,连它自己录制的也不行(希望HFSS下个版本能改掉这个万年bug);

引用模块调用无效。import ScriptEnv 在HFSS外部调用时没有意义,因为这不是一个通用的Python包,也就是说想在Python中写这么一段就调用HFSS是不可能的;

格式。格式有点杂乱,相当地不pythonic,这当然是不能忍的,应手动调整一下。

改写后的代码如下所示(将变量名与变量值设成了输入参数):

def set_variable(_var_name, _var_value):

_NAME = 'NAME:' + _var_name

_VALUE = str(_var_value) + 'mm'

oDesign.ChangeProperty(["NAME:AllTabs",

["NAME:LocalVariableTab",

["NAME:PropServers", "LocalVariables"],

["NAME:NewProps",

[_NAME, "PropType:=", "VariableProp", "UserDef:=", True, "Value:=", _VALUE]]]])

改写以后,是否感觉清爽了很多?采用这种思路,将15个函数统统编好,为了调用方便,再整体封装为一个对象HFSS,程序就比较像样了。

最后要强调的就是,通过查阅各种资料,我个人认为在Python中直接打开HFSS最好的方式还是要借助win32com这个模块,其介绍如下:python模块:win32com用法详解 - 杜雪峰的个人页面 - 开源中国​my.oschina.net

综合以上,形成HFSS调用模块,其代码如下(sim.py):

from win32com import client

import os

class HFSS:

def __init__(self):

self.oAnsoftApp = client.Dispatch('AnsoftHfss.HfssScriptInterface')

self.oDesktop = self.oAnsoftApp.GetAppDesktop()

self.oProject = self.oDesktop.NewProject()

self.oProject.InsertDesign('HFSS', 'HFSSDesign1', 'DrivenModal1', '')

self.oDesign = self.oProject.SetActiveDesign("HFSSDesign1")

self.oEditor = self.oDesign.SetActiveEditor("3D Modeler")

self.oModule = self.oDesign.GetModule('BoundarySetup')

self.transparency = 0.5

def set_variable(self, _var_name, _var_value):

_NAME = 'NAME:' + _var_name

_VALUE = str(_var_value) + 'mm'

self.oDesign.ChangeProperty(["NAME:AllTabs",

["NAME:LocalVariableTab",

["NAME:PropServers", "LocalVariables"],

["NAME:NewProps",

[_NAME, "PropType:=", "VariableProp", "UserDef:=", True, "Value:=", _VALUE]]]])

def create_centered_rectangle(self, _var_x, _var_y, _var_z, _name, _dir='Z'):

self.oEditor.CreateRectangle(

[

"NAME:RectangleParameters",

"IsCovered:=", True,

"XStart:=", '-' + _var_x + '/2',

"YStart:=", '-' + _var_y + '/2',

"ZStart:=", _var_z,

"Width:=", _var_x,

"Height:=", _var_y,

"WhichAxis:=", _dir

],

[

"NAME:Attributes",

"Name:=", _name,

"Flags:=", "",

"Color:=", "(143 175 143)",

"Transparency:=", 0,

"PartCoordinateSystem:=", "Global",

"UDMId:=", "",

"MaterialValue:=", "\"vacuum\"",

"SurfaceMaterialValue:=", "\"\"",

"SolveInside:=", True,

"IsMaterialEditable:=", True,

"UseMaterialAppearance:=", False

])

def connect(self, _obj1, _obj2):

self.oEditor.Connect(["NAME:Selections", "Selections:=", _obj1 + ',' + _obj2])

def unite(self, _obj1, _obj2):

self.oEditor.Unite(["NAME:Selections", "Selections:=", _obj1 + ',' + _obj2],

["NAME:UniteParameters", "KeepOriginals:=", False])

def subtract(self, _obj1, _obj2):

self.oEditor.Subtract(["NAME:Selections", "Blank Parts:=", _obj1, "Tool Parts:=", _obj2],

["NAME:SubtractParameters", "KeepOriginals:=", False])

def copy_and_paste(self, _obj):

self.oEditor.Copy(["NAME:Selections", "Selections:=", _obj])

self.oEditor.Paste()

def set_material(self, _obj, _mat='pec'):

self.oEditor.AssignMaterial(

[

"NAME:Selections",

"AllowRegionDependentPartSelectionForPMLCreation:=", True,

"AllowRegionSelectionForPMLCreation:=", True,

"Selections:=", _obj

],

[

"NAME:Attributes",

"MaterialValue:=", "\"" + _mat + "\"",

"SolveInside:=", False,

"IsMaterialEditable:=", True,

"UseMaterialAppearance:=", False

])

def assign_port(self, _obj):

self.oModule.AssignWavePort(["NAME:1", "Objects:=", [_obj],

"NumModes:=", 1, "RenormalizeAllTerminals:=", True,

"UseLineModeAlignment:=", False, "DoDeembed:=", False,

["NAME:Modes",

["NAME:Mode1", "ModeNum:=", 1, "UseIntLine:=", False, "CharImp:=", "Zpi"]],

"ShowReporterFilter:=", False,

"ReporterFilter:=", [True],

"UseAnalyticAlignment:=", False])

def create_region(self, _var_ab):

self.oEditor.CreateRegion(

[

"NAME:RegionParameters",

"+XPaddingType:=", "Absolute Offset",

"+XPadding:=", _var_ab,

"-XPaddingType:=", "Absolute Offset",

"-XPadding:=", _var_ab,

"+YPaddingType:=", "Absolute Offset",

"+YPadding:=", _var_ab,

"-YPaddingType:=", "Absolute Offset",

"-YPadding:=", _var_ab,

"+ZPaddingType:=", "Absolute Offset",

"+ZPadding:=", _var_ab,

"-ZPaddingType:=", "Absolute Offset",

"-ZPadding:=", _var_ab

],

[

"NAME:Attributes",

"Name:=", "Region",

"Flags:=", "Wireframe#",

"Color:=", "(143 175 143)",

"Transparency:=", 0,

"PartCoordinateSystem:=", "Global",

"UDMId:=", "",

"MaterialValue:=", "\"vacuum\"",

"SurfaceMaterialValue:=", "\"\"",

"SolveInside:=", True,

"IsMaterialEditable:=", True,

"UseMaterialAppearance:=", False

])

def assign_radiation_region(self):

self.oModule.AssignRadiation(

[

"NAME:Rad1",

"Objects:=", ["Region"],

"IsFssReference:=", False,

"IsForPML:=", False

])

def insert_radiation_setup(self):

mod = self.oDesign.GetModule('RadField')

mod.InsertFarFieldSphereSetup(

[

"NAME:Infinite Sphere1",

"UseCustomRadiationSurface:=", False,

"ThetaStart:=", "-180deg",

"ThetaStop:=", "180deg",

"ThetaStep:=", "1deg",

"PhiStart:=", "0deg",

"PhiStop:=", "90deg",

"PhiStep:=", "90deg",

"UseLocalCS:=", False

])

def insert_analysis_setup(self, _freq):

mod = self.oDesign.GetModule('AnalysisSetup')

mod.InsertSetup("HfssDriven",

[

"NAME:Setup1",

"AdaptMultipleFreqs:=", False,

"Frequency:=", str(_freq) + 'GHz',

"MaxDeltaS:=", 0.02,

"PortsOnly:=", False,

"UseMatrixConv:=", False,

"MaximumPasses:=", 20,

"MinimumPasses:=", 1,

"MinimumConvergedPasses:=", 1,

"PercentRefinement:=", 30,

"IsEnabled:=", True,

"BasisOrder:=", 1,

"DoLambdaRefine:=", True,

"DoMaterialLambda:=", True,

"SetLambdaTarget:=", False,

"Target:=", 0.3333,

"UseMaxTetIncrease:=", False,

"PortAccuracy:=", 2,

"UseABCOnPort:=", False,

"SetPortMinMaxTri:=", False,

"UseDomains:=", False,

"UseIterativeSolver:=", False,

"SaveRadFieldsOnly:=", False,

"SaveAnyFields:=", True,

"IESolverType:=", "Auto",

"LambdaTargetForIESolver:=", 0.15,

"UseDefaultLambdaTgtForIESolver:=", True

])

def create_reports(self):

mod = self.oDesign.GetModule('ReportSetup')

mod.CreateReport("VSWR Plot 1", "Modal Solution Data", "Rectangular Plot", "Setup1 : LastAdaptive", [],

["Freq:=", ["All"], ],

["X Component:=", "Freq",

"Y Component:=", ["VSWR(1)"]], [])

mod.CreateReport("Realized Gain Plot 1", "Far Fields", "Rectangular Plot", "Setup1 : LastAdaptive",

["Context:=", "Infinite Sphere1"],

[

"Theta:=", ["All"],

"Phi:=", ["All"],

"Freq:=", ["All"],

],

[

"X Component:=", "Theta",

"Y Component:=", ["dB(RealizedGainTotal)"]

], [])

mod.AddTraceCharacteristics("Realized Gain Plot 1", "max", [], ["Full"])

mod.AddTraceCharacteristics("Realized Gain Plot 1", "xdb10Beamwidth", ["3"], ["Full"])

def save_prj(self):

_base_path = os.getcwd()

_prj_num = 1

while True:

_path = os.path.join(_base_path, 'Prj{}.aedt'.format(_prj_num))

if os.path.exists(_path):

_prj_num += 1

else:

break

self.oProject.SaveAs(_path, True)

def run(self):

self.oDesktop.RestoreWindow()

self.oDesign.Analyze('Setup1')

调用方法是首先实例化HFSS对象,再使用其方法,就可以顺利调用HFSS啦,例如:

if __name__ == '__main__':

h = HFSS()

# 设置变量

h.set_variable('wg_a', 22.86)

h.set_variable('wg_b', 10.16)

# 画个矩形

h.create_centered_rectangle('wg_a', 'wg_b', 0, 'wg_in')

# 保存一下

h.save_prj()

要注意的是,save_prj函数会将新建立的工程保存在与程序同样目录中,这个目录的路径照例不可以有任何中文符号,否则HFSS保存出错,至于文件名,save_prj函数中已作了简单的判重处理,不用担心覆盖,当然,有特别需求的请自行修改。

小结

本部分是相对比较麻烦的部分,相当于写了一个HFSS与Python之间的通讯接口,然而后续将会看到,有了这部分基础,主调程序才可以用相对清晰的逻辑来操作HFSS建模。

本篇介绍即到此结束,下一部分将会讲到主调用模块及GUI模块,谢谢各位观看(*^_^*)!

Peace!

用python语言实现喇叭发声原理_用Python实现喇叭天线设计小工具(三)相关推荐

  1. 用python语言实现喇叭发声原理_用Python实现喇叭天线设计小工具(一)

    前言 作为系列文章的第一篇,本文主要介绍采用Python编写一个图形化界面的小程序,方便快速根据波束宽度设计出最优化喇叭天线,一键调用HFSS进行仿真,并可打包为exe文件方便其他人使用,其效果如下: ...

  2. 用python语言实现喇叭发声原理_一文看懂音频原理

    笔者博客:mwhitelab.com 笔者公众号:技术杂学铺 前言 笔者最近正好在做和声音处理有关的项目,突然对音频数字化感兴趣,想了解一下基本原理.可网上文章知识都很散.排版也不美观.因此笔者便决定 ...

  3. 采用python语言实现猜数游戏_用python实现猜数游戏

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 本文实例为大家分享了python实现猜数游戏的具体代码,供大家参考,具体内容如下 ...

  4. python语言下划线怎么打_初学Python语言者必须理解的下划线

    下划线(_)在Python语言中有特殊作用. 在大多数编程语言中,下划线是命名变量或者函数名称时的连字符,但是,在Python语言中,不仅如此.如果你是一名Python程序员,对于诸如 _ in ra ...

  5. python语言的变量特点随时_【Python】Python语言特点

    Python语言强调简洁直观.可读性强,常被称为"可执行的伪代码". 一.一切都是对象 Python是面向对象的编程语言,数.字符串.数据容器.函数.类.模块(函数)等都是对象.每 ...

  6. python语言的记事本在哪_入门Python语言记事本03

    本文主要向大家介绍了入门Python语言记事本03,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断.比如,输入用户年龄, ...

  7. python扫雷的代码及原理_基于Python实现的扫雷游戏实例代码

    摘要:这篇Python开发技术栏目下的"基于Python实现的扫雷游戏实例代码",介绍的技术点是"Python实现.Python.实例代码.扫雷游戏.扫雷.游戏" ...

  8. python语言最适合的领域_掌握python语言可以做什么?十大应用领域介绍

    python作为一门当下极其火爆的编程语言,得到世界范围内无数编程爱好者和开发者喜欢并不是偶然的,除了要比其他编程语言更容易入门,python还拥有无比广阔的应用前景,薪资待遇也非常不错. 1. WE ...

  9. 什么是python语言的动态类型机制_理解Python的Dynamic typing

    Python的Dynamic typing有些类似于C语言的指针,在C中,一个变量可以指向任何地址空间,在Python中,一个变量也可以指向任何type的数据对象.变量的指向可以在程序运行过程中变化, ...

最新文章

  1. hdu3724 字典树(商品条形码)
  2. ModuleNotFoundError: No module named 'tinymce
  3. 设计模式 之 《组合模式》
  4. Pytorch——对应点相乘和矩阵相乘
  5. Linux下的CUDA多版本管理
  6. python rich_Python - rich 库讲解
  7. C# 调用word时,禁用宏
  8. 关于使用CKplayer播放m3u8视频出现没有视频的问题分析
  9. 详解 Redis 中布隆过滤器解决缓存穿透问题
  10. C语言汉字在内存中如何存储
  11. mysql 增加分区_MySql数据分区操作之新增分区操作
  12. 一些网址备忘 (在线剪辑音频、在线工具箱、全网音乐下载)
  13. 操作系统-比例份额调度
  14. oracle_java.exe,系统找不到C:\ProgramData\Oracle\Java\javapath\java.exe问题及解决方案
  15. 新浪微博技术架构分析 2010
  16. Stochastic Weight Averaging (SWA) 随机权重平均
  17. 【音频解码芯片】VS1503音频解码芯片的应用
  18. 小程序集成Three.js,使用npm安装gsap动画库
  19. 无论是狗粮还是降落伞,反正WeLink来了……
  20. Infortrend 荣登“2019年十大云解决方案提供商”行列

热门文章

  1. matlab对曲线等距取点,请问如何在matlab曲线图里面取点
  2. sybase数据库环境搭建的过程
  3. 2018.7.10 无线充电方案 调试
  4. 走进小作坊(十九)----商场博弈论的诡计
  5. LSF Reordering
  6. 在ubuntu18.04中分屏给PC显示器
  7. WPS表格如何对散点数据进行指数函数拟合
  8. 一种 低噪声放大器 电路结构
  9. Shapley Value(****夏普利值,沙普利值****)
  10. 【C/C++】%2d,%02d是什么意思