python: update tutorials, improve doc
Signed-off-by: Thorsten Liebig <Thorsten.Liebig@gmx.de>
This commit is contained in:
parent
015f6bcde0
commit
c943590548
198
python/Tutorials/Bent_Patch_Antenna.py
Normal file
198
python/Tutorials/Bent_Patch_Antenna.py
Normal file
@ -0,0 +1,198 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Bent Patch Antenna Tutorial
|
||||
|
||||
Tested with
|
||||
- python 3.4
|
||||
- openEMS v0.0.33+
|
||||
|
||||
(C) 2016 Thorsten Liebig <thorsten.liebig@gmx.de>
|
||||
|
||||
"""
|
||||
|
||||
### Import Libraries
|
||||
import os, tempfile
|
||||
from pylab import *
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
from CSXCAD import CSXCAD
|
||||
|
||||
from openEMS.openEMS import openEMS
|
||||
from openEMS.physical_constants import *
|
||||
|
||||
|
||||
### Setup the simulation
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'Bent_Patch')
|
||||
|
||||
post_proc_only = False
|
||||
|
||||
unit = 1e-3 # all length in mm
|
||||
|
||||
f0 = 2.4e9 # center frequency, frequency of interest!
|
||||
lambda0 = round(C0/f0/unit) # wavelength in mm
|
||||
fc = 0.5e9 # 20 dB corner frequency
|
||||
|
||||
# patch width in alpha-direction
|
||||
patch_width = 32 # resonant length in alpha-direction
|
||||
patch_radius = 50 # radius
|
||||
patch_length = 40 # patch length in z-direction
|
||||
|
||||
#substrate setup
|
||||
substrate_epsR = 3.38
|
||||
substrate_kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate_epsR
|
||||
substrate_width = 80
|
||||
substrate_length = 90
|
||||
substrate_thickness = 1.524
|
||||
substrate_cells = 4
|
||||
|
||||
#setup feeding
|
||||
feed_pos = -5.5 #feeding position in x-direction
|
||||
feed_width = 2 #feeding port width
|
||||
feed_R = 50 #feed resistance
|
||||
|
||||
# size of the simulation box
|
||||
SimBox_rad = 2*100
|
||||
SimBox_height = 1.5*200
|
||||
|
||||
### Setup FDTD parameter & excitation function
|
||||
FDTD = openEMS(CoordSystem=1) # init a cylindrical FDTD
|
||||
f0 = 2e9 # center frequency
|
||||
fc = 1e9 # 20 dB corner frequency
|
||||
FDTD.SetGaussExcite(f0, fc)
|
||||
FDTD.SetBoundaryCond(['MUR', 'MUR', 'MUR', 'MUR', 'MUR', 'MUR']) # boundary conditions
|
||||
|
||||
### Setup the Geometry & Mesh
|
||||
# init a cylindrical mesh
|
||||
CSX = CSXCAD.ContinuousStructure(CoordSystem=1)
|
||||
FDTD.SetCSX(CSX)
|
||||
mesh = CSX.GetGrid()
|
||||
mesh.SetDeltaUnit(unit)
|
||||
|
||||
### Setup the geometry using cylindrical coordinates
|
||||
# calculate some width as an angle in radiant
|
||||
patch_ang_width = patch_width/(patch_radius+substrate_thickness)
|
||||
substr_ang_width = substrate_width/patch_radius
|
||||
feed_angle = feed_pos/patch_radius
|
||||
|
||||
# create patch
|
||||
patch = CSX.AddMetal('patch') # create a perfect electric conductor (PEC)
|
||||
start = [patch_radius+substrate_thickness, -patch_ang_width/2, -patch_length/2 ]
|
||||
stop = [patch_radius+substrate_thickness, patch_ang_width/2, patch_length/2 ]
|
||||
CSX.AddBox(patch, priority=10, start=start, stop=stop, edges2grid='all') # add a box-primitive to the metal property 'patch'
|
||||
|
||||
# create substrate
|
||||
substrate = CSX.AddMaterial('substrate', epsilon=substrate_epsR, kappa=substrate_kappa )
|
||||
start = [patch_radius , -substr_ang_width/2, -substrate_length/2]
|
||||
stop = [patch_radius+substrate_thickness, substr_ang_width/2, substrate_length/2]
|
||||
CSX.AddBox(substrate, start=start, stop=stop, edges2grid='all')
|
||||
|
||||
# save current density oon the patch
|
||||
jt_patch = CSX.AddDump('Jt_patch', dump_type=3, file_type=1)
|
||||
start = [patch_radius+substrate_thickness, -substr_ang_width/2, -substrate_length/2]
|
||||
stop = [patch_radius+substrate_thickness, +substr_ang_width/2, substrate_length/2]
|
||||
CSX.AddBox(jt_patch, start=start, stop=stop)
|
||||
|
||||
# create ground
|
||||
gnd = CSX.AddMetal('gnd') # create a perfect electric conductor (PEC)
|
||||
start = [patch_radius, -substr_ang_width/2, -substrate_length/2]
|
||||
stop = [patch_radius, +substr_ang_width/2, +substrate_length/2]
|
||||
CSX.AddBox(gnd, priority=10, start=start, stop=stop, edges2grid='all')
|
||||
|
||||
# apply the excitation & resist as a current source
|
||||
start = [patch_radius , feed_angle, 0]
|
||||
stop = [patch_radius+substrate_thickness, feed_angle, 0]
|
||||
port = FDTD.AddLumpedPort(1 ,feed_R, start, stop, 'r', 1.0, priority=50, edges2grid='all')
|
||||
|
||||
### Finalize the Mesh
|
||||
# add the simulation domain size
|
||||
mesh.AddLine('r', patch_radius+np.array([-20, SimBox_rad]))
|
||||
mesh.AddLine('a', [-0.75*pi, 0.75*pi])
|
||||
mesh.AddLine('z', [-SimBox_height/2, SimBox_height/2])
|
||||
|
||||
# add some lines for the substrate
|
||||
mesh.AddLine('r', patch_radius+np.linspace(0,substrate_thickness,substrate_cells))
|
||||
|
||||
# generate a smooth mesh with max. cell size: lambda_min / 20
|
||||
max_res = C0 / (f0+fc) / unit / 20
|
||||
max_ang = max_res/(SimBox_rad+patch_radius) # max res in radiant
|
||||
mesh.SmoothMeshLines(0, max_res, 1.4)
|
||||
mesh.SmoothMeshLines(1, max_ang, 1.4)
|
||||
mesh.SmoothMeshLines(2, max_res, 1.4)
|
||||
|
||||
## Add the nf2ff recording box
|
||||
nf2ff = FDTD.CreateNF2FFBox()
|
||||
|
||||
### Run the simulation
|
||||
if 0: # debugging only
|
||||
CSX_file = os.path.join(Sim_Path, 'bent_patch.xml')
|
||||
if not os.path.exists(Sim_Path):
|
||||
os.mkdir(Sim_Path)
|
||||
CSX.Write2XML(CSX_file)
|
||||
os.system(r'AppCSXCAD "{}"'.format(CSX_file))
|
||||
|
||||
|
||||
if not post_proc_only:
|
||||
FDTD.Run(Sim_Path, verbose=3, cleanup=True)
|
||||
|
||||
### Postprocessing & plotting
|
||||
f = np.linspace(max(1e9,f0-fc),f0+fc,401)
|
||||
port.CalcPort(Sim_Path, f)
|
||||
Zin = port.uf_tot / port.if_tot
|
||||
s11 = port.uf_ref/port.uf_inc
|
||||
s11_dB = 20.0*np.log10(np.abs(s11))
|
||||
|
||||
figure()
|
||||
plot(f/1e9, s11_dB)
|
||||
grid()
|
||||
ylabel('s11 (dB)')
|
||||
xlabel('frequency (GHz)')
|
||||
|
||||
P_in = 0.5*np.real(port.uf_tot * np.conj(port.if_tot)) # antenna feed power
|
||||
|
||||
# plot feed point impedance
|
||||
figure()
|
||||
plot( f/1e6, real(Zin), 'k-', linewidth=2, label=r'$\Re(Z_{in})$' )
|
||||
grid()
|
||||
plot( f/1e6, imag(Zin), 'r--', linewidth=2, label=r'$\Im(Z_{in})$' )
|
||||
title( 'feed point impedance' )
|
||||
xlabel( 'frequency (MHz)' )
|
||||
ylabel( 'impedance ($\Omega$)' )
|
||||
legend( )
|
||||
|
||||
|
||||
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)
|
||||
print("Calculate NF2FF")
|
||||
nf2ff_res_phi0 = nf2ff.CalcNF2FF(Sim_Path, f_res, theta, 0, center=np.array([patch_radius+substrate_thickness, 0, 0])*unit, read_cached=True, outfile='nf2ff_xz.h5')
|
||||
|
||||
figure(figsize=(15, 7))
|
||||
ax = subplot(121, polar=True)
|
||||
E_norm = 20.0*np.log10(nf2ff_res_phi0.E_norm/np.max(nf2ff_res_phi0.E_norm)) + nf2ff_res_phi0.Dmax
|
||||
ax.plot(np.deg2rad(theta), 10**(np.squeeze(E_norm)/20), linewidth=2, label='xz-plane')
|
||||
ax.grid(True)
|
||||
ax.set_xlabel('theta (deg)')
|
||||
ax.set_theta_zero_location('N')
|
||||
ax.set_theta_direction(-1)
|
||||
ax.legend(loc=3)
|
||||
|
||||
phi = theta
|
||||
nf2ff_res_theta90 = nf2ff.CalcNF2FF(Sim_Path, f_res, 90, phi, center=np.array([patch_radius+substrate_thickness, 0, 0])*unit, read_cached=True, outfile='nf2ff_xy.h5')
|
||||
|
||||
ax = subplot(122, polar=True)
|
||||
E_norm = 20.0*np.log10(nf2ff_res_theta90.E_norm/np.max(nf2ff_res_theta90.E_norm)) + nf2ff_res_theta90.Dmax
|
||||
ax.plot(np.deg2rad(phi), 10**(np.squeeze(E_norm)/20), linewidth=2, label='xy-plane')
|
||||
ax.grid(True)
|
||||
ax.set_xlabel('phi (deg)')
|
||||
suptitle('Bent Patch Anteanna Pattern\nFrequency: {} GHz'.format(f_res/1e9), fontsize=14)
|
||||
ax.legend(loc=3)
|
||||
|
||||
print( 'radiated power: Prad = {:.2e} Watt'.format(nf2ff_res_theta90.Prad[0]))
|
||||
print( 'directivity: Dmax = {:.1f} ({:.1f} dBi)'.format(nf2ff_res_theta90.Dmax[0], 10*np.log10(nf2ff_res_theta90.Dmax[0])))
|
||||
print( 'efficiency: nu_rad = {:.1f} %'.format(100*nf2ff_res_theta90.Prad[0]/real(P_in[idx[0]])))
|
||||
|
||||
show()
|
||||
|
@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|
||||
Tutorials / helical antenna
|
||||
Helical Antenna Tutorial
|
||||
|
||||
Tested with
|
||||
- python 3.4
|
||||
@ -11,19 +10,20 @@
|
||||
|
||||
"""
|
||||
|
||||
### Import Libraries
|
||||
import os, tempfile
|
||||
from pylab import *
|
||||
|
||||
from CSXCAD import CSXCAD
|
||||
|
||||
from openEMS.openEMS import openEMS
|
||||
from openEMS import openEMS
|
||||
from openEMS.physical_constants import *
|
||||
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'Helical_Ant')
|
||||
|
||||
### Setup the simulation
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'Helical_Ant')
|
||||
post_proc_only = False
|
||||
|
||||
## setup the simulation
|
||||
unit = 1e-3 # all length in mm
|
||||
|
||||
f0 = 2.4e9 # center frequency, frequency of interest!
|
||||
@ -44,12 +44,12 @@ feed_R = 120 #feed impedance
|
||||
# size of the simulation box
|
||||
SimBox = array([1, 1, 1.5])*2.0*lambda0
|
||||
|
||||
## setup FDTD parameter & excitation function
|
||||
### Setup FDTD parameter & excitation function
|
||||
FDTD = openEMS(EndCriteria=1e-4)
|
||||
FDTD.SetGaussExcite( f0, fc )
|
||||
FDTD.SetBoundaryCond( ['MUR', 'MUR', 'MUR', 'MUR', 'MUR', 'PML_8'] )
|
||||
|
||||
## setup CSXCAD geometry & mesh
|
||||
### Setup Geometry & Mesh
|
||||
CSX = CSXCAD.ContinuousStructure()
|
||||
FDTD.SetCSX(CSX)
|
||||
mesh = CSX.GetGrid()
|
||||
@ -77,8 +77,11 @@ mesh.AddLine('z', [-SimBox[2]/2, max(mesh.GetLines('z'))+SimBox[2]/2 ])
|
||||
# create a smooth mesh between specified fixed mesh lines
|
||||
mesh.SmoothMeshLines('z', max_res, ratio=1.4)
|
||||
|
||||
## create helix using the wire primitive
|
||||
helix_metal = CSX.AddMetal('helix' ) # create a perfect electric conductor (PEC)
|
||||
### Create the Geometry
|
||||
## * Create the metal helix using the wire primitive.
|
||||
## * Create a metal gorund plane as cylinder.
|
||||
# create a perfect electric conductor (PEC)
|
||||
helix_metal = CSX.AddMetal('helix' )
|
||||
|
||||
ang = linspace(0,2*pi,21)
|
||||
coil_x = Helix_radius*cos(ang)
|
||||
@ -98,7 +101,7 @@ for n in range(Helix_turns-1):
|
||||
p = np.array([Helix_x, Helix_y, Helix_z])
|
||||
CSX.AddCurve(helix_metal, p)
|
||||
|
||||
## create ground circular ground
|
||||
# create ground circular ground
|
||||
gnd = CSX.AddMetal( 'gnd' ) # create a perfect electric conductor (PEC)
|
||||
|
||||
# add a box using cylindrical coordinates
|
||||
@ -106,14 +109,15 @@ start = [0, 0, -0.1]
|
||||
stop = [0, 0, 0.1]
|
||||
CSX.AddCylinder(gnd, start, stop, radius=gnd_radius)
|
||||
|
||||
### apply the excitation & resist as a current source
|
||||
# apply the excitation & resist as a current source
|
||||
start = [Helix_radius, 0, 0]
|
||||
stop = [Helix_radius, 0, feed_heigth]
|
||||
port = FDTD.AddLumpedPort(1 ,feed_R, start, stop, 'z', 1.0, priority=5)
|
||||
|
||||
## nf2ff calc
|
||||
# nf2ff calc
|
||||
nf2ff = FDTD.CreateNF2FFBox(opt_resolution=[lambda0/15]*3)
|
||||
|
||||
### Run the simulation
|
||||
if 0: # debugging only
|
||||
CSX_file = os.path.join(Sim_Path, 'helix.xml')
|
||||
if not os.path.exists(Sim_Path):
|
||||
@ -124,14 +128,14 @@ if 0: # debugging only
|
||||
if not post_proc_only:
|
||||
FDTD.Run(Sim_Path, verbose=3, cleanup=True)
|
||||
|
||||
## postprocessing & do the plots
|
||||
### Postprocessing & plotting
|
||||
freq = linspace( f0-fc, f0+fc, 501 )
|
||||
port.CalcPort(Sim_Path, freq)
|
||||
|
||||
Zin = port.uf_tot / port.if_tot
|
||||
s11 = port.uf_ref / port.uf_inc
|
||||
|
||||
## plot feed point impedance
|
||||
## Plot the feed point impedance
|
||||
figure()
|
||||
plot( freq/1e6, real(Zin), 'k-', linewidth=2, label=r'$\Re(Z_{in})$' )
|
||||
grid()
|
||||
@ -141,7 +145,7 @@ xlabel( 'frequency (MHz)' )
|
||||
ylabel( 'impedance ($\Omega$)' )
|
||||
legend( )
|
||||
|
||||
## plot reflection coefficient S11
|
||||
## Plot reflection coefficient S11
|
||||
figure()
|
||||
plot( freq/1e6, 20*log10(abs(s11)), 'k-', linewidth=2 )
|
||||
grid()
|
||||
@ -149,33 +153,30 @@ title( 'reflection coefficient $S_{11}$' )
|
||||
xlabel( 'frequency (MHz)' )
|
||||
ylabel( 'reflection coefficient $|S_{11}|$' )
|
||||
|
||||
## NFFF contour plots ####################################################
|
||||
## calculate the far field at phi=0 degrees and at phi=90 degrees
|
||||
### Create the NFFF contour
|
||||
## * calculate the far field at phi=0 degrees and at phi=90 degrees
|
||||
theta = arange(0.,180.,1.)
|
||||
phi = arange(-180,180,2)
|
||||
disp( 'calculating the 3D far field...' )
|
||||
|
||||
nf2ff_res = nf2ff.CalcNF2FF(Sim_Path, f0, theta, phi, read_cached=True, verbose=True )
|
||||
|
||||
#
|
||||
Dmax_dB = 10*log10(nf2ff_res.Dmax[0])
|
||||
E_norm = 20.0*log10(nf2ff_res.E_norm[0]/np.max(nf2ff_res.E_norm[0])) + 10*log10(nf2ff_res.Dmax[0])
|
||||
|
||||
theta_HPBW = theta[ np.where(squeeze(E_norm[:,phi==0])<Dmax_dB-3)[0][0] ]
|
||||
#
|
||||
# display power and directivity
|
||||
|
||||
## * Display power and directivity
|
||||
print('radiated power: Prad = {} W'.format(nf2ff_res.Prad[0]))
|
||||
print('directivity: Dmax = {} dBi'.format(Dmax_dB))
|
||||
print('efficiency: nu_rad = {} %'.format(100*nf2ff_res.Prad[0]/interp(f0, freq, port.P_acc)))
|
||||
print('theta_HPBW = {} °'.format(theta_HPBW))
|
||||
|
||||
|
||||
##
|
||||
E_norm = 20.0*log10(nf2ff_res.E_norm[0]/np.max(nf2ff_res.E_norm[0])) + 10*log10(nf2ff_res.Dmax[0])
|
||||
E_CPRH = 20.0*log10(np.abs(nf2ff_res.E_cprh[0])/np.max(nf2ff_res.E_norm[0])) + 10*log10(nf2ff_res.Dmax[0])
|
||||
E_CPLH = 20.0*log10(np.abs(nf2ff_res.E_cplh[0])/np.max(nf2ff_res.E_norm[0])) + 10*log10(nf2ff_res.Dmax[0])
|
||||
|
||||
##
|
||||
## * Plot the pattern
|
||||
figure()
|
||||
plot(theta, E_norm[:,phi==0],'k-' , linewidth=2, label='$|E|$')
|
||||
plot(theta, E_CPRH[:,phi==0],'g--', linewidth=2, label='$|E_{CPRH}|$')
|
||||
@ -186,8 +187,5 @@ ylabel('directivity (dBi)')
|
||||
title('Frequency: {} GHz'.format(nf2ff_res.freq[0]/1e9))
|
||||
legend()
|
||||
|
||||
### dump to vtk
|
||||
# TODO
|
||||
|
||||
show()
|
||||
|
||||
|
@ -1,27 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Microstrip Notch Filter Tutorial
|
||||
|
||||
Tutorials / MSL_NotchFilter
|
||||
Describtion at:
|
||||
http://openems.de/doc/openEMS/Tutorials.html#microstrip-notch-filter
|
||||
|
||||
Tested with
|
||||
- python 3.4
|
||||
- openEMS v0.0.33+
|
||||
- openEMS v0.0.34+
|
||||
|
||||
(C) 2016 Thorsten Liebig <thorsten.liebig@gmx.de>
|
||||
|
||||
"""
|
||||
|
||||
### Import Libraries
|
||||
import os, tempfile
|
||||
from pylab import *
|
||||
|
||||
from CSXCAD import CSXCAD
|
||||
|
||||
from CSXCAD import ContinuousStructure
|
||||
from openEMS import openEMS
|
||||
from openEMS.physical_constants import *
|
||||
|
||||
post_proc_only = False
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'NotchFilter')
|
||||
|
||||
## setup the simulation ###################################################
|
||||
### Setup the simulation
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'NotchFilter')
|
||||
post_proc_only = False
|
||||
|
||||
unit = 1e-6 # specify everything in um
|
||||
MSL_length = 50000
|
||||
MSL_width = 600
|
||||
@ -30,13 +34,13 @@ substrate_epr = 3.66
|
||||
stub_length = 12e3
|
||||
f_max = 7e9
|
||||
|
||||
## setup FDTD parameters & excitation function ############################
|
||||
FDTD = openEMS.openEMS()
|
||||
### Setup FDTD parameters & excitation function
|
||||
FDTD = openEMS()
|
||||
FDTD.SetGaussExcite( f_max/2, f_max/2 )
|
||||
FDTD.SetBoundaryCond( ['PML_8', 'PML_8', 'MUR', 'MUR', 'PEC', 'MUR'] )
|
||||
|
||||
## setup CSXCAD geometry & mesh ###########################################
|
||||
CSX = CSXCAD.ContinuousStructure()
|
||||
### Setup Geometry & Mesh
|
||||
CSX = ContinuousStructure()
|
||||
FDTD.SetCSX(CSX)
|
||||
mesh = CSX.GetGrid()
|
||||
mesh.SetDeltaUnit(unit)
|
||||
@ -44,6 +48,7 @@ mesh.SetDeltaUnit(unit)
|
||||
resolution = C0/(f_max*sqrt(substrate_epr))/unit/50 # resolution of lambda/50
|
||||
third_mesh = array([2*resolution/3, -resolution/3])/4
|
||||
|
||||
## Do manual meshing
|
||||
mesh.AddLine('x', 0)
|
||||
mesh.AddLine('x', MSL_width/2+third_mesh)
|
||||
mesh.AddLine('x', -MSL_width/2-third_mesh)
|
||||
@ -65,13 +70,13 @@ mesh.AddLine('z', linspace(0,substrate_thickness,5))
|
||||
mesh.AddLine('z', 3000)
|
||||
mesh.SmoothMeshLines('z', resolution)
|
||||
|
||||
## substrate
|
||||
## Add the substrate
|
||||
substrate = CSX.AddMaterial( 'RO4350B', epsilon=substrate_epr)
|
||||
start = [-MSL_length, -15*MSL_width, 0]
|
||||
stop = [+MSL_length, +15*MSL_width+stub_length, substrate_thickness]
|
||||
CSX.AddBox(substrate, start, stop )
|
||||
|
||||
## MSL port
|
||||
## MSL port setup
|
||||
port = [None, None]
|
||||
pec = CSX.AddMetal( 'PEC' )
|
||||
portstart = [ -MSL_length, -MSL_width/2, substrate_thickness]
|
||||
@ -82,11 +87,12 @@ portstart = [MSL_length, -MSL_width/2, substrate_thickness]
|
||||
portstop = [0 , MSL_width/2, 0]
|
||||
port[1] = FDTD.AddMSLPort( 2, pec, portstart, portstop, 'x', 'z', MeasPlaneShift=MSL_length/3, priority=10 )
|
||||
|
||||
## Filter-stub
|
||||
## Filter-Stub Definition
|
||||
start = [-MSL_width/2, MSL_width/2, substrate_thickness]
|
||||
stop = [ MSL_width/2, MSL_width/2+stub_length, substrate_thickness]
|
||||
box = CSX.AddBox( pec, start, stop, priority=10 )
|
||||
|
||||
### Run the simulation
|
||||
if 0: # debugging only
|
||||
CSX_file = os.path.join(Sim_Path, 'notch.xml')
|
||||
if not os.path.exists(Sim_Path):
|
||||
@ -98,7 +104,7 @@ if 0: # debugging only
|
||||
if not post_proc_only:
|
||||
FDTD.Run(Sim_Path, verbose=3, cleanup=True)
|
||||
|
||||
## post-processing
|
||||
### Post-processing and plotting
|
||||
f = linspace( 1e6, f_max, 1601 )
|
||||
for p in port:
|
||||
p.CalcPort( Sim_Path, f, ref_impedance = 50)
|
||||
|
@ -1,30 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Dec 29 15:40:23 2015
|
||||
|
||||
Tutorials / Rect_Waveguide
|
||||
Rectangular Waveguide Tutorial
|
||||
|
||||
Describtion at:
|
||||
http://openems.de/index.php/Tutorial:_Rectangular_Waveguide
|
||||
http://openems.de/doc/openEMS/Tutorials.html#rectangular-waveguide
|
||||
|
||||
Tested with
|
||||
- python 3.4
|
||||
- openEMS v0.0.33+
|
||||
- openEMS v0.0.34+
|
||||
|
||||
(C) 2015-2016 Thorsten Liebig <thorsten.liebig@gmx.de>
|
||||
|
||||
"""
|
||||
|
||||
### Import Libraries
|
||||
import os, tempfile
|
||||
from pylab import *
|
||||
|
||||
from CSXCAD import CSXCAD
|
||||
from openEMS.openEMS import openEMS
|
||||
from CSXCAD import ContinuousStructure
|
||||
from openEMS import openEMS
|
||||
from openEMS.physical_constants import *
|
||||
|
||||
### Setup the simulation
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'Rect_WG')
|
||||
|
||||
## setup the simulation ###################################################
|
||||
post_proc_only = False
|
||||
unit = 1e-6; #drawing unit in um
|
||||
|
||||
@ -46,15 +45,15 @@ TE_mode = 'TE10';
|
||||
#targeted mesh resolution
|
||||
mesh_res = lambda0/30
|
||||
|
||||
## setup FDTD parameter & excitation function #############################
|
||||
### Setup FDTD parameter & excitation function
|
||||
FDTD = openEMS(NrTS=1e4);
|
||||
FDTD.SetGaussExcite(0.5*(f_start+f_stop),0.5*(f_stop-f_start));
|
||||
|
||||
# boundary conditions
|
||||
FDTD.SetBoundaryCond([0, 0, 0, 0, 3, 3]);
|
||||
|
||||
## setup CSXCAD geometry & mesh
|
||||
CSX = CSXCAD.ContinuousStructure()
|
||||
### Setup geometry & mesh
|
||||
CSX = ContinuousStructure()
|
||||
FDTD.SetCSX(CSX)
|
||||
mesh = CSX.GetGrid()
|
||||
mesh.SetDeltaUnit(unit)
|
||||
@ -63,7 +62,7 @@ mesh.AddLine('x', [0, a])
|
||||
mesh.AddLine('y', [0, b])
|
||||
mesh.AddLine('z', [0, length])
|
||||
|
||||
## apply the waveguide port ###################################################
|
||||
## Apply the waveguide port
|
||||
ports = []
|
||||
start=[0, 0, 10*mesh_res];
|
||||
stop =[a, b, 15*mesh_res];
|
||||
@ -77,13 +76,13 @@ ports.append(FDTD.AddRectWaveGuidePort( 1, start, stop, 'z', a*unit, b*unit, TE_
|
||||
|
||||
mesh.SmoothMeshLines('all', mesh_res, ratio=1.4)
|
||||
|
||||
## define dump box... #####################################################
|
||||
### Define dump box...
|
||||
Et = CSX.AddDump('Et', file_type=0, sub_sampling=[2,2,2])
|
||||
start = [0, 0, 0];
|
||||
stop = [a, b, length];
|
||||
CSX.AddBox(Et, start, stop);
|
||||
|
||||
## Write openEMS compatoble xml-file ######################################
|
||||
### Run the simulation
|
||||
if 0: # debugging only
|
||||
CSX_file = os.path.join(Sim_Path, 'rect_wg.xml')
|
||||
if not os.path.exists(Sim_Path):
|
||||
@ -94,7 +93,7 @@ if 0: # debugging only
|
||||
if not post_proc_only:
|
||||
FDTD.Run(Sim_Path, verbose=3, cleanup=True)
|
||||
|
||||
### postproc ###############################################################
|
||||
### Postprocessing & plotting
|
||||
freq = linspace(f_start,f_stop,201)
|
||||
for port in ports:
|
||||
port.CalcPort(Sim_Path, freq)
|
||||
@ -104,7 +103,7 @@ s21 = ports[1].uf_ref / ports[0].uf_inc
|
||||
ZL = ports[0].uf_tot / ports[0].if_tot
|
||||
ZL_a = ports[0].ZL # analytic waveguide impedance
|
||||
|
||||
## plot s-parameter #######################################################
|
||||
## Plot s-parameter
|
||||
figure()
|
||||
plot(freq*1e-6,20*log10(abs(s11)),'k-',linewidth=2, label='$S_{11}$')
|
||||
grid()
|
||||
@ -113,7 +112,7 @@ legend();
|
||||
ylabel('S-Parameter (dB)')
|
||||
xlabel(r'frequency (MHz) $\rightarrow$')
|
||||
|
||||
## compare analytic and numerical wave-impedance ##########################
|
||||
## Compare analytic and numerical wave-impedance
|
||||
figure()
|
||||
plot(freq*1e-6,real(ZL), linewidth=2, label='$\Re\{Z_L\}$')
|
||||
grid()
|
||||
|
@ -5,20 +5,21 @@ Created on Fri Dec 18 20:56:53 2015
|
||||
@author: thorsten
|
||||
"""
|
||||
|
||||
### Import Libraries
|
||||
import os, tempfile
|
||||
from pylab import *
|
||||
|
||||
from CSXCAD import CSXCAD
|
||||
|
||||
from openEMS.openEMS import openEMS
|
||||
from CSXCAD import ContinuousStructure
|
||||
from openEMS import openEMS
|
||||
from openEMS.physical_constants import *
|
||||
|
||||
### General parameter setup
|
||||
Sim_Path = os.path.join(tempfile.gettempdir(), 'Simp_Patch')
|
||||
|
||||
post_proc_only = False
|
||||
post_proc_only = True
|
||||
|
||||
# patch width in x-direction
|
||||
patch_width = 32 # resonant length
|
||||
# patch width (resonant length) in x-direction
|
||||
patch_width = 32 #
|
||||
# patch length in y-direction
|
||||
patch_length = 40
|
||||
|
||||
@ -37,33 +38,38 @@ feed_R = 50 #feed resistance
|
||||
# size of the simulation box
|
||||
SimBox = np.array([200, 200, 150])
|
||||
|
||||
## setup FDTD parameter & excitation function
|
||||
# setup FDTD parameter & excitation function
|
||||
f0 = 2e9 # center frequency
|
||||
fc = 1e9 # 20 dB corner frequency
|
||||
|
||||
### FDTD setup
|
||||
## * Limit the simulation to 30k timesteps
|
||||
## * Define a reduced end criteria of -40dB
|
||||
FDTD = openEMS(NrTS=30000, EndCriteria=1e-4)
|
||||
FDTD.SetGaussExcite( f0, fc )
|
||||
FDTD.SetBoundaryCond( ['MUR', 'MUR', 'MUR', 'MUR', 'MUR', 'MUR'] )
|
||||
|
||||
mesh_res = C0/(f0+fc)/1e-3/20
|
||||
|
||||
CSX = CSXCAD.ContinuousStructure()
|
||||
CSX = ContinuousStructure()
|
||||
FDTD.SetCSX(CSX)
|
||||
mesh = CSX.GetGrid()
|
||||
mesh.SetDeltaUnit(1e-3)
|
||||
mesh_res = C0/(f0+fc)/1e-3/20
|
||||
|
||||
### Generate properties, primitives and mesh-grid
|
||||
#initialize the mesh with the "air-box" dimensions
|
||||
mesh.AddLine('x', [-SimBox[0]/2, feed_pos, SimBox[0]/2])
|
||||
mesh.AddLine('y', [-SimBox[1]/2, SimBox[1]/2] )
|
||||
mesh.AddLine('z', [-SimBox[2]/3, SimBox[2]*2/3] )
|
||||
|
||||
## create patch
|
||||
# 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]
|
||||
pb=CSX.AddBox(patch, priority=10, start=start, stop=stop) # add a box-primitive to the metal property 'patch'
|
||||
pb.AddEdges2Grid('xy', metal_edge_res=mesh_res/2)
|
||||
|
||||
## create substrate
|
||||
# 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]
|
||||
@ -72,21 +78,23 @@ sb=CSX.AddBox( substrate, 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)
|
||||
# create ground (same size as substrate)
|
||||
gnd = CSX.AddMetal( 'gnd' ) # create a perfect electric conductor (PEC)
|
||||
start[2]=0
|
||||
stop[2] =0
|
||||
gb=CSX.AddBox(gnd, start, stop, priority=10, edges2grid='all')
|
||||
|
||||
## apply the excitation & resist as a current source
|
||||
# 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='all')
|
||||
|
||||
mesh.SmoothMeshLines('all', mesh_res, 1.4)
|
||||
|
||||
# Add the nf2ff recording box
|
||||
nf2ff = FDTD.CreateNF2FFBox()
|
||||
|
||||
### Run the simulation
|
||||
if 0: # debugging only
|
||||
CSX_file = os.path.join(Sim_Path, 'simp_patch.xml')
|
||||
if not os.path.exists(Sim_Path):
|
||||
@ -97,15 +105,18 @@ if 0: # debugging only
|
||||
if not post_proc_only:
|
||||
FDTD.Run(Sim_Path, verbose=3, cleanup=True)
|
||||
|
||||
|
||||
### Post-processing and plotting
|
||||
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)
|
||||
plot(f/1e9, s11_dB, 'k-', linewidth=2, label='$S_{11}$')
|
||||
grid()
|
||||
ylabel('s11 (dB)')
|
||||
xlabel('frequency (GHz)')
|
||||
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:
|
||||
@ -118,20 +129,21 @@ else:
|
||||
|
||||
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]), label='xz-plane')
|
||||
plot(theta, np.squeeze(E_norm[:,1]), label='yz-plane')
|
||||
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)')
|
||||
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))
|
||||
plot(f/1e9, np.imag(Zin))
|
||||
plot(f/1e9, np.real(Zin), 'k-', linewidth=2, label='$\Re\{Z_{in}\}$')
|
||||
plot(f/1e9, np.imag(Zin), 'r--', linewidth=2, label='$\Im\{Z_{in}\}$')
|
||||
grid()
|
||||
legend()
|
||||
ylabel('Zin (Ohm)')
|
||||
xlabel('frequency (GHz)')
|
||||
xlabel('Frequency (GHz)')
|
||||
|
||||
show()
|
||||
|
Loading…
Reference in New Issue
Block a user