2022年7月17日 星期日

Q3D輸出Touchstone及SPICE模型

 

from pyaedt import Q3d
import string, random

design_name = ''.join(random.sample(string.ascii_lowercase, 10))

q3d = Q3d(designname=design_name)
q3d.change_validation_settings(skip_intersections=True)

faces = {}
q3d.modeler.delete(q3d.modeler.object_list)

x1 = q3d.modeler.create_box((-10, 0, 0), (20, 1, 1), matname='copper')
x2 = q3d.modeler.create_box((0, 0, 0), (1, 10, 1), matname='copper')
q3d.modeler.unite([x1, x2])
q3d.assign_net([x1], net_name='net_a', net_type='signal')
faces['net_a'] = [x1.top_face_x, x1.bottom_face_x, x1.top_face_y]

x3 = q3d.modeler.create_box((-10, -2, 0), (15, 1, 1), matname='copper')
x4 = q3d.modeler.create_box((-5, -2, 0), (1, 1, 5), matname='copper')
q3d.modeler.unite([x3, x4])
q3d.assign_net([x3], net_name='net_b', net_type='signal')
faces['net_b'] = [x3.top_face_x, x3.bottom_face_x, x3.top_face_z]

case = {'net_a': ['source', 'source', 'sink'],
'net_b': ['source', 'source', 'sink']}

for net in case:
for face, _type, name in zip(faces[net], case[net], ['_A', '_B', '_C']):
if _type == 'source':
q3d.assign_source_to_objectface(face, source_name=net + name, net_name=net)
if _type == 'sink':
q3d.assign_sink_to_objectface(face, sink_name=net + name, net_name=net)

x = q3d.create_setup()
y = x.add_sweep()
y.props['RangeStart'] = '0GHz'
y.props['RangeEnd'] = '1GHz'
y.props['RangeStep'] = '0.1GHz'
y.update()

q3d.analyze_nominal(num_cores=4)

data = q3d.post.get_solution_data('C(net_a,net_a)')
freqs = [1e9 * i for i in data.primary_sweep_values]

q3d.odesign.ExportNetworkData("", q3d.nominal_sweep, f"D:/demo/{design_name}.s6p", "Original", 50, freqs, "MagPhase", 0)

for freq in freqs:
q3d.oanalysis.ExportCircuit(q3d.nominal_sweep, "", f"D:/demo/{design_name}_{freq}.cir",
[
"NAME:CircuitData",
"MatrixName:=" , "Original",
"NumberOfCells:=" , "1",
"UserHasChangedSettings:=", True,
"IncludeCap:=" , True,
"IncludeCond:=" , True,
[
"NAME:CouplingLimits",
"CouplingLimitType:=" , "None"
],
"IncludeDCR:=" , False,
"IncudeDCL:=" , False,
"IncludeACR:=" , False,
"IncludeACL:=" , True,
"ADDResistance:=" , True,
"ParsePinNames:=" , False,
"IncludeCPP:=" , False,
[
"NAME:CPPInfo",
"PackageType:=" , "wirebond dieup",
"RelativeCS:=" , "",
"LengthUnits:=" , "mm",
[
"NAME:Pins"
]
]
], q3d.project_name, freq)

2022年7月16日 星期六

將Q3D匯出的cir檔案轉成TouchStone檔案

 

import re, os
from pyaedt import Circuit

circuit = Circuit(non_graphical=True, new_desktop_session='True', close_on_exit=True)


def cirtosnp(cir_path, fstart='0GHz', fstop='1GHz', fpoints=1001):
with open(cir_path) as f:
text = f.readlines()

ports = re.findall(r'\*\snode\s(\d+)\s+(.*)', '\n'.join(text))
snp_path = cir_path.replace('.cir', f'.s{len(ports)}p')
netlist = f'.inc "{cir_path}"\n\n'

for line in text:
if line.startswith('.subckt'):
_, cmp, *num = line.strip().split()
break

temp = ' '.join([i[1] for i in ports])
netlist += f'x1 {temp} {cmp}\n'
netlist_path = os.path.join(circuit.temp_directory, 'temp.cir')

with open(netlist_path, 'w') as f:
f.write(netlist)
circuit.add_netlist_datablock(netlist_path)

for port_id, port_name in ports:
circuit.modeler.components.create_interface_port(port_name)

setup1 = circuit.create_setup()
setup1.props["SweepDefinition"]["Data"] = f"LINC {fstart} {fstop} {fpoints}"
circuit.analyze_nominal()
circuit.export_touchstone(file_name=snp_path)
circuit.close_project()


cirtosnp("D:\demo\yqopvgihel_400000000.0.cir")

2022年5月26日 星期四

輸出一個專案當中所有設計的屬性值到CSV檔當中方便做比較

 


from pyaedt import Hfss

hfss = Hfss(specified_version='2022.1')

properties = {}
prop_list = []
for design in hfss.design_list:
properties[design] = {}
x = Hfss(projectname=hfss.project_name, designname=design)
props = x.odesign.GetProperties('LocalVariableTab', 'LocalVariables')
for i in props:
if i not in prop_list:
prop_list.append(i)
properties[design][i] = x.odesign.GetPropertyValue('LocalVariableTab', 'LocalVariables', i)

prop_list.sort()

with open('d:/demo/tabls.csv', 'w') as f:
f.writelines(','.join(hfss.design_list))
for p in prop_list:
row = [p]
for design in hfss.design_list:
try:
row.append(properties[design][p])
except:
row.append('NaN')
f.writelines(','.join(row) + '\n')



2022年5月22日 星期日

TDR 模擬

 執行Transient模擬,輸出tdr圖

#啟動非圖形模式
from pyaedt import Circuit
circuit = Circuit(non_graphical=True)

#網表內容
template = '''
.model diff_line S TSTONEFILE="D:/OneDrive - ANSYS, Inc/Models/S_Parameter/diff_line.s4p"
+ INTERPOLATION=LINEAR INTDATTYP=MA HIGHPASS=10 LOWPASS=10 convolution=0 enforce_passivity=0 Noisemodel=External

S2 net_1 net_2 net_3 net_4 FQMODEL="diff_line"
A3 net_2 net_1 COMPONENT=TDR_Differential_Ended enabled=1
R4 net_3 0 50
R7 net_4 0 50

.print TRAN V(*) O(*,z*)

.end
'''
#輸出template網表到檔案當中
with open('d:/demo/tdr.net', 'w') as f:
f.write(template)

#將網表加入到電路當中
oModule = circuit.add_netlist_datablock("D:/demo/tdr.net")

#加上Transient模擬設定並執行模擬
transient = circuit.create_setup('mytransient', circuit.SETUPS.NexximTransient)
transient.props['TransientData'] = ['0.1ns', '20ns']
circuit.analyse_nominal()

#取值並繪圖
data = circuit.post.get_solution_data('O(a3:zdiff)', domain='Time')
data.plot(math_formula='re')

#釋放license
circuit.release_desktop()


2022年5月21日 星期六

參數化結構範例

 

from math import sin, cos
from pyaedt import Q3d

q3d = Q3d(specified_version='2022.1', non_graphical=True)

q3d['r1'] = '150mm'
q3d['r2'] = '50mm'
q3d['dt'] = '1mm'
q3d['u_min'] = '-0.4*pi'
q3d['u_max'] = '0.4*pi'
q3d['du'] = 0.065
q3d['dr'] = '5mm'

q3d['v_min'] = '-0.3*pi'
q3d['v_max'] = '0.3*pi'
q3d['dv'] = 0.25

c1 = q3d.modeler.create_equationbased_curve('(r1+r2*cos(_t))*cos(u_min)', '(r1+r2*cos(_t))*sin(u_min)', 'r2*sin(_t)', 'v_min', 'v_max')
q3d.modeler.sweep_around_axis(c1, 2, 'u_max-u_min')
q3d.modeler.thicken_sheet(c1, 'dt')

spheres = []
for i in range(0, 100, 1):
for j in range(0, 10, 1):
x = f'if({i}*du+u_min<=u_max && {j}*dv+v_min<=v_max, (r1+r2*cos({j}*dv+v_min))*cos({i}*du+u_min), r1+r2*cos(v_min)*cos(u_min))'
y = f'if({i}*du+u_min<=u_max && {j}*dv+v_min<=v_max, (r1+r2*cos({j}*dv+v_min))*sin({i}*du+u_min), r1+r2*cos(v_min)*sin(u_min))'
z = f'if({i}*du+u_min<=u_max && {j}*dv+v_min<=v_max, r2*sin({j}*dv+v_min),r2*sin(v_min))'
s = q3d.modeler.create_sphere((x,y,z), 'dr')
s.color=(255,0,0)
spheres.append(s)

q3d.modeler.subtract(c1, spheres, False)
q3d.save_project('d:/demo/torus.aedt')
q3d.release_desktop()



不須啟動GUI執行PyAEDT電路模擬

 

#啟動非圖形模式
from pyaedt import Circuit
circuit = Circuit(non_graphical=True)

#輸出100級LC電路網表
with open('d:/demo/lc.net', 'w') as f:
for i in range(100):
f.writelines(f'L{i} net_{i} net_{i+1} 1e-9\n')
f.writelines(f'C{i} net_{i+1} 0 5e-12\n')

#將網表加入到電路當中
circuit.add_netlist_datablock('d:/demo/lc.net')

#加上ports
circuit.modeler.components.create_interface_port('net_0', (0,0))
circuit.modeler.components.create_interface_port('net_100', (0.01,0))

#加上模擬設定並執行模擬
lna = circuit.create_setup('mylna', circuit.SETUPS.NexximLNA)
lna.props['SweepDefinition']['Data']= 'LINC 0Hz 1GHz 101'
circuit.analyse_nominal()

#取值並繪圖
data = circuit.post.get_solution_data('db(Z11)')
data.plot(math_formula='re')

#釋放license
circuit.release_desktop()




2022年5月4日 星期三

生成帶有約束條件之線性規劃曲面

 

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

fig = plt.figure(figsize=(8,6))
ax3d = plt.axes(projection="3d")

def func(x, y):
result = (3*x+4*y)
return result

constraint = lambda x, y: (x+y<5)*(x+y>1)

xdata = np.linspace(0,3,100)
ydata = np.linspace(0,3,100)
X,Y = np.meshgrid(xdata,ydata)
Z = func(X, Y)/constraint(X, Y)


ax3d = plt.axes(projection='3d')
ax3d.plot_surface(X, Y, Z,cmap='jet')
ax3d.set_title('Surface Plot in Matplotlib')
ax3d.set_xlabel('X')
ax3d.set_ylabel('Y')
ax3d.set_zlabel('Z')

plt.show()



EDB建立PinGroup

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