2021年2月6日 星期六

如何選擇落在某個pad上面的bondwires

選擇位於'L1_pkg'層的Pin,執行下列腳本便可以選擇落在選中的Pin的所有Bondwires。這個功能可以用來協助開發分離bondwires腳位的工具(見上一篇)。

import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oLayout = oDesign.GetActiveEditor()

sele = oLayout.GetSelections()
AddWarningMessage(str(sele))
#polygon1 = oLayout.GetPolygon(sele[0])
toselect = []
for i in oLayout.FindObjects('Type', 'bondwire'):
p1 = oLayout.Point()
x, y = oLayout.GetPropertyValue('BaseElementTab',i, 'Pt1').split(',')
p1 = p1.Set(float(x)*1e-3 ,float(y)*1e-3)
obj = oLayout.FindObjectsByPoint(p1, 'L1_pkg')

if set(obj).intersection(set(sele)):
AddWarningMessage(str(i))
toselect.append(i)

oLayout.Select(toselect)

(圖一)選擇Pin,接著執行腳本


(圖二)落在被選中的Pin上的bondwires被選擇出來


Bondwire直線連接問題探索

有人問是否能自動調整bondwire pt2的位置,避免bondwire重疊導致網格失敗。所以先簡化成2D直線問題。在已知die端的座標點及pkg端的座標點且Npkg>=Ndie的前提下,採用隨機算法+交叉判斷,七條以內的直線不交叉配對可以在1sec內完成。雖然不代表bond-wires不會碰撞(因立體且有厚度),但是或許可以從這裡出發來探索一個可行的方法。 

from itertools import combinations
from math import sqrt
import random

w = 0.1


def getparallel(A, B, d):
x1, y1 = A
x2, y2 = B
r = sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)

deltax = (d / r) * (y1 - y2)
deltay = (d / r) * (x2 - x1)
x3 = x1 + deltax
y3 = y1 + deltay
x4 = x2 + deltax
y4 = y2 + deltay
return (x3, y3), (x4, y4)


def ccw(A, B, C):
Ax, Ay = A
Bx, By = B
Cx, Cy = C
return (Cy - Ay) * (Bx - Ax) > (By - Ay) * (Cx - Ax)


def intersect(A, B, C, D):
return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D)


def checkintersection(segments):
for (A, B), (C, D) in combinations(segments, 2):
_A, _B = getparallel(A, B, w / 2)
A_, B_ = getparallel(A, B, -w / 2)
_C, _D = getparallel(C, D, w / 2)
C_, D_ = getparallel(C, D, -w / 2)

if intersect(_A, _B, C_, D_) or intersect(A_, B_, _C, _D) or intersect(_A, B_, C_, _D) or intersect(A_, _B, _C,
D_):
return True
return False


import matplotlib.pyplot as plt

y0 = -2
die = [(0, i) for i in range(y0, y0 + 8)]
for i, j in die:
plt.scatter(i, j, marker='s')
x0, y0 = 3, 0
ds1 = [-1, -0.5, 0, 0.5]
ds2 = [-0.4, 0, 0.4, ]
pkg = [(x0 + i, y0 + j) for i in ds1 for j in ds2]

for i, j in pkg:
plt.scatter(i, j)

while (True):
segments = []
random.shuffle(pkg)
for (pt1, pt2) in zip(die, pkg[0:len(die)]):
segments.append((pt1, pt2))
if checkintersection(segments) == False:
break

for pt1, pt2 in segments:
x1, y1 = pt1
x2, y2 = pt2
plt.plot([x1, x2], [y1, y2])
plt.show()



2021年2月5日 星期五

如何簡化Python啟動步驟

不管是透過Run Script或ToolKit啟動python script都需要多個步驟。我們可以在Definitions/Script加入一段VB腳本,當中再呼叫Python Script。AEDT環境當中透過Run Script執行該VB就可以執行Python Script了。VB碼如下:


Dim oAnsoftApp

Dim oDesktop

Set oAnsoftApp = CreateObject("Ansoft.ElectronicsDesktop")

Set oDesktop = oAnsoftApp.GetAppDesktop()


oDesktop.RunScript("d:/demo/test.py")


(圖一)建立VB Script


(圖二)透過執行VB Script間接執行Python Script


HFSS Djordjevic Sarkar材料模型頻率變化公式字串輸出

多謝 Gregory, Liao的糾錯,程式計算的解果與HFSS完全一致。


from math import tan, pi, sqrt, atan, log, exp

'''
3.85309+0.0265244*ln((2.53303e+22+Freq*Freq)/(6.10915e+09+Freq*Freq))
1e-12+2.95123e-12*Freq*(atan(Freq/78161.1)-atan(Freq/1.59155e+11))
'''


def Djordjevic_Sarkar(dk=4, df=0.02, f0=10e9):
epson0 = 8.8541878128e-12
epson1 = dk
delta1 = df
f1 = f0
fb = 159.15494e9
sigma_dc = 1e-12

K = (epson1 * delta1 - sigma_dc / (2 * pi * f1 * epson0)) / atan(fb / f1)
epson_inf = epson1 - K * log(sqrt(fb ** 2 + f1 ** 2) / (f1))

delta_epson = 10 * delta1 * epson_inf
fa = fb / exp(delta_epson / K)

formula1 = '{:.5f}+{:.7f}*ln(({:.5e}+Freq*Freq)/({:.5e}+Freq*Freq))'.format(epson_inf, K / 2, fb ** 2, fa ** 2)
formula2 = '{}+{:.5e}*Freq*(atan(Freq/{:.5e})-atan(Freq/{:.5e}))'.format(sigma_dc, 2 * pi * epson0 * K, fa, fb)

return formula1, formula2


dk, df = Djordjevic_Sarkar()
print(dk)
print(df)

(圖一)輸出Dk, Df字串



2021年2月1日 星期一

找出特定目錄底下最早及最近被修改過的檔案

 import os

import datetime
import pathlib

data = []
for path, subdirs, files in os.walk(r'C:\Program Files\AnsysEM\AnsysEM20.2\Win64'):
for name in files:
fname = pathlib.Path(os.path.join(path, name))
mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime)
data.append((mtime, fname))
data.sort()
print(data[0])
print(data[-1])
輸出結果
D:\Customer2020\pythonProject1\venv\Scripts\python.exe D:/Customer2020/pythonProject1/main.py
(datetime.datetime(1999, 12, 31, 20, 0), WindowsPath('C:/Program Files/AnsysEM/AnsysEM20.2/Win64/common/ROMViewer/resources/app/services/System.Diagnostics.Process.dll'))
(datetime.datetime(2021, 1, 4, 9, 18, 48, 61165), WindowsPath('C:/Program Files/AnsysEM/AnsysEM20.2/Win64/syslib/Toolkits/Icepak/Geometry/Packages/DUAL.py'))

Process finished with exit code 0

2021年1月21日 星期四

如何在3D Layout當中生成陣列結構

import ScriptEnv


ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.GetActiveEditor()


def create_rect(x, y, w, l, layer):
x0, y0 = x - w / 2, y - l / 2
x1, y1 = x + w / 2, y + l / 2
objname = oEditor.CreateRectangle(
[
"NAME:Contents",
"rectGeometry:=",
["Name:=", "", "LayerName:=", layer, "lw:=", "0", "Ax:=", str(x0), "Ay:=", str(y0), "Bx:=", str(x1), "By:=",
str(y1), "cr:=", "0deg", "ang:=", "0deg"]
])

return objname


def build_array(obj_name, m, n, dx, dy):
obj_type = oEditor.GetPropertyValue('BaseElementTab', obj_name, 'Type')
old = oEditor.FindObjects('Type', obj_type)
oEditor.Duplicate(
[
"NAME:options",
"count:=" , m
],
[
"NAME:elements",
obj_name
], [dx, 0])
new = oEditor.FindObjects('Type', obj_type)
x = [obj_name] + list(set(new) -set(old))

oEditor.Duplicate(
[
"NAME:options",
"count:=" , n
],
["NAME:elements"] + x,
[0, dy])
new = oEditor.FindObjects('Type', obj_type)
return [obj_name] + list(set(new) -set(old))


def copytolayer(obj_list, layer_name):
oEditor.DuplicateAcrossLyrs(
["NAME:elements"] + obj_list,
[
"NAME:layers",
layer_name,
])


x = create_rect(0, 0, 1e-3, 1e-3, layer='top')
y = build_array(x, 5, 5, 2e-3, 2e-3)
copytolayer(y, 'bottom')
(圖一)多層陣列



2021年1月11日 星期一

如何處理大stp檔案

使用者提供了一個400MB的複雜機構stp檔,需要找出當中某些部件輸出到HFSS當中做模擬。正常狀況機構工程師應該只輸出實體物件到stp檔當中,但是這個stp檔並不是。該檔案當中包含了極多的輔助線以及輔助面,要在HFSS當中載入全部物件再從中篩選出所要的實體部件極為耗時(十幾個小時)。為了解決這個問題,我安裝了FreeCAD,當中提供了Python API。我寫了腳本先讀取stp檔,當中用函數輸出所有的實體部件(共600多個)並將其匯出到新的stp當中。最後載入stp到HFSS當中做操作即可。這時候要再設定就簡單多了。

從腳本讀取stp檔的實體物件到生成新的stp檔到最後匯入stp到HFSS,完成所有工作僅需20分鐘。環境為Python3.6版,在Anaconda當中執行。

import sys
sys.path.append('D:/Program Files/FreeCAD 0.18/bin')
import FreeCAD
import Part #載入Part模組

shape = Part.Shape()
shape.read('D:/demo/design.stp') #讀取stp

model = Part.makeCompound(shape.Solids) #solid部件轉成shape
model.exportStep('d:/demo12/final.stp') #shape輸出stp

(圖一) 匯入到HFSS的實體物件