CST-Python實例教程三:仿真并繪制結果
前言
在工程設計、求解計算的過程中,往往存在大量重復性的工作,這些工作不僅耗時耗力,而且容易出錯。為了提高工作效率,減少人為錯誤,我們希望這些重復性工作能夠被計算機自動完成,從而讓工程師從繁重的重復性勞動中解放出來,將更多的精力投入到創造性的工作中。
CST Studio Suite(R) 提供了 Python 編程接口,也提供了在 Python 環境中執行 VB 腳本的接口。并且,在 CST Studio Suite 2024 中,CST Python Libraries 的特性得到了更新。
廣州浦信系統技術有限公司發布的 CST Studio Suite(R) Python Automation and Scripting 系列文章,將會為您詳細介紹使用 Jupyter Notebook 連接到 CST Studio Suite 進行腳本控制與自動化仿真的方方面面。
現在,我們將使用 Jupyter Notebook 連接到 CST Studio Suite,通過一個演示案例,完成腳本控制建立模型、查看結果等工作,并在 Python 中進行更多自動化任務。
文章共分為5個部分,分別介紹以下內容:
搭建 Python 環境
控制 CST 建模
仿真并繪制結果
仿真優化
外部后處理
本期為第 3 篇文章,詳細介紹如何使用 Python 控制 CST 仿真、讀取結果以及繪圖。
一、準備工作
在此前的兩篇文章中,我們分享了搭建 Python 測試環境的流程,并完成了建模、求解器設置等工作。
現在,我們嘗試使用 Python 命令啟動求解器,對模型進行求解計算,并繪制計算結果。
本文后續的流程基于上一篇文章《控制 CST 建模》的模型操作,如果您保留了該模型,可以關聯文件后基于該模型繼續操作。如果您未保留上一次的 CST 工程,請參考上述文章中的步驟重新建模。
二、求解
運行求解
完成建模及求解器設置等工作后,即可進行求解計算。
運行下面代碼,求解器就會開始求解計算,可以打開軟件窗口查看仿真進度條。
mws_project.model3d.run_solver()
默認情況下,仿真結束時,命令run_solver()
才會返回 Python 環境。
如果需要定時返回 Python 環境,可以根據任務需要,在這里設置返回 Python 環境的超時時間。
保存結果
單元格執行后,等到求解器運行結束,即可運行以下代碼保存項目。
mws_project.save()
項目保存在此前手動設定的路徑中,如果未調整路徑,默認保存在當前用戶的TEMP
文件夾中,即C:\Users\<Users>\AppData\Local\Temp
訪問結果
為了訪問本次仿真的結果,我們使用了cst.results
庫。
result_project = cst.results.ProjectFile(tmp + r"\CST_TEST.cst")
若直接運行上述代碼,會出現報錯,提示該項目已被打開。
這是因為:在默認的情況下,當前在 CST Studio Suite 中打開的項目的結果,無法被外部訪問。
要訪問結果,我們需要做一些措施:
可以使用
mws_project.close()
關閉項目,在工程文件被關閉的狀態下訪問仿真結果。或者使用
allow_interactive=True
參數取消訪問限制。
以下為使用 allow_interactive=True
的命令:
result_project = cst.results.ProjectFile(tmp + r"\CST_TEST.cst", allow_interactive=True)
三、后處理
在這里,我們使用 Python 讀取本次仿真的結果,并進行繪圖,分別繪制“場”的結果和“路”的結果。
后處理需要用到IPython
庫,請確保IPython
安裝且工作正常。
繪制場的結果
在場的仿真中,我們通過左側的 Navigation Tree 導航到仿真結果中。我們也可以使用 Python 對場的仿真結果進行后處理。
為了在 Python 中進行進一步的后處理,我們現在將選定的結果加載到 Python 變量中。
s11 = result_project.get_3d().get_result_item("1D Results\S-Parameters\S1,1")TD_in = result_project.get_3d().get_result_item("1D Results\Port signals\i1")TD_ref = result_project.get_3d().get_result_item("1D Results\Port signals\o1,1")
可以使用 Python 中的type()
函數檢查結果類型(如int
、str
、list
等)。
type(TD_in)
顯示仿真結果的數據類型為:_cst_results.ResultItem
由于這是一種相當特殊的格式,我們需要將結果提取出來,并存儲到一個標準數組中,這樣就可以對數據執行 FFT、IFFT 等運算操作。
運行以下代碼轉存數據。
ss = np.asarray([s11.get_xdata() , s11.get_ydata()])tt = np.asarray([TD_in.get_xdata() , TD_in.get_ydata()])tt2 = np.asarray([TD_ref.get_xdata() , TD_ref.get_ydata()])ss[0,:].real
下面進行圖像繪制。
S參數(幅度相位)
%matplotlib inlineplt.figure(figsize=(9,5))plt.plot(s11.get_xdata(),20*np.log10(np.absolute(np.asarray(s11.get_ydata()))))plt.title('S-Parameter Magnitude')plt.ylabel('Mag in dB')plt.xlabel('Freq. in GHz')plt.grid(True)plt.ylim((-38,-18))plt.xlim((8,10))plt.figure(figsize=(9,5))plt.plot(s11.get_xdata(),np.angle(np.asarray(s11.get_ydata()),deg=True))plt.title('S-Parameter Phase')plt.ylabel('Phase in deg')plt.xlabel('Freq. in GHz')plt.grid(True)plt.ylim((-180,180))plt.xlim((8,10))
時域信號
查看時域激勵的入射信號和反射信號。
%matplotlib inlineplt.ion()plt.figure(figsize=(9,5))plt.plot(TD_in.get_xdata(),TD_in.get_ydata())plt.title('TD In ')plt.ylabel('Amp')plt.xlabel('Time in ns')plt.grid(True)plt.figure(figsize=(9,5))plt.plot(TD_ref.get_xdata(),TD_ref.get_ydata())plt.title('TD ref ')plt.ylabel('Amp')plt.xlabel('Time in ns')plt.grid(True)
頻域轉換
將時域信號進行快速傅里葉變換,并繪制圖像,查看信號的頻域分布。
td_fft=np.fft.fft(tt,n=10*len(tt[0]),axis=1)td2_fft=np.fft.fft(tt2,n=10*len(tt2[0]),axis=1)freq = np.fft.fftfreq(10*len(tt2[0]), tt2[0,1] - tt2[0,0])plt.figure(figsize=(9,5))plt.xlabel('Freq. in GHz')plt.title('FFT of TD In & TD_ref ')plt.grid(True)plt.ylim((0,0.5))plt.xlim((6,12))plt.plot(freq,abs(td_fft[1])*(tt[0,1] - tt[0,0]))plt.plot(freq,abs(td2_fft[1])*(tt2[0,1] - tt2[0,0]))
繪制原理圖結果
到目前為止,我們只研究了場的仿真結果。當然,我們也可以使用 Python 在原理圖中進行后處理(即查看路的結果)。
設置外部端口
運行下面代碼,將外部端口連接到 Python 環境(即 Jupyter Notebook 項目)中,并進行端口設置。
prj_schematic = mws_project.schematicprj_external_port = prj_schematic.ExternalPortprj_block = prj_schematic.Blockprj_net = prj_schematic.Net# Set up external ports...prj_external_port.Reset()prj_external_port.Name("1")prj_external_port.Position(49850, 49950)prj_external_port.Create()prj_external_port.Reset()prj_external_port.Name("2")prj_external_port.Position(49850, 50020)prj_external_port.Create()prj_external_port.Reset()prj_external_port.Name("3")prj_external_port.Position(50325, 49950)prj_external_port.Create()# Connect external portsconnections = [[0 for x in range(3)] for y in range(2)]connections[0][0] = "Block"connections[0][1] = "MWSSCHEM1"connections[0][2] = 0connections[1][0] = "Externalport"connections[1][1] = "1"connections[1][2] = 0prj_net.Reset()prj_net.AddComponentPorts("", connections, False)prj_net.Apply()connections[0][0] = "Block"connections[0][1] = "MWSSCHEM1"connections[0][2] = 1connections[1][0] = "Externalport"connections[1][1] = "2"connections[1][2] = 0prj_net.Reset()prj_net.AddComponentPorts("", connections, False)prj_net.Apply()connections[0][0] = "Block"connections[0][1] = "MWSSCHEM1"connections[0][2] = 2connections[1][0] = "Externalport"connections[1][1] = "3"connections[1][2] = 0prj_net.Reset()prj_net.AddComponentPorts("", connections, False)prj_net.Apply()
當然,更有效的方法是直接調用相應的宏,會產生同樣的端口設置效果,而且會快很多。
prj_schematic.RunMacro("Construct\Add Ports to all pins of a block")
這一步對應的 GUI 操作流程如下圖所示:首先切換到原理圖界面,隨后在 VBA Marcos 中選擇“Construct”,打開“Add Ports to all pins of a block”。
計算Z參數
現在,外部端口已經定義并連接完畢,讓我們快速設置并執行 Z 參數任務。
# set up S-parameter taskprj_sim_task = prj_schematic.SimulationTask# create taskprj_sim_task.Reset()prj_sim_task.Type("S-Parameters")prj_sim_task.Name("ZPara1")prj_sim_task.SetProperty("maximum frequency range", "True")prj_sim_task.Create()# request Z-parameters and set port impedanceprj_sim_task.SetResultOption("Z-Parameters", "On (Parametric)")# and updateprj_sim_task.Update()
結果繪圖
使用繪制場的結果時相同的基本方法,可以獲得 Z 參數結果。
z11_schem = result_project.get_schematic().get_result_item(r"Tasks\ZPara1\Z-Parameters\Z1,1")z11 = np.transpose(np.asarray([z11_schem.get_xdata(), z11_schem.get_ydata()]))%matplotlib inlineplt.figure(figsize=(9,5))plt.plot(z11[:,0].real, np.abs(z11[:,1]))plt.title('Z-Parameter Magnitude')plt.ylabel('Magnitude (linear)')plt.xlabel('Freq. in GHz')plt.grid(True)plt.xlim((8,10))plt.semilogy()
總結
場的結果和路的結果,對應的操作對象不同,因此需要分別編寫程序繪制。
在測試過程中,如遇到 IPython 相關的警告或報錯,可以考慮將
%matplotlib notebook
替換成%matplotlib inline
。