2022年3月12日 星期六

如何輸出HFSS遠場資料

以下方法可以用在HFSS任何遠場物理量輸出,使用np.ndarray可以加快矩陣運算速度。

import numpy as np
import matplotlib.pyplot as plt
from pyaedt import Hfss
hfss = Hfss(specified_version='2022.1')

data = hfss.post.get_far_field_data(['rETheta', 'rEPhi'],
'Setup1 : LastAdaptive',
'3D')
print(data.units_data)

x_real = data.solutions_data_real['rETheta']
x_imag = data.solutions_data_imag['rETheta']
rETheta = [complex(x_real[i], x_imag[i]) for i in x_real]


x_real = data.solutions_data_real['rEPhi']
x_imag = data.solutions_data_imag['rEPhi']
rEPhi = [complex(x_real[i], x_imag[i]) for i in x_real]

rEPhi = np.array(rEPhi)
x = np.reshape(np.absolute(rEPhi), (361, 181))

plt.xlabel('Phi')
plt.ylabel('Theta')
plt.imshow(x.T, cmap='jet')

(圖一) Python輸出
(圖二)HFSS輸出









2022年2月14日 星期一

如何將平面轉變成曲面

使用PyAEDT模組,適合簡單平面。

# -*- coding: utf-8 -*-
"""
Created on Mon Feb 14 23:36:29 2022

@author: mlin
"""
from math import sqrt
from collections import defaultdict
from scipy import interpolate
from pyaedt import Hfss

hfss = Hfss(specified_version='2021.2')

x = hfss.modeler.object_list
path = x[1]
polygon = x[0]

ds = 0
s_map = {}
for edge in path.edges:
v1, v2 = edge.vertices
x1, y1, z1 = v1.position
x2, y2, z2 = v2.position
if len(s_map) == 0:
s_map[ds] = [(0, 0)]
ds += sqrt((x2 - x1) ** 2 + (z2 - z1) ** 2)
s_map[ds] = (x2, z2)

result = defaultdict(list)

for edge in polygon.edges:
v1, v2 = edge.vertices
x1, y1, z1 = v1.position
x2, y2, z2 = v2.position
x = [x1, x2]
y = [y1, y2]
f = interpolate.interp1d(x, y)
if x2 > x1:
new_s = [i for i in s_map.keys() if x2 >= i >= x1]
else:
new_s = [i for i in reversed(s_map.keys()) if x2 <= i <= x1]

print(new_s)
new_y = f(new_s)
for s, y3 in zip(new_s, new_y):
x3, z3 = s_map[s]
result[s].append((x3, y3, z3))

keys = [k for k in result]
pieces = []
for m, n in zip(keys[0:-1], keys[1:]):
v1, v2 = result[m][0:2]
v4, v3 = result[n][0:2]
p = hfss.modeler.primitives.create_polyline([v1, v2, v3, v4], cover_surface=True, close_surface=True)
pieces.append(p)

sheet = hfss.modeler.unite(pieces)
hfss.modeler.purge_history([pieces[0].name])



2022年2月8日 星期二

如何輸出任一AEDT專案3D模型不同視角圖片檔

範例碼如下(當中export3DModel在0.4.26版輸出.obj仍有問題,需手動修改):

import os
from pyaedt import Hfss
from pyaedt.generic.plot import ModelPlotter

hfss = Hfss('d:/demo/RADHAZ_MIL-STD-461C_ICNIRP.aedt', 'HERP', non_graphical=True)

data = {}
for i in hfss.modeler.object_list:
key = (i.color, i.transparency)
if key in data:
data[key].append(i)
else:
data[key] = [i]

cad = {}
for key, objs in data.items():
filename = objs[0].name
hfss.export3DModel(filename, hfss.temp_directory, '.obj', object_list=[i.name for i in objs])
cad[key] = os.path.join(hfss.temp_directory, filename + '.obj')

hfss.close_desktop()

model = ModelPlotter()
model.bounding_box = False
model.show_legend = False
model.show_grid = True
model.show_axes = False
model.off_screen = True
model.background_color = (240,240,240)
model.zoom = 1

for (color, transparency), cad_path in cad.items():
model.add_object(cad_path, cad_color=color, opacity=1-transparency)

for angle in range(0, 360, 30):
model.set_orientation('yz', 0, angle, 30)
model.plot('d:/demo2/view_{}.png'.format(angle))



2021年12月20日 星期一

抓出App所有屬性(Property)

 執行程式查詢屬性

from pyaedt import Hfss
with Hfss(specified_version='2021.2', non_graphical=True) as hfss:
for i in dir(hfss):
if callable(getattr(hfss, i)) or i in ['components3d'] or i.startswith('_'):
continue
else:
print('{:20}:{}'.format(i, getattr(hfss, i)))

輸出結果


analysis_setup :None
available_variations:<pyaedt.application.Analysis.Analysis.AvailableVariations object at 0x0000014C24948610>
boundaries :[]
close_on_exit :False
default_solution_type:DrivenModal
design_datasets :{}
design_list :['HFSS_PBG']
design_name :HFSS_PBG
design_properties :OrderedDict()
design_type :HFSS
desktop_install_dir :C:/Program Files/AnsysEM/AnsysEM21.2/Win64/
existing_analysis_setups:[]
existing_analysis_sweeps:[]
library_list :['C:\\Program Files\\AnsysEM\\AnsysEM21.2\\Win64\\syslib', 'C:\\Program Files\\AnsysEM\\AnsysEM21.2\\Win64\\userlib', 'D:\\temp\\PersonalLib']
lock_file :D:\temp\Project57.aedt.lock
logger :<pyaedt.aedt_logger.AedtLogger object at 0x0000014C24948C70>
materials :<pyaedt.modules.MaterialLib.Materials object at 0x0000014C24948A00>
mesh :<pyaedt.modules.Mesh.Mesh object at 0x0000014C2493F250>
modeler :<pyaedt.modeler.Model3D.Modeler3D object at 0x0000014C27074E20>
native_components :[]
nominal_adaptive :
nominal_sweep :
opti_designxplorer :<pyaedt.modules.DesignXPloration.DXSetups object at 0x0000014C27074BB0>
opti_doe :<pyaedt.modules.DesignXPloration.DOESetups object at 0x0000014C27074220>
opti_optimization :<pyaedt.modules.DesignXPloration.OptimizationSetups object at 0x0000014C27074730>
opti_parametric :<pyaedt.modules.DesignXPloration.ParametericsSetups object at 0x0000014C27074F40>
opti_sensitivity :<pyaedt.modules.DesignXPloration.SensitivitySetups object at 0x0000014C270746D0>
opti_statistical :<pyaedt.modules.DesignXPloration.StatisticalSetups object at 0x0000014C27074880>
personallib :D:\temp\PersonalLib
post :<pyaedt.modules.AdvancedPostProcessing.PostProcessor object at 0x0000014C2493F460>
project_datasets :{}
project_file :D:\temp\Project57.aedt
project_list :['Project57']
project_name :Project57
project_path :D:\temp
project_properies :OrderedDict()
pyaedt_dir :C:\my_venv\Lib\site-packages\pyaedt
release_on_exit :True
results_directory :D:\temp\Project57.aedtresults
setup_names :()
setups :[]
solution_type :DrivenModal
src_dir :C:\my_venv\Lib\site-packages\pyaedt\application
syslib :C:\Program Files\AnsysEM\AnsysEM21.2\Win64\syslib
temp_directory :C:\Users\mlin\AppData\Local\Temp
toolkit_directory :D:\temp\Project57.toolkit
userlib :C:\Program Files\AnsysEM\AnsysEM21.2\Win64\userlib
valid_design :True
variable_manager :<pyaedt.application.Variables.VariableManager object at 0x0000014C24956550>
working_directory :D:\temp\Project57.toolkit\HFSS_PBG

2021年12月12日 星期日

PyAEDT做螺旋電感模擬並輸出L及Q

 螺旋電感範例

rin = 10
width = 2
spacing = 1
thickness = 1
Np = 8
Nr = 10
gap = 3
Tsub = 6

import matplotlib.pyplot as plt
from math import pi, cos, sin, tan, sqrt


def spiral(rin=10, pitch=2, Np=8, Nr=10):
dtheta = 2 * pi / Np
theta = pi / 2
pts = [(rin, 0), (rin, rin * tan(dtheta / 2))]
rin = rin * tan(dtheta / 2) * 2

x = rin
r = rin
for i in range(Np):
r += 1
theta += dtheta
x = x + r * cos(theta)
dr = pitch / (x - rin)

for i in range(Nr * Np - int(Np / 2) - 1):
rin += dr
theta += dtheta
x0, y0 = pts[-1]
x1, y1 = x0 + rin * cos(theta), y0 + rin * sin(theta)
pts.append((x1, y1))

pts.append((x1, 0))
return pts


from pyaedt import Desktop, Hfss, constants

with Desktop("2021.2", non_graphical=True):
hfss = Hfss(designname='A1')
hfss.modeler.model_units = "um"
p = hfss.modeler.primitives


def create_line(pts):
p.create_polyline(pts,
xsection_type='Rectangle',
xsection_width=width,
xsection_height=thickness, matname='copper')


pts = [(x0, y0, 0) for (x0, y0) in spiral(rin, (width + spacing), Np, Nr)]
create_line(pts)

x0, y0, z0 = pts[0]
x1, y1, z1 = pts[-1]

create_line([(x0 - width / 2, y0, -gap), (abs(x1) + 5, y0, -gap)])
p.create_rectangle(constants.PLANE.YZ,
(abs(x1) + 5, y0 - width / 2, -gap - thickness / 2),
(width, -Tsub + gap),
name='port1')
hfss.create_lumped_port_to_sheet(sheet_name='port1', axisdir=constants.AXIS.Z)

create_line([(x1 + width / 2, y1, 0), (x1 - 5, y1, 0)])
p.create_rectangle(constants.PLANE.YZ,
(x1 - 5, y1 - width / 2, -thickness / 2),
(width, -Tsub),
name='port2')
hfss.create_lumped_port_to_sheet(sheet_name='port2', axisdir=constants.AXIS.Z)

p.create_box((x0 - width / 2, y0 - width / 2, -gap - thickness / 2),
(width, width, gap + thickness),
matname='copper')
p.create_box([x1 - 20, x1 - 20, -Tsub - thickness / 2],
[-2 * x1 + 40, -2 * x1 + 40, Tsub],
matname='silicon')
p.create_box([x1 - 20, x1 - 20, -Tsub - thickness / 2],
[-2 * x1 + 40, -2 * x1 + 40, -0.1],
matname='PEC')

box = p.create_box([x1 - 20, x1 - 20, -Tsub - thickness / 2 - 0.1],
[-2 * x1 + 40, -2 * x1 + 40, 100],
name='airbox',
matname='air')

hfss.assign_radiation_boundary_to_objects('airbox')

hfss.change_material_override()
setup1 = hfss.create_setup(setupname='setup1')
setup1.props['Frequency'] = '10GHz'
hfss.create_frequency_sweep('setup1', 'GHz', 1e-3, 50)
setup1.update()
hfss.save_project()
hfss.analyze_all()

L_formula = '1e9*im(1/Y(1,1))/(2*pi*freq)'
f, m = [], []
x = hfss.post.get_report_data(L_formula)

for freq in x.solutions_data_real[L_formula]:
mag = x.solutions_data_real[L_formula][freq]
f.append(freq[0])
m.append(mag)

plt.plot(f, m)

plt.grid()
plt.xlabel('Freq')
plt.ylabel('L(nH)')
plt.show()

plt.clf()
L_formula = 'im(Y(1,1))/re(Y(1,1))'
f, m = [], []
x = hfss.post.get_report_data(L_formula)
hfss.save_project()
for freq in x.solutions_data_real[L_formula]:
mag = x.solutions_data_real[L_formula][freq]
f.append(freq[0])
m.append(-mag)

plt.plot(f, m)

plt.grid()
plt.xlabel('Freq')
plt.ylabel('Q')
plt.show()

hfss.save_project()


2021年12月11日 星期六

PCB傳輸線S參數萃取並繪圖

 匯入brd檔,切割,設ports,模擬並繪圖。

import matplotlib.pyplot as plt
from pyaedt import Desktop, Hfss3dLayout, examples, Edb

with Desktop("2021.2", non_graphical=True):
edb = Edb()
edb.import_cadence_file("d:/demo/Galileo_G87173_204.brd")
edb.core_hfss.create_coax_port_on_component(['U1B5', 'U2A5'], ['M_DQ<0>', 'M_DQ<1>'])

edb.core_components.set_solder_ball('U1B5')
edb.core_components.set_solder_ball('U2A5')

edb.create_cutout(['M_DQ<0>', 'M_DQ<1>'],
['GND'],
output_aedb_path='d:/demo/ddr.aedb',
open_cutout_at_end=False)
edb.close_edb()

h3d = Hfss3dLayout('d:/demo/ddr.aedb/edb.def')
setup1 = h3d.create_setup('setup1')
setup1.props['Frequency'] = '1GHz'
h3d.create_frequency_sweep('setup1', 'GHz', 0, 1, 11)
setup1.update()

h3d.analyze_all()
h3d.save_project()

for i in ["dB(S(4,1))", "dB(S(3,2))"]:
f, m = [], []
x = h3d.post.get_report_data(i)

for freq in x.solutions_data_mag[i]:
mag = x.solutions_data_mag[i][freq]
f.append(freq[0])
m.append(-mag)

plt.plot(f, m)

plt.grid()
plt.xlabel('Freq')
plt.ylabel('mag(dB)')
plt.show()


2021年12月10日 星期五

利用PyAEDT掃描不同長度dipole antenna並比較S參數

這一組掃描dipole antenna的範例程式從dipole建模,模擬設定,資料萃取到輸出圖,只用了40行程式碼,不用開AEDT GUI,就像是把AEDT當作一般的Python模組使用。減少繁複的操作及資料匯入匯出,大幅提高了工作效率。

import matplotlib.pyplot as plt
from pyaedt import Desktop, Hfss, constants

with Desktop("2021.2", non_graphical=True):
hfss = Hfss(designname='A1')
hfss['length'] = '50mm'

p = hfss.modeler.primitives
p.create_cylinder(constants.PLANE.XY, ('0mm', '0mm', '1mm'), '1mm', 'length', matname='copper')
p.create_cylinder(constants.PLANE.XY, ('0mm', '0mm', '-1mm'), '1mm', '-length', matname='copper')
p.create_rectangle(constants.PLANE.YZ, ('0mm', '-1mm', '-1mm'), ('2mm', '2mm'), name='sheet1')

hfss.create_lumped_port_to_sheet(sheet_name='sheet1', axisdir=constants.AXIS.Z)

setup1 = hfss.create_setup(setupname='setup1')
setup1.props['Frequency'] = '1GHz'
hfss.create_frequency_sweep('setup1', 'GHz', 1e-3, 3)
setup1.update()

hfss.create_open_region(Frequency='1GHz')

for l in ['40mm', '50mm', '60mm']:
hfss['length'] = l
hfss.analyze_all()

f, m = [], []
x = hfss.post.get_report_data("dB(S(1,1))")

for freq in x.solutions_data_mag['dB(S(1,1))']:
mag = x.solutions_data_mag['dB(S(1,1))'][freq]
f.append(freq[0])
m.append(-mag)

plt.plot(f, m)

plt.grid()
plt.xlabel('Freq')
plt.ylabel('mag(dB)')
plt.show()





EDB建立PinGroup

為U2A5建立GND PinGroup,儲存之後匯入EDB from pyaedt import Edb edb = Edb(edbpath= r"D:\demo\Galileo_G87173_20454.aedb" , edbversion= '20...