CST-Python實例教程三:仿真并繪制結(jié)果
前言
在工程設(shè)計、求解計算的過程中,往往存在大量重復(fù)性的工作,這些工作不僅耗時耗力,而且容易出錯。為了提高工作效率,減少人為錯誤,我們希望這些重復(fù)性工作能夠被計算機自動完成,從而讓工程師從繁重的重復(fù)性勞動中解放出來,將更多的精力投入到創(chuàng)造性的工作中。
CST Studio Suite(R) 提供了 Python 編程接口,也提供了在 Python 環(huán)境中執(zhí)行 VB 腳本的接口。并且,在 CST Studio Suite 2024 中,CST Python Libraries 的特性得到了更新。
廣州浦信系統(tǒng)技術(shù)有限公司發(fā)布的 CST Studio Suite(R) Python Automation and Scripting 系列文章,將會為您詳細介紹使用 Jupyter Notebook 連接到 CST Studio Suite 進行腳本控制與自動化仿真的方方面面。
現(xiàn)在,我們將使用 Jupyter Notebook 連接到 CST Studio Suite,通過一個演示案例,完成腳本控制建立模型、查看結(jié)果等工作,并在 Python 中進行更多自動化任務(wù)。
文章共分為5個部分,分別介紹以下內(nèi)容:
搭建 Python 環(huán)境
控制 CST 建模
仿真并繪制結(jié)果
仿真優(yōu)化
外部后處理
本期為第 3 篇文章,詳細介紹如何使用 Python 控制 CST 仿真、讀取結(jié)果以及繪圖。
一、準備工作
在此前的兩篇文章中,我們分享了搭建 Python 測試環(huán)境的流程,并完成了建模、求解器設(shè)置等工作。
現(xiàn)在,我們嘗試使用 Python 命令啟動求解器,對模型進行求解計算,并繪制計算結(jié)果。
本文后續(xù)的流程基于上一篇文章《控制 CST 建模》的模型操作,如果您保留了該模型,可以關(guān)聯(lián)文件后基于該模型繼續(xù)操作。如果您未保留上一次的 CST 工程,請參考上述文章中的步驟重新建模。
二、求解
運行求解
完成建模及求解器設(shè)置等工作后,即可進行求解計算。
運行下面代碼,求解器就會開始求解計算,可以打開軟件窗口查看仿真進度條。
mws_project.model3d.run_solver()
默認情況下,仿真結(jié)束時,命令run_solver()
才會返回 Python 環(huán)境。
如果需要定時返回 Python 環(huán)境,可以根據(jù)任務(wù)需要,在這里設(shè)置返回 Python 環(huán)境的超時時間。
保存結(jié)果
單元格執(zhí)行后,等到求解器運行結(jié)束,即可運行以下代碼保存項目。
mws_project.save()
項目保存在此前手動設(shè)定的路徑中,如果未調(diào)整路徑,默認保存在當(dāng)前用戶的TEMP
文件夾中,即C:\Users\<Users>\AppData\Local\Temp
訪問結(jié)果
為了訪問本次仿真的結(jié)果,我們使用了cst.results
庫。
result_project = cst.results.ProjectFile(tmp + r"\CST_TEST.cst")
若直接運行上述代碼,會出現(xiàn)報錯,提示該項目已被打開。
這是因為:在默認的情況下,當(dāng)前在 CST Studio Suite 中打開的項目的結(jié)果,無法被外部訪問。
要訪問結(jié)果,我們需要做一些措施:
可以使用
mws_project.close()
關(guān)閉項目,在工程文件被關(guān)閉的狀態(tài)下訪問仿真結(jié)果。或者使用
allow_interactive=True
參數(shù)取消訪問限制。
以下為使用 allow_interactive=True
的命令:
result_project = cst.results.ProjectFile(tmp + r"\CST_TEST.cst", allow_interactive=True)
三、后處理
在這里,我們使用 Python 讀取本次仿真的結(jié)果,并進行繪圖,分別繪制“場”的結(jié)果和“路”的結(jié)果。
后處理需要用到IPython
庫,請確保IPython
安裝且工作正常。
繪制場的結(jié)果
在場的仿真中,我們通過左側(cè)的 Navigation Tree 導(dǎo)航到仿真結(jié)果中。我們也可以使用 Python 對場的仿真結(jié)果進行后處理。
為了在 Python 中進行進一步的后處理,我們現(xiàn)在將選定的結(jié)果加載到 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()
函數(shù)檢查結(jié)果類型(如int
、str
、list
等)。
type(TD_in)
顯示仿真結(jié)果的數(shù)據(jù)類型為:_cst_results.ResultItem
由于這是一種相當(dāng)特殊的格式,我們需要將結(jié)果提取出來,并存儲到一個標準數(shù)組中,這樣就可以對數(shù)據(jù)執(zhí)行 FFT、IFFT 等運算操作。
運行以下代碼轉(zhuǎn)存數(shù)據(jù)。
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參數(shù)(幅度相位)
%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)
頻域轉(zhuǎn)換
將時域信號進行快速傅里葉變換,并繪制圖像,查看信號的頻域分布。
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]))
繪制原理圖結(jié)果
到目前為止,我們只研究了場的仿真結(jié)果。當(dāng)然,我們也可以使用 Python 在原理圖中進行后處理(即查看路的結(jié)果)。
設(shè)置外部端口
運行下面代碼,將外部端口連接到 Python 環(huán)境(即 Jupyter Notebook 項目)中,并進行端口設(shè)置。
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()
當(dāng)然,更有效的方法是直接調(diào)用相應(yīng)的宏,會產(chǎn)生同樣的端口設(shè)置效果,而且會快很多。
prj_schematic.RunMacro("Construct\Add Ports to all pins of a block")
這一步對應(yīng)的 GUI 操作流程如下圖所示:首先切換到原理圖界面,隨后在 VBA Marcos 中選擇“Construct”,打開“Add Ports to all pins of a block”。
計算Z參數(shù)
現(xiàn)在,外部端口已經(jīng)定義并連接完畢,讓我們快速設(shè)置并執(zhí)行 Z 參數(shù)任務(wù)。
# 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()
結(jié)果繪圖
使用繪制場的結(jié)果時相同的基本方法,可以獲得 Z 參數(shù)結(jié)果。
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()
總結(jié)
場的結(jié)果和路的結(jié)果,對應(yīng)的操作對象不同,因此需要分別編寫程序繪制。
在測試過程中,如遇到 IPython 相關(guān)的警告或報錯,可以考慮將
%matplotlib notebook
替換成%matplotlib inline
。