|
OpenEMS 免费开源的电磁场求解器
“ openEMS 是一个使用 FDTD 方法的开源电磁场求解器。可以通过 Matlab、Octave 或 Python 接口调用。 ”
简介openEMS 是一款基于有限差分时域 (FDTD) 方法的免费开源电磁场求解器。它使用了 FDTD 方法的改进版本(称为等效电路 FDTD 或 EC-FDTD),在离散空间和时间中求解麦克斯韦方程,以三维全波方式直接模拟电磁波的传播。它具有分析射频/微波电路设计、天线、雷达、元材料和医学研究等重要应用问题的潜力。该引擎用 C++ 编写,通过一套广泛的 Matlab/Octave 或 Python 接口定义仿真,编程灵活。一个单独的库 CSXCAD 也是 openEMS 项目的一部分,用于处理 FDTD 仿真中使用的几何图形。为了帮助编程,还为 CSXCAD 提供了一个简单的图形用户界面,称为 AppCSXCAD,用于检查 3D 模型。该项目由杜伊斯堡-埃森大学通用和理论电气工程(ATE)实验室的 Thorsten Liebig 于 2010 年 2 月启动和维护。openEMS 采用 GNU 通用公共许可证第 3 版或更高版本,CSXCAD 采用 GNU 宽通用公共许可证第 3 版或更高版本。 openEMS的仓库及文档: 文档: https://docs.openEMS.de
Github: https://github.com/thliebig/openEMS-Project
主要功能 三维笛卡尔坐标(x,y,z)和柱坐标(ρ, φ, z)。 全分级网格。 子网格可减少柱坐标的模拟时间 吸收边界条件(MUR、PML) vtk 或 hdf5 文件格式的时域和频域场转储 用于天线仿真的近场到远场(NF2FF)变换。 坐标相关材料定义 坐标相关激励定义(例如模式分布) Matlab/Octave 和 Python 接口 灵活的后处理例程(主要在 Matlab/Octave 中进行) 多线程、SIMD(SSE)和 MPI 支持并行 FDTD。 跨平台支持,包括 Linux、FreeBSD、macOS 和 Windows,并已在 x86、ARM 和 POWER9 CPU 上成功构建。
示例2.4 G 简易平面天线(Simple Patch Antenna) 示例包含以下内容:
设置平面(贴片)、基板和接地。 设置叠加馈电端口。 添加近场到远场(nf2ff)记录盒。 计算天线的 S 参数。 计算并绘制远场图案
导入库- imp
- ort
- os, tempfile
- from pylab
- import
- *
- from
- CSXCAD
- import
- ContinuousStructure
- from openEMS
- import
- openEMS
- from openEMS.physical_constants
- import
- *
复制代码
通用参数设置- Sim_Path = os.path.join(tempfile.gettempdir(), 'Simp_Patch')
- post_proc_only = False
- # patch width (resonant length) in x-direction
- patch_width = 32
- #
- # patch length in y-direction
- patch_length = 40
- #substrate setup
- substrate_epsR = 3.38
- substrate_kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate_epsR
- substrate_width = 60
- substrate_length = 60
- substrate_thickness = 1.524
- substrate_cells = 4
- #setup feeding
- feed_pos = -6
- #feeding position in x-direction
- feed_R = 50
- #feed resistance
- # size of the simulation box
- SimBox = np.array([200, 200, 150])
- # setup FDTD parameter & excitation function
- f0 = 2e9
- # center frequency
- fc = 1e9
- # 20 dB corner frequency
复制代码
FDTD设置 将仿真限制为 30k 个时间步长 定义-40 分贝的降低结束标准
- FDTD = openEMS(NrTS=30000, EndCriteria=1e-4)
- FDTD.SetGaussExcite( f0,
- fc
- )
- FDTD.SetBoundaryCond( [
- 'MUR'
- ,
- 'MUR'
- ,
- 'MUR'
- ,
- 'MUR'
- ,
- 'MUR'
- ,
- 'MUR'
- ] )
- CSX = ContinuousStructure()
- FDTD.SetCSX(CSX)
- mesh = CSX.GetGrid()
- mesh.SetDeltaUnit(1e-3)
- mesh_res = C0/(f0+
- fc
- )/1e-3/20
复制代码
生成属性、基元和网格- #initialize the mesh with the "air-box" dimensions
- mesh.AddLine('x', [-SimBox[0]/2, SimBox[0]/2])
- mesh.AddLine('y', [-SimBox[1]/2, SimBox[1]/2] )
- mesh.AddLine('z', [-SimBox[2]/3, SimBox[2]*2/3] )
- # create patch
- patch = CSX.AddMetal( 'patch' )
- # create a perfect electric conductor (PEC)
- start = [-patch_width/2, -patch_length/2, substrate_thickness]
- stop = [ patch_width/2 , patch_length/2, substrate_thickness]
- patch.AddBox(priority=10, start=start, stop=stop)
- # add a box-primitive to the metal property 'patch'
- FDTD.AddEdges2Grid(dirs='xy', properties=patch, metal_edge_res=mesh_res/2)
- # create substrate
- substrate = CSX.AddMaterial( 'substrate', epsilon=substrate_epsR, kappa=substrate_kappa)
- start = [-substrate_width/2, -substrate_length/2, 0]
- stop = [ substrate_width/2, substrate_length/2, substrate_thickness]
- substrate.AddBox( priority=0, start=start, stop=stop )
- # add extra cells to discretize the substrate thickness
- mesh.AddLine('z', linspace(0,substrate_thickness,substrate_cells+1))
- # create ground (same size as substrate)
- gnd = CSX.AddMetal( 'gnd' )
- # create a perfect electric conductor (PEC)
- start[2]=0
- stop[2] =0
- gnd.AddBox(start, stop, priority=10)
- FDTD.AddEdges2Grid(dirs='xy', properties=gnd)
- # apply the excitation & resist as a current source
- start = [feed_pos, 0, 0]
- stop = [feed_pos, 0, substrate_thickness]
- port = FDTD.AddLumpedPort(1, feed_R, start, stop, 'z', 1.0, priority=5, edges2grid='xy')
- mesh.SmoothMeshLines('all', mesh_res, 1.4)
- # Add the nf2ff recording box
- nf2ff = FDTD.CreateNF2FFBox()
复制代码
运行仿真- if
- 0
- :
- # debugging only
- CSX_file = os.path.join(Sim_Path,
- 'simp_patch.xml'
- )
- if
- not
- os.path.exists(Sim_Path):
- os.mkdir(Sim_Path)
- CSX.Write2XML(CSX_file)
- from
- CSXCAD
- import
- AppCSXCAD_BIN
- os.system(AppCSXCAD_BIN +
- ' "{}"'
- .format(CSX_file))
- if
- not
- post_proc_only:
- FDTD.Run(Sim_Path, verbose=
- 3
- , cleanup=
- True
- )
复制代码
后处理和绘图 - f = np.linspace(max(
- 1e9
- ,f0-fc),f0+fc,
- 401
- )
- port.CalcPort(Sim_Path, f)
- s11 = port.uf_ref/port.uf_inc
- s11_dB =
- 20.0
- *np.log10(np.abs(s11))
- figure()
- plot(f/
- 1e9
- , s11_dB,
- 'k-'
- , linewidth=
- 2
- , label=
- '$S_{11}
- [align=left]生成的图形[/align][align=left]
[/align][align=left]
[/align]
[align=left]文档及 Q&A[/align][list]
- [*][p=24, null, left]https://wiki.openems.de/index.php/Main_Page.html[/p]
- [*][p=24, null, left]https://github.com/thliebig/openEMS-Project/discussions[/p]
- [/list]FDTD 教程:https://eecs.wsu.edu/~schneidj/ufdtd/index.php
- )
- grid()
- legend()
- ylabel(
- 'S-Parameter (dB)'
- )
- xlabel(
- 'Frequency (GHz)'
- )
- idx = np.where((s11_dB<
- -10
- ) & (s11_dB==np.min(s11_dB)))[
- 0
- ]
- if
- not
- len
- (idx)==
- 1
- :
- print
- (
- 'No resonance frequency found for far-field calulation'
- )
- else
- :
- f_res = f[idx[
- 0
- ]]
- theta = np.arange(
- -180.0
- ,
- 180.0
- ,
- 2.0
- )
- phi = [
- 0.
- ,
- 90.
- ]
- nf2ff_res = nf2ff.CalcNF2FF(Sim_Path, f_res, theta, phi, center=[
- 0
- ,
- 0
- ,
- 1e-3
- ])
- figure()
- E_norm =
- 20.0
- *np.log10(nf2ff_res.E_norm[
- 0
- ]/np.max(nf2ff_res.E_norm[
- 0
- ])) + nf2ff_res.Dmax[
- 0
- ]
- plot(theta, np.squeeze(E_norm[:,
- 0
- ]),
- 'k-'
- , linewidth=
- 2
- , label=
- 'xz-plane'
- )
- plot(theta, np.squeeze(E_norm[:,
- 1
- ]),
- 'r--'
- , linewidth=
- 2
- , label=
- 'yz-plane'
- )
- grid()
- ylabel(
- 'Directivity (dBi)'
- )
- xlabel(
- 'Theta (deg)'
- )
- title(
- 'Frequency: {} GHz'
- .format(f_res/
- 1e9
- ))
- legend()
- Zin = port.uf_tot/port.if_tot
- figure()
- plot(f/
- 1e9
- , np.
- real
- (Zin),
- 'k-'
- , linewidth=
- 2
- , label=
- '$\Re\{Z_{in}\}
- [align=left]生成的图形[/align][align=left]
[/align][align=left]
[/align]
[align=left]文档及 Q&A[/align][list]
- [*][p=24, null, left]https://wiki.openems.de/index.php/Main_Page.html[/p]
- [*][p=24, null, left]https://github.com/thliebig/openEMS-Project/discussions[/p]
- [/list]FDTD 教程:https://eecs.wsu.edu/~schneidj/ufdtd/index.php
- )
- plot(f/
- 1e9
- , np.
- imag
- (Zin),
- 'r--'
- , linewidth=
- 2
- , label=
- '$\Im\{Z_{in}\}
- [align=left]生成的图形[/align][align=left]
[/align][align=left]
[/align]
[align=left]文档及 Q&A[/align][list]
- [*][p=24, null, left]https://wiki.openems.de/index.php/Main_Page.html[/p]
- [*][p=24, null, left]https://github.com/thliebig/openEMS-Project/discussions[/p]
- [/list]FDTD 教程:https://eecs.wsu.edu/~schneidj/ufdtd/index.php
- )
- grid()
- legend()
- ylabel(
- 'Zin (Ohm)'
- )
- xlabel(
- 'Frequency (GHz)'
- )
- show()
复制代码
生成的图形
文档及 Q&A FDTD 教程:https://eecs.wsu.edu/~schneidj/ufdtd/index.php
|
+10
|