首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >CST_with_Python(三):仿真并绘制结果

CST_with_Python(三):仿真并绘制结果

原创
作者头像
浦信仿真大讲堂
修改2026-06-09 10:45:36
修改2026-06-09 10:45:36
10
举报

前言

在工程设计、求解计算的过程中,往往存在大量重复性的工作,这些工作不仅耗时耗力,而且容易出错。为了提高工作效率,减少人为错误,我们希望这些重复性工作能够被计算机自动完成,从而让工程师从繁重的重复性劳动中解放出来,将更多的精力投入到创造性的工作中。

CST Studio Suite® 提供了 Python 编程接口,也提供了在 Python 环境中执行 VB 脚本的接口。并且,在 CST Studio Suite 2024 中,CST Python Libraries 的特性得到了更新。

现在,我们将使用 Jupyter Notebook 连接到 CST Studio Suite,通过一个演示案例,完成脚本控制建立模型、查看结果等工作,并在 Python 中进行更多自动化任务。

文章共分为5个部分,分别介绍以下内容:

  1. 搭建 Python 环境
  2. 控制 CST 建模
  3. 仿真并绘制结果
  4. 仿真优化
  5. 外部后处理

本期为第 3 篇文章,详细介绍如何使用 Python 控制 CST 仿真、读取结果以及绘图。

一、准备工作

在此前的两篇文章中,我们分享了搭建 Python 测试环境的流程,并完成了建模、求解器设置等工作。

现在,我们尝试使用 Python 命令启动求解器,对模型进行求解计算,并绘制计算结果。

图片
图片

求解器为T求解器,频率范围8-10GHz

本文后续的流程基于上一篇文章《控制 CST 建模》的模型操作,如果您保留了该模型,可以关联文件后基于该模型继续操作。如果您未保留上一次的 CST 工程,请参考上述文章中的步骤重新建模。

二、求解

运行求解

完成建模及求解器设置等工作后,即可进行求解计算。

运行下面代码,求解器就会开始求解计算,可以打开软件窗口查看仿真进度条。

代码语言:javascript
复制
mws_project.model3d.run_solver()
图片
图片

求解器求解中

默认情况下,仿真结束时,命令run_solver()才会返回 Python 环境。

如果需要定时返回 Python 环境,可以根据任务需要,在这里设置返回 Python 环境的超时时间。

保存结果

单元格执行后,等到求解器运行结束,即可运行以下代码保存项目。

代码语言:javascript
复制
mws_project.save()

项目保存在此前手动设定的路径中,如果未调整路径,默认保存在当前用户的TEMP文件夹中,即C:\Users\<Users>\AppData\Local\Temp

访问结果

为了访问本次仿真的结果,我们使用了cst.results库。

代码语言:javascript
复制
result_project = cst.results.ProjectFile(tmp + r"\CST_TEST.cst")

若直接运行上述代码,会出现报错,提示该项目已被打开。

图片
图片

提示该项目已被打开

这是因为:在默认的情况下,当前在 CST Studio Suite 中打开的项目的结果,无法被外部访问。

要访问结果,我们需要做一些措施:

  • 可以使用mws_project.close()关闭项目,在工程文件被关闭的状态下访问仿真结果。
  • 或者使用 allow_interactive=True 参数取消访问限制。

以下为使用 allow_interactive=True 的命令:

代码语言:javascript
复制
result_project = cst.results.ProjectFile(tmp + r"\CST_TEST.cst", allow_interactive=True)
图片
图片

allow_interactive=True运行结果

三、后处理

在这里,我们使用 Python 读取本次仿真的结果,并进行绘图,分别绘制“场”的结果和“路”的结果。

后处理需要用到IPython库,请确保IPython安装且工作正常。

绘制场的结果

在场的仿真中,我们通过左侧的 Navigation Tree 导航到仿真结果中。我们也可以使用 Python 对场的仿真结果进行后处理。

图片
图片

在GUI中查看“场”的结果

为了在 Python 中进行进一步的后处理,我们现在将选定的结果加载到 Python 变量中。

代码语言:javascript
复制
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()函数检查结果类型(如intstrlist等)。

代码语言:javascript
复制
type(TD_in)

显示仿真结果的数据类型为:_cst_results.ResultItem

图片
图片

仿真结果的数据类型

由于这是一种相当特殊的格式,我们需要将结果提取出来,并存储到一个标准数组中,这样就可以对数据执行 FFT、IFFT 等运算操作。

运行以下代码转存数据。

代码语言:javascript
复制
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参数(幅度相位)

代码语言:javascript
复制
%matplotlib inline
plt.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))   
图片
图片

S11幅度和相位

时域信号

查看时域激励的入射信号和反射信号。

代码语言:javascript
复制
%matplotlib inline
plt.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)
图片
图片

入射波和反射波的时域分布

频域转换

将时域信号进行快速傅里叶变换,并绘制图像,查看信号的频域分布。

代码语言:javascript
复制
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 在原理图中进行后处理(即查看路的结果)。

图片
图片

在GUI中查看“路”的结果

设置外部端口

运行下面代码,将外部端口连接到 Python 环境(即 Jupyter Notebook 项目)中,并进行端口设置。

代码语言:javascript
复制
prj_schematic = mws_project.schematic
prj_external_port = prj_schematic.ExternalPort
prj_block = prj_schematic.Block
prj_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 ports
connections = [[0 for x in range(3)] for y in range(2)]
connections[0][0] = "Block"
connections[0][1] = "MWSSCHEM1"
connections[0][2] = 0
connections[1][0] = "Externalport"
connections[1][1] = "1"
connections[1][2] = 0

prj_net.Reset()
prj_net.AddComponentPorts("", connections, False)
prj_net.Apply()

connections[0][0] = "Block"
connections[0][1] = "MWSSCHEM1"
connections[0][2] = 1
connections[1][0] = "Externalport"
connections[1][1] = "2"
connections[1][2] = 0

prj_net.Reset()
prj_net.AddComponentPorts("", connections, False)
prj_net.Apply()

connections[0][0] = "Block"
connections[0][1] = "MWSSCHEM1"
connections[0][2] = 2
connections[1][0] = "Externalport"
connections[1][1] = "3"
connections[1][2] = 0

prj_net.Reset()
prj_net.AddComponentPorts("", connections, False)
prj_net.Apply()

当然,更有效的方法是直接调用相应的宏,会产生同样的端口设置效果,而且会快很多。

代码语言:javascript
复制
prj_schematic.RunMacro("Construct\Add Ports to all pins of a block")

这一步对应的 GUI 操作流程如下图所示:首先切换到原理图界面,随后在 VBA Marcos 中选择“Construct”,打开“Add Ports to all pins of a block”。

图片
图片

在GUI中设置外部端口

计算Z参数

现在,外部端口已经定义并连接完毕,让我们快速设置并执行 Z 参数任务。

代码语言:javascript
复制
# set up S-parameter task
prj_sim_task = prj_schematic.SimulationTask

# create task
prj_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 impedance
prj_sim_task.SetResultOption("Z-Parameters", "On (Parametric)")

# and update
prj_sim_task.Update()

结果绘图

使用绘制场的结果时相同的基本方法,可以获得 Z 参数结果。

代码语言:javascript
复制
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 inline
plt.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()
图片
图片

Z参数

总结

  1. 场的结果和路的结果,对应的操作对象不同,因此需要分别编写程序绘制。
  2. 在测试过程中,如遇到 IPython 相关的警告或报错,可以考虑将 %matplotlib notebook 替换成 %matplotlib inline

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、准备工作
  • 二、求解
    • 运行求解
    • 保存结果
    • 访问结果
  • 三、后处理
    • 绘制场的结果
      • S参数(幅度相位)
      • 时域信号
      • 频域转换
    • 绘制原理图结果
      • 设置外部端口
      • 计算Z参数
      • 结果绘图
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档