KiCad PCB EDA Suite
rectwaveguide.cpp
Go to the documentation of this file.
1 /*
2  * rectwaveguide.cpp - rectangular waveguide class implementation
3  *
4  * Copyright (C) 2001 Gopal Narayanan <[email protected]>
5  * Copyright (C) 2005, 2006 Stefan Jahn <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this package; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #include <cmath>
25 #include <cstdio>
26 #include <cstring>
27 
28 #include "rectwaveguide.h"
29 #include "units.h"
30 
32  mur( 0.0 ), // magnetic permeability of substrate
33  a( 0.0 ), // width of waveguide
34  b( 0.0 ), // height of waveguide
35  l( 0.0 ), // length of waveguide
36  Z0( 0.0 ), // characteristic impedance
37  Z0EH( 0.0 ), // characteristic impedance of field quantities*/
38  mur_eff( 0.0 ), // Effective mag. permeability
39  atten_dielectric( 0.0 ), // Loss in dielectric (dB)
40  atten_cond( 0.0 ), // Loss in conductors (dB)
41  fc10( 1.0 ) // Cutoff frequency for TE10 mode
42 {
43  m_Name = "RectWaveGuide";
44  Init();
45 }
46 
47 
48 /*
49  * returns square of k
50  */
52 {
53  double kval;
54 
55  kval = 2.0 * M_PI * m_parameters[FREQUENCY_PRM]
57 
58  return kval * kval;
59 }
60 
61 
62 /*
63  * given mode numbers m and n
64  * returns square of cutoff kc value
65  */
66 double RECTWAVEGUIDE::kc_square( int m, int n )
67 {
68  return pow( ( m * M_PI / m_parameters[PHYS_A_PRM] ), 2.0 )
69  + pow( ( n * M_PI / m_parameters[PHYS_B_PRM] ), 2.0 );
70 }
71 
72 
73 /*
74  * given mode numbers m and n
75  * returns cutoff fc value
76  */
77 double RECTWAVEGUIDE::fc( int m, int n )
78 {
79  return sqrt( kc_square( m, n ) / m_parameters[MUR_PRM] / m_parameters[EPSILONR_PRM] ) * C0 / 2.0
80  / M_PI;
81 }
82 
83 
84 /*
85  * alphac - returns attenuation due to conductor losses for all propagating
86  * modes in the waveguide
87  */
89 {
90  double Rs, f_c;
91  double ac;
92  short m, n, mmax, nmax;
93  double* a = &m_parameters[PHYS_A_PRM];
94  double* b = &m_parameters[PHYS_B_PRM];
95  double* f = &m_parameters[FREQUENCY_PRM];
96  double* murc = &m_parameters[MURC_PRM];
97  double* sigma = &m_parameters[SIGMA_PRM];
98 
99  Rs = sqrt( M_PI * *f * *murc * MU0 / *sigma );
100  ac = 0.0;
101  mmax = (int) floor( *f / fc( 1, 0 ) );
102  nmax = mmax;
103 
104  /* below from Ramo, Whinnery & Van Duzer */
105 
106  /* TE(m,n) modes */
107  for( n = 0; n <= nmax; n++ )
108  {
109  for( m = 1; m <= mmax; m++ )
110  {
111  f_c = fc( m, n );
112 
113  if( *f > f_c )
114  {
115  switch( n )
116  {
117  case 0:
118  ac += ( Rs / ( *b * ZF0 * sqrt( 1.0 - pow( ( f_c / *f ), 2.0 ) ) ) )
119  * ( 1.0 + ( ( 2 * *b / *a ) * pow( ( f_c / *f ), 2.0 ) ) );
120  break;
121 
122  default:
123  ac += ( ( 2. * Rs ) / ( *b * ZF0 * sqrt( 1.0 - pow( ( f_c / *f ), 2.0 ) ) ) )
124  * ( ( ( 1. + ( *b / *a ) ) * pow( ( f_c / *f ), 2.0 ) )
125  + ( ( 1. - pow( ( f_c / *f ), 2.0 ) )
126  * ( ( ( *b / *a )
127  * ( ( ( *b / *a ) * pow( m, 2. ) )
128  + pow( n, 2. ) ) )
129  / ( pow( ( *b * m / *a ), 2.0 )
130  + pow( n, 2.0 ) ) ) ) );
131  break;
132  }
133  }
134  }
135  }
136 
137  /* TM(m,n) modes */
138  for( n = 1; n <= nmax; n++ )
139  {
140  for( m = 1; m <= mmax; m++ )
141  {
142  f_c = fc( m, n );
143 
144  if( *f > f_c )
145  {
146  ac += ( ( 2. * Rs ) / ( *b * ZF0 * sqrt( 1.0 - pow( ( f_c / *f ), 2.0 ) ) ) )
147  * ( ( ( pow( m, 2.0 ) * pow( ( *b / *a ), 3.0 ) ) + pow( n, 2. ) )
148  / ( ( pow( ( m * *b / *a ), 2. ) ) + pow( n, 2.0 ) ) );
149  }
150  }
151  }
152 
153  ac = ac * 20.0 * log10( exp( 1. ) ); /* convert from Np/m to db/m */
154  return ac;
155 }
156 
157 
158 /*
159  * alphac_cutoff - returns attenuation for a cutoff wg
160  */
162 {
163  double acc;
164 
165  acc = sqrt( kc_square( 1, 0 ) - kval_square() );
166  acc = 20 * log10( exp( 1.0 ) ) * acc;
167  return acc;
168 }
169 
170 
171 /*
172  * returns attenuation due to dielectric losses
173  */
175 {
176  double k_square, beta;
177  double ad;
178 
179  k_square = kval_square();
180  beta = sqrt( k_square - kc_square( 1, 0 ) );
181 
182  ad = ( k_square * m_parameters[TAND_PRM] ) / ( 2.0 * beta );
183  ad = ad * 20.0 * log10( exp( 1. ) ); /* convert from Np/m to db/m */
184  return ad;
185 }
186 
187 
188 /*
189  * get_rectwaveguide_sub
190  * get and assign rectwaveguide substrate parameters
191  * into rectwaveguide structure
192  */
194 {
200 }
201 
202 
203 /*
204  * get_rectwaveguide_comp
205  * get and assign rectwaveguide component parameters
206  * into rectwaveguide structure
207  */
209 {
211 }
212 
213 
214 /*
215  * get_rectwaveguide_elec
216  * get and assign rectwaveguide electrical parameters
217  * into rectwaveguide structure
218  */
220 {
223 }
224 
225 
226 /*
227  * get_rectwaveguide_phys
228  * get and assign rectwaveguide physical parameters
229  * into rectwaveguide structure
230  */
232 {
236 }
237 
238 
239 /*
240  * analyze - analysis function
241  * source: https://empossible.net/wp-content/uploads/2018/03/Lecture-5c-Rectangular-waveguide.pdf
242  */
244 {
245  double lambda_g;
246  double k_square;
247 
248  k_square = kval_square();
249 
250  if( kc_square( 1, 0 ) <= k_square )
251  {
252  /* propagating modes */
253 
254  // Z0 definition using fictive voltages and currents
257  / sqrt( 1.0 - pow( ( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM] ), 2.0 ) );
258 
259  /* calculate electrical angle */
260  lambda_g = 2.0 * M_PI / sqrt( k_square - kc_square( 1, 0 ) );
262  2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g; /* in radians */
266  ( 1.0 - pow( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM], 2.0 ) );
267  }
268  else
269  {
270  /* evanascent modes */
271  m_parameters[Z0_PRM] = 0;
272  m_parameters[ANG_L_PRM] = 0;
276  }
277 }
278 
279 /*
280  * synthesize - synthesis function
281  * source: re-arrangment of calcAnalyze equation
282  * TE10 (via fc(1,0) ) results in the b term not influencing the result, as long as
283  * 1) fc > f
284  * 2) a > b
285  */
287 {
288  double lambda_g, k_square, beta;
289  /* solve for a */
291  C0
292  / ( sqrt( ( m_parameters[MUR_PRM] * m_parameters[EPSILONR_PRM] ) ) * 2
293  * m_parameters[FREQUENCY_PRM] * sqrt( 1
294  - pow( ( ZF0 * sqrt( m_parameters[MUR_PRM]
297  ,2.0 ) ) );
298 
299  k_square = kval_square();
300  beta = sqrt( k_square - kc_square( 1, 0 ) );
301  lambda_g = 2.0 * M_PI / beta;
302  m_parameters[PHYS_LEN_PRM] = ( m_parameters[ANG_L_PRM] * lambda_g ) / ( 2.0 * M_PI ); /* in m */
303 
304  if( kc_square( 1, 0 ) <= k_square )
305  {
306  /*propagating modes */
307  beta = sqrt( k_square - kc_square( 1, 0 ) );
308  lambda_g = 2.0 * M_PI / beta;
312  ( 1.0 - pow( ( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM] ), 2.0 ) );
313  }
314  else
315  {
316  /*evanascent modes */
317  m_parameters[Z0_PRM] = 0;
318  m_parameters[ANG_L_PRM] = 0;
322  }
323 }
324 
326 {
327  if( isSelected( PHYS_A_PRM ) )
329 
330  if( isSelected( PHYS_B_PRM ) )
332 
334 
335  // Check for errors
336  if( !std::isfinite( m_parameters[PHYS_A_PRM] ) || m_parameters[PHYS_A_PRM] <= 0 )
338 
339  if( !std::isfinite( m_parameters[PHYS_B_PRM] ) || m_parameters[PHYS_B_PRM] <= 00 )
341 
342  // Check for warnings
343  if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
345 
346  if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
348 }
349 
350 
352 {
355 
356  // Check for errors
357  if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
359 
360  if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
362 
363  // Check for warnings
364  if( !std::isfinite( m_parameters[PHYS_A_PRM] ) || m_parameters[PHYS_A_PRM] <= 0 )
366 
367  if( !std::isfinite( m_parameters[PHYS_B_PRM] ) || m_parameters[PHYS_B_PRM] <= 00 )
369 }
370 
371 
373 {
374  int m, n, max = 6;
375  wxString text;
376 
377  // Z0EH = Ey / Hx (definition with field quantities)
378  Z0EH = ZF0 * sqrt( kval_square() / ( kval_square() - kc_square( 1, 0 ) ) );
379  setResult( 0, Z0EH, wxT( "Ohm" ) );
380 
382  setResult( 2, m_parameters[LOSS_CONDUCTOR_PRM], wxT( "dB" ) );
383  setResult( 3, m_parameters[LOSS_DIELECTRIC_PRM], wxT( "dB" ) );
384 
385  // show possible TE modes (H modes)
386  if( m_parameters[FREQUENCY_PRM] < fc( 1, 0 ) )
387  {
388  text = wxT( "none" );
389  }
390  else
391  {
392  for( m = 0; m <= max; m++ )
393  {
394  for( n = 0; n <= max; n++ )
395  {
396  if( ( m == 0 ) && ( n == 0 ) )
397  continue;
398 
399  if( m_parameters[FREQUENCY_PRM] >= ( fc( m, n ) ) )
400  text << wxString::Format( wxT( "H(%d,%d) " ), m, n );
401  }
402  }
403  }
404  setResult( 4, text );
405 
406  // show possible TM modes (E modes)
407  if( m_parameters[FREQUENCY_PRM] < fc( 1, 1 ) )
408  {
409  text = wxT( "none" );
410  }
411  else
412  {
413  text.Clear();
414 
415  for( m = 1; m <= max; m++ )
416  {
417  for( n = 1; n <= max; n++ )
418  {
419  if( m_parameters[FREQUENCY_PRM] >= fc( m, n ) )
420  text << wxString::Format( wxT( "E(%d,%d) " ), m, n );
421  }
422  }
423  }
424 
425  setResult( 5, text );
426 }
bool isSelected(enum PRMS_ID aPrmId)
Definition: transline.cpp:127
void setResult(int, const wxString &)
Definition: transline.cpp:135
double kval_square()
void showSynthesize() override
Shows analysis results and checks for errors / warnings.
void Init()
Definition: transline.cpp:98
#define MU0
Definition: units.h:60
void get_rectwaveguide_comp()
void calcSynthesize() override
Computation for synthesis.
void setProperty(enum PRMS_ID aPrmId, double aValue)
Definition: transline.cpp:117
void get_rectwaveguide_sub()
#define PHYS_B_PRM
Definition: rectwaveguide.h:31
void show_results() override
Shows results.
void get_rectwaveguide_elec()
double alphac_cutoff()
#define ZF0
Definition: units.h:62
double m_parameters[EXTRA_PRMS_COUNT]
Definition: transline.h:131
void get_rectwaveguide_phys()
double getProperty(enum PRMS_ID aPrmId)
Definition: transline.cpp:148
void showAnalyze() override
Shows synthesis results and checks for errors / warnings.
const char * m_Name
Definition: transline.h:84
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
#define C0
Definition: units.h:61
#define TRANSLINE_ERROR
Definition: transline.h:31
void calcAnalyze() override
Computation for analysis.
double fc(int, int)
double kc_square(int, int)
#define PHYS_A_PRM
Definition: rectwaveguide.h:30
#define TRANSLINE_WARNING
Definition: transline.h:30
void setErrorLevel(PRMS_ID, char)
@function setErrorLevel
Definition: transline.cpp:443