77 - openEMS v0.0.35+
88
99 (c) 2016-2023 Thorsten Liebig <thorsten.liebig@gmx.de>
10-
10+ 04-Jan-2026: modified to use matplotlib.pyplot instead of pylab
1111"""
1212
1313
1414### Import Libraries
1515import os , tempfile
16- from pylab import *
16+ import numpy as np
17+ import matplotlib .pyplot as plt # pip install matplotlib
1718
1819from CSXCAD import ContinuousStructure
1920from openEMS import openEMS
@@ -45,7 +46,7 @@ def setEdgeResolution(self, res):
4546 def createCell (self , translate = [0 ,0 ,0 ]):
4647 mesh = [None ,None ,None ]
4748 third_res = self .edge_resolution / 3
48- translate = array (translate )
49+ translate = np . array (translate )
4950 start = [- self .LL / 2 , - self .LW / 2 , self .Top ] + translate
5051 stop = [- self .GLT / 2 , self .LW / 2 , self .Top ] + translate
5152 box = self .props ['metal_top' ].AddBox (start , stop , priority = 10 )
@@ -113,16 +114,16 @@ def createCell(self, translate = [0,0,0]):
113114 FDTD .SetBoundaryCond ( ['PML_8' , 'PML_8' , 'MUR' , 'MUR' , 'PEC' , 'PML_8' ] )
114115
115116 ### Setup a basic mesh and create the CRLH unit cell
116- resolution = C0 / (f_stop * sqrt (max (substrate_epsr )))/ unit / 30 # resolution of lambda/30
117+ resolution = C0 / (f_stop * np . sqrt (max (substrate_epsr )))/ unit / 30 # resolution of lambda/30
117118 CRLH .setEdgeResolution (resolution / 4 )
118119
119120 mesh .SetLines ('x' , [- feed_length - CRLH .LL / 2 , 0 , feed_length + CRLH .LL / 2 ])
120121 mesh .SetLines ('y' , [- 30000 , 0 , 30000 ])
121122
122- substratelines = cumsum (substrate_thickness )
123+ substratelines = np . cumsum (substrate_thickness )
123124 mesh .SetLines ('z' , [0 , 20000 ])
124- mesh .AddLine ('z' , cumsum (substrate_thickness ))
125- mesh .AddLine ('z' , linspace (substratelines [- 2 ],substratelines [- 1 ],4 ))
125+ mesh .AddLine ('z' , np . cumsum (substrate_thickness ))
126+ mesh .AddLine ('z' , np . linspace (substratelines [- 2 ],substratelines [- 1 ],4 ))
126127
127128 # create the CRLH unit cell (will define additional fixed mesh lines)
128129 mesh_hint = CRLH .createCell ()
@@ -169,21 +170,22 @@ def createCell(self, translate = [0,0,0]):
169170 FDTD .Run (Sim_Path , cleanup = True )
170171
171172 ### Post-Processing
172- f = linspace ( f_start , f_stop , 1601 )
173+ f = np . linspace ( f_start , f_stop , 1601 )
173174 for p in port :
174175 p .CalcPort ( Sim_Path , f , ref_impedance = 50 , ref_plane_shift = feed_length )
175176
176177 # calculate and plot scattering parameter
177178 s11 = port [0 ].uf_ref / port [0 ].uf_inc
178179 s21 = port [1 ].uf_ref / port [0 ].uf_inc
179180
180- plot (f / 1e9 ,20 * log10 (abs (s11 )),'k-' , linewidth = 2 , label = '$S_{11}$' )
181- plot (f / 1e9 ,20 * log10 (abs (s21 )),'r--' , linewidth = 2 , label = '$S_{21}$' )
182- grid ()
183- legend (loc = 3 )
184- ylabel ('S-Parameter (dB)' )
185- xlabel ('frequency (GHz)' )
186- ylim ([- 40 , 2 ])
181+ fig , axis = plt .subplots (num = "S11" , tight_layout = True )
182+ axis .plot (f / 1e9 , 20 * np .log10 (abs (s11 )), 'k-' , linewidth = 2 , label = 'S11' )
183+ axis .plot (f / 1e9 , 20 * np .log10 (abs (s21 )), 'r--' , linewidth = 2 , label = 'S21' )
184+ axis .grid ()
185+ axis .set_xmargin (0 )
186+ axis .set_xlabel ('Frequency (GHz)' )
187+ axis .set_ylabel ('S-Parameter (dB)' )
188+ axis .legend ()
187189
188190 ### Extract CRLH parameter form ABCD matrix
189191 A = ((1 + s11 )* (1 - s11 ) + s21 * s21 )/ (2 * s21 )
@@ -192,41 +194,44 @@ def createCell(self, translate = [0,0,0]):
192194 Y = C
193195 Z = 2 * (A - 1 )/ C
194196
195- iZ = imag (Z )
196- iY = imag (Y )
197+ iZ = np . imag (Z )
198+ iY = np . imag (Y )
197199
198- fse = interp (0 , iZ , f )
199- fsh = interp (0 , iY , f )
200+ fse = np . interp (0 , iZ , f )
201+ fsh = np . interp (0 , iY , f )
200202
201203 df = f [1 ]- f [0 ]
202204 fse_idx = np .where (f > fse )[0 ][0 ]
203205 fsh_idx = np .where (f > fsh )[0 ][0 ]
204206
205- LR = 0.5 * (iZ [fse_idx ]- iZ [fse_idx - 1 ])/ (2 * pi * df )
206- CL = 1 / (2 * pi * fse )** 2 / LR
207+ LR = 0.5 * (iZ [fse_idx ]- iZ [fse_idx - 1 ])/ (2 * np . pi * df )
208+ CL = 1 / (2 * np . pi * fse )** 2 / LR
207209
208- CR = 0.5 * (iY [fsh_idx ]- iY [fsh_idx - 1 ])/ (2 * pi * df )
209- LL = 1 / (2 * pi * fsh )** 2 / CR
210+ CR = 0.5 * (iY [fsh_idx ]- iY [fsh_idx - 1 ])/ (2 * np . pi * df )
211+ LL = 1 / (2 * np . pi * fsh )** 2 / CR
210212
211213 print (' Series tank: CL = {:.2f} pF, LR = {:.2f} nH -> f_se = {:.2f} GHz ' .format (CL * 1e12 , LR * 1e9 , fse * 1e-9 ))
212214 print (' Shunt tank: CR = {:.2f} pF, LL = {:.2f} nH -> f_sh = {:.2f} GHz ' .format (CR * 1e12 , LL * 1e9 , fsh * 1e-9 ))
213215
214216 ### Calculate analytical wave-number of an inf-array of cells
215- w = 2 * pi * f
216- wse = 2 * pi * fse
217- wsh = 2 * pi * fsh
218- beta_calc = real (arccos (1 - (w ** 2 - wse ** 2 )* (w ** 2 - wsh ** 2 )/ (2 * w ** 2 / CR / LR )))
217+ w = 2 * np . pi * f
218+ wse = 2 * np . pi * fse
219+ wsh = 2 * np . pi * fsh
220+ beta_calc = np . real (np . arccos (1 - (w ** 2 - wse ** 2 )* (w ** 2 - wsh ** 2 )/ (2 * w ** 2 / CR / LR )))
219221
220222 # plot
221- figure ()
222- beta = - angle (s21 )/ CRLH .LL / unit
223- plot (abs (beta )* CRLH .LL * unit / pi ,f * 1e-9 ,'k-' , linewidth = 2 , label = r'$\beta_{CRLH,\ 1\ cell}$' )
224- grid ()
225- plot (beta_calc / pi ,f * 1e-9 ,'c--' , linewidth = 2 , label = r'$\beta_{CRLH,\ \infty\ cells}$' )
226- plot (real (port [1 ].beta )* CRLH .LL * unit / pi ,f * 1e-9 ,'g-' , linewidth = 2 , label = r'$\beta_{MSL}$' )
227- ylim ([1 , 6 ])
228- xlabel (r'$|\beta| p / \pi$' )
229- ylabel ('frequency (GHz)' )
230- legend (loc = 2 )
231-
232- show ()
223+ beta = - np .angle (s21 )/ CRLH .LL / unit
224+ fig , axis = plt .subplots (num = "beta" , tight_layout = True )
225+ axis .plot (np .abs (beta )* CRLH .LL * unit / np .pi ,f * 1e-9 , 'k-' , linewidth = 2 , label = r'$\beta_{CRLH,\ 1\ cell}$' )
226+ axis .plot (beta_calc / np .pi ,f * 1e-9 ,'c--' , linewidth = 2 , label = r'$\beta_{CRLH,\ \infty\ cells}$' )
227+ axis .plot (np .real (port [1 ].beta )* CRLH .LL * unit / np .pi ,f * 1e-9 ,'g-' , linewidth = 2 , label = r'$\beta_{MSL}$' )
228+ axis .grid ()
229+ # axis.set_xmargin(0)
230+ axis .set_ylim ([1 , 6 ])
231+ axis .set_xlabel (r'$|\beta| p / \pi$' )
232+ axis .set_ylabel ('S-Parameter (dB)' )
233+ axis .legend (loc = 'upper left' )
234+
235+
236+ # show all plots
237+ plt .show ()
0 commit comments