You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

415 lines
11 KiB

  1. /*
  2. * rectwaveguide.cpp - rectangular waveguide class implementation
  3. *
  4. * Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
  5. * Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
  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. #include <stdio.h>
  24. #include <string.h>
  25. #include <cmath>
  26. #include <units.h>
  27. #include <transline.h>
  28. #include <rectwaveguide.h>
  29. RECTWAVEGUIDE::RECTWAVEGUIDE() : TRANSLINE()
  30. {
  31. m_name = "RectWaveGuide";
  32. // Initialize these here variables mainly to avoid warnings from a static analyzer
  33. mur = 0.0; // magnetic permeability of substrate
  34. tanm = 0.0; // Magnetic Loss Tangent
  35. a = 0.0; // width of waveguide
  36. b = 0.0; // height of waveguide
  37. l = 0.0; // length of waveguide
  38. Z0 = 0.0; // characteristic impedance
  39. Z0EH = 0.0; // characteristic impedance of field quantities*/
  40. ang_l = 0.0; // Electrical length in angle
  41. er_eff = 0.0; // Effective dielectric constant
  42. mur_eff = 0.0; // Effective mag. permeability
  43. atten_dielectric = 0.0; // Loss in dielectric (dB)
  44. atten_cond = 0.0; // Loss in conductors (dB)
  45. fc10 = 0.0; // Cutoff frequency for TE10 mode
  46. }
  47. /*
  48. * returns square of k
  49. */
  50. double RECTWAVEGUIDE::kval_square()
  51. {
  52. double kval;
  53. kval = 2.0* M_PI* f* sqrt( mur* er ) / C0;
  54. return kval * kval;
  55. }
  56. /*
  57. * given mode numbers m and n
  58. * returns square of cutoff kc value
  59. */
  60. double RECTWAVEGUIDE::kc_square( int m, int n )
  61. {
  62. return pow( (m * M_PI / a), 2.0 ) + pow( (n * M_PI / b), 2.0 );
  63. }
  64. /*
  65. * given mode numbers m and n
  66. * returns cutoff fc value
  67. */
  68. double RECTWAVEGUIDE::fc( int m, int n )
  69. {
  70. return sqrt( kc_square( m, n ) / mur / er ) * C0 / 2.0 / M_PI;
  71. }
  72. /*
  73. * alphac - returns attenuation due to conductor losses for all propagating
  74. * modes in the waveguide
  75. */
  76. double RECTWAVEGUIDE::alphac()
  77. {
  78. double Rs, f_c;
  79. double ac;
  80. short m, n, mmax, nmax;
  81. Rs = sqrt( M_PI * f * murC * MU0 / sigma );
  82. ac = 0.0;
  83. mmax = (int) floor( f / fc( 1, 0 ) );
  84. nmax = mmax;
  85. /* below from Ramo, Whinnery & Van Duzer */
  86. /* TE(m,n) modes */
  87. for( n = 0; n<= nmax; n++ )
  88. {
  89. for( m = 1; m <= mmax; m++ )
  90. {
  91. f_c = fc( m, n );
  92. if( f > f_c )
  93. {
  94. switch( n )
  95. {
  96. case 0:
  97. ac += ( Rs / ( b * ZF0 * sqrt( 1.0 - pow( (f_c / f), 2.0 ) ) ) ) *
  98. ( 1.0 + ( (2 * b / a) * pow( (f_c / f), 2.0 ) ) );
  99. break;
  100. default:
  101. ac += ( (2. * Rs) / ( b * ZF0 * sqrt( 1.0 - pow( (f_c / f), 2.0 ) ) ) ) *
  102. ( ( ( 1. + (b / a) ) * pow( (f_c / f), 2.0 ) ) +
  103. ( ( 1. -
  104. pow( (f_c / f),
  105. 2.0 ) ) *
  106. ( ( (b / a) * ( ( (b / a) * pow( m, 2. ) ) + pow( n, 2. ) ) ) /
  107. ( pow( (b * m / a),
  108. 2.0 ) + pow( n, 2.0 ) ) ) ) );
  109. break;
  110. }
  111. }
  112. }
  113. }
  114. /* TM(m,n) modes */
  115. for( n = 1; n<= nmax; n++ )
  116. {
  117. for( m = 1; m<= mmax; m++ )
  118. {
  119. f_c = fc( m, n );
  120. if( f > f_c )
  121. {
  122. ac += ( (2. * Rs) / ( b * ZF0 * sqrt( 1.0 - pow( (f_c / f), 2.0 ) ) ) ) *
  123. ( ( ( pow( m, 2.0 ) * pow( (b / a), 3.0 ) ) + pow( n, 2. ) ) /
  124. ( ( pow( (m * b / a), 2. ) ) + pow( n, 2.0 ) ) );
  125. }
  126. }
  127. }
  128. ac = ac * 20.0 * log10( exp( 1. ) ); /* convert from Np/m to db/m */
  129. return ac;
  130. }
  131. /*
  132. * alphac_cutoff - returns attenuation for a cutoff wg
  133. */
  134. double RECTWAVEGUIDE::alphac_cutoff()
  135. {
  136. double acc;
  137. acc = sqrt( kc_square( 1, 0 ) - kval_square() );
  138. acc = 20 * log10( exp( 1.0 ) ) * acc;
  139. return acc;
  140. }
  141. /*
  142. * returns attenuation due to dielectric losses
  143. */
  144. double RECTWAVEGUIDE::alphad()
  145. {
  146. double k_square, beta;
  147. double ad;
  148. k_square = kval_square();
  149. beta = sqrt( k_square - kc_square( 1, 0 ) );
  150. ad = (k_square * tand) / (2.0 * beta);
  151. ad = ad * 20.0 * log10( exp( 1. ) ); /* convert from Np/m to db/m */
  152. return ad;
  153. }
  154. /*
  155. * get_rectwaveguide_sub
  156. * get and assign rectwaveguide substrate parameters
  157. * into rectwaveguide structure
  158. */
  159. void RECTWAVEGUIDE::get_rectwaveguide_sub()
  160. {
  161. er = getProperty( EPSILONR_PRM );
  162. mur = getProperty( MUR_PRM );
  163. murC = getProperty( MURC_PRM );
  164. sigma = 1.0 / getProperty( RHO_PRM );
  165. tand = getProperty( TAND_PRM );
  166. tanm = getProperty( TANM_PRM );
  167. }
  168. /*
  169. * get_rectwaveguide_comp
  170. * get and assign rectwaveguide component parameters
  171. * into rectwaveguide structure
  172. */
  173. void RECTWAVEGUIDE::get_rectwaveguide_comp()
  174. {
  175. f = getProperty( FREQUENCY_PRM );
  176. }
  177. /*
  178. * get_rectwaveguide_elec
  179. * get and assign rectwaveguide electrical parameters
  180. * into rectwaveguide structure
  181. */
  182. void RECTWAVEGUIDE::get_rectwaveguide_elec()
  183. {
  184. Z0 = getProperty( Z0_PRM );
  185. ang_l = getProperty( ANG_L_PRM );
  186. }
  187. /*
  188. * get_rectwaveguide_phys
  189. * get and assign rectwaveguide physical parameters
  190. * into rectwaveguide structure
  191. */
  192. void RECTWAVEGUIDE::get_rectwaveguide_phys()
  193. {
  194. a = getProperty( PHYS_WIDTH_PRM );
  195. b = getProperty( PHYS_S_PRM );
  196. l = getProperty( PHYS_LEN_PRM );
  197. }
  198. /*
  199. * analyze - analysis function
  200. */
  201. void RECTWAVEGUIDE::analyze()
  202. {
  203. double lambda_g;
  204. double k_square;
  205. /* Get and assign substrate parameters */
  206. get_rectwaveguide_sub();
  207. /* Get and assign component parameters */
  208. get_rectwaveguide_comp();
  209. /* Get and assign physical parameters */
  210. get_rectwaveguide_phys();
  211. k_square = kval_square();
  212. if( kc_square( 1, 0 ) <= k_square )
  213. {
  214. /* propagating modes */
  215. // Z0 definition using fictive voltages and currents
  216. Z0 = 2.0* ZF0* sqrt( mur / er ) * (b / a) / sqrt( 1.0 - pow( (fc( 1, 0 ) / f), 2.0 ) );
  217. /* calculate electrical angle */
  218. lambda_g = 2.0 * M_PI / sqrt( k_square - kc_square( 1, 0 ) );
  219. ang_l = 2.0 * M_PI * l / lambda_g; /* in radians */
  220. atten_cond = alphac() * l;
  221. atten_dielectric = alphad() * l;
  222. er_eff = ( 1.0 - pow( fc( 1, 0 ) / f, 2.0 ) );
  223. }
  224. else
  225. {
  226. /* evanascent modes */
  227. Z0 = 0;
  228. ang_l = 0;
  229. er_eff = 0;
  230. atten_dielectric = 0.0;
  231. atten_cond = alphac_cutoff() * l;
  232. }
  233. setProperty( Z0_PRM, Z0 );
  234. setProperty( ANG_L_PRM, ang_l );
  235. show_results();
  236. }
  237. /*
  238. * synthesize - synthesis function
  239. */
  240. void RECTWAVEGUIDE::synthesize()
  241. {
  242. double lambda_g, k_square, beta;
  243. /* Get and assign substrate parameters */
  244. get_rectwaveguide_sub();
  245. /* Get and assign component parameters */
  246. get_rectwaveguide_comp();
  247. /* Get and assign electrical parameters */
  248. get_rectwaveguide_elec();
  249. /* Get and assign physical parameters */
  250. get_rectwaveguide_phys();
  251. if( isSelected( PHYS_S_PRM ) )
  252. {
  253. /* solve for b */
  254. b = Z0 * a * sqrt( 1.0 - pow( fc( 1, 0 ) / f, 2.0 ) ) / ( 2.0 * ZF0 * sqrt( mur / er ) );
  255. setProperty( PHYS_S_PRM, b );
  256. }
  257. else if( isSelected( PHYS_WIDTH_PRM ) )
  258. {
  259. /* solve for a */
  260. a = sqrt( pow( 2.0 * ZF0 * b / Z0, 2.0 ) + pow( C0 / (2.0 * f), 2.0 ) );
  261. setProperty( PHYS_WIDTH_PRM, a );
  262. }
  263. k_square = kval_square();
  264. beta = sqrt( k_square - kc_square( 1, 0 ) );
  265. lambda_g = 2.0 * M_PI / beta;
  266. l = (ang_l * lambda_g) / (2.0 * M_PI); /* in m */
  267. setProperty( PHYS_LEN_PRM, l );
  268. if( kc_square( 1, 0 ) <= k_square )
  269. {
  270. /*propagating modes */
  271. beta = sqrt( k_square - kc_square( 1, 0 ) );
  272. lambda_g = 2.0 * M_PI / beta;
  273. atten_cond = alphac() * l;
  274. atten_dielectric = alphad() * l;
  275. er_eff = ( 1.0 - pow( (fc( 1, 0 ) / f), 2.0 ) );
  276. }
  277. else
  278. {
  279. /*evanascent modes */
  280. Z0 = 0;
  281. ang_l = 0;
  282. er_eff = 0;
  283. atten_dielectric = 0.0;
  284. atten_cond = alphac_cutoff() * l;
  285. }
  286. show_results();
  287. }
  288. #define MAXSTRLEN 128
  289. void RECTWAVEGUIDE::show_results()
  290. {
  291. int m, n, max = 6;
  292. char text[MAXSTRLEN], txt[32];
  293. // Z0EH = Ey / Hx (definition with field quantities)
  294. Z0EH = ZF0 * sqrt( kval_square() / ( kval_square() - kc_square( 1, 0 ) ) );
  295. setResult( 0, Z0EH, "Ohm" );
  296. setResult( 1, er_eff, "" );
  297. setResult( 2, atten_cond, "dB" );
  298. setResult( 3, atten_dielectric, "dB" );
  299. // show possible TE modes (H modes)
  300. if( f < fc( 1, 0 ) )
  301. strcpy( text, "none" );
  302. else
  303. {
  304. strcpy( text, "" );
  305. for( m = 0; m<= max; m++ )
  306. {
  307. for( n = 0; n<= max; n++ )
  308. {
  309. if( (m == 0) && (n == 0) )
  310. continue;
  311. if( f >= ( fc( m, n ) ) )
  312. {
  313. sprintf( txt, "H(%d,%d) ", m, n );
  314. if( (strlen( text ) + strlen( txt ) + 5) < MAXSTRLEN )
  315. strcat( text, txt );
  316. else
  317. {
  318. strcat( text, "..." );
  319. m = n = max + 1; // print no more modes
  320. }
  321. }
  322. }
  323. }
  324. }
  325. setResult( 4, text );
  326. // show possible TM modes (E modes)
  327. if( f < fc( 1, 1 ) )
  328. strcpy( text, "none" );
  329. else
  330. {
  331. strcpy( text, "" );
  332. for( m = 1; m<= max; m++ )
  333. {
  334. for( n = 1; n<= max; n++ )
  335. {
  336. if( f >= fc( m, n ) )
  337. {
  338. sprintf( txt, "E(%d,%d) ", m, n );
  339. if( (strlen( text ) + strlen( txt ) + 5) < MAXSTRLEN )
  340. strcat( text, txt );
  341. else
  342. {
  343. strcat( text, "..." );
  344. m = n = max + 1; // print no more modes
  345. }
  346. }
  347. }
  348. }
  349. }
  350. setResult( 5, text );
  351. }