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.

970 lines
34 KiB

  1. /*
  2. * c_microstrip.cpp - coupled microstrip class implementation
  3. *
  4. * Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
  5. * Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * 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. /* c_microstrip.c - Puts up window for coupled microstrips and
  24. * performs the associated calculations
  25. * Based on the original microstrip.c by Gopal Narayanan
  26. */
  27. #include <cmath>
  28. #include <cstdio>
  29. #include <cstdlib>
  30. #include <cstring>
  31. #include "c_microstrip.h"
  32. #include "microstrip.h"
  33. #include "transline.h"
  34. #include "units.h"
  35. C_MICROSTRIP::C_MICROSTRIP() : TRANSLINE(),
  36. h( 0.0 ), // height of substrate
  37. ht( 0.0 ), // height to the top of box
  38. t( 0.0 ), // thickness of top metal
  39. rough( 0.0 ), // Roughness of top metal
  40. w( 0.0 ), // width of lines
  41. w_t_e( 0.0 ), // even-mode thickness-corrected line width
  42. w_t_o( 0.0 ), // odd-mode thickness-corrected line width
  43. l( 0.0 ), // length of lines
  44. s( 0.0 ), // spacing of lines
  45. Z0_e_0( 0.0 ), // static even-mode impedance
  46. Z0_o_0( 0.0 ), // static odd-mode impedance
  47. Z0e( 0.0 ), // even-mode impedance
  48. Z0o( 0.0 ), // odd-mode impedance
  49. c_e( 0.0 ), // even-mode capacitance
  50. c_o( 0.0 ), // odd-mode capacitance
  51. ang_l_e( 0.0 ), // even-mode electrical length in angle
  52. ang_l_o( 0.0 ), // odd-mode electrical length in angle
  53. er_eff_e( 0.0 ), // even-mode effective dielectric constant
  54. er_eff_o( 0.0 ), // odd-mode effective dielectric constant
  55. er_eff_e_0( 0.0 ), // static even-mode effective dielectric constant
  56. er_eff_o_0( 0.0 ), // static odd-mode effective dielectric constant
  57. w_eff( 0.0 ), // Effective width of line
  58. atten_dielectric_e( 0.0 ), // even-mode dielectric losses (dB)
  59. atten_cond_e( 0.0 ), // even-mode conductors losses (dB)
  60. atten_dielectric_o( 0.0 ), // odd-mode dielectric losses (dB)
  61. atten_cond_o( 0.0 ), // odd-mode conductors losses (dB)
  62. aux_ms( nullptr )
  63. {
  64. m_Name = "Coupled_MicroStrip";
  65. Init();
  66. }
  67. C_MICROSTRIP::~C_MICROSTRIP()
  68. {
  69. delete aux_ms;
  70. }
  71. /*
  72. * delta_u_thickness_single() computes the thickness effect on
  73. * normalized width for a single microstrip line
  74. *
  75. * References: H. A. Atwater, "Simplified Design Equations for
  76. * Microstrip Line Parameters", Microwave Journal, pp. 109-115,
  77. * November 1989.
  78. */
  79. double C_MICROSTRIP::delta_u_thickness_single( double u, double t_h )
  80. {
  81. double delta_u;
  82. if( t_h > 0.0 )
  83. {
  84. delta_u =
  85. (1.25 * t_h /
  86. M_PI) *
  87. ( 1.0 +
  88. log( ( 2.0 +
  89. (4.0 * M_PI * u -
  90. 2.0) / ( 1.0 + exp( -100.0 * ( u - 1.0 / (2.0 * M_PI) ) ) ) ) / t_h ) );
  91. }
  92. else
  93. {
  94. delta_u = 0.0;
  95. }
  96. return delta_u;
  97. }
  98. /*
  99. * delta_u_thickness() - compute the thickness effect on normalized
  100. * width for coupled microstrips
  101. *
  102. * References: Rolf Jansen, "High-Speed Computation of Single and
  103. * Coupled Microstrip Parameters Including Dispersion, High-Order
  104. * Modes, Loss and Finite Strip Thickness", IEEE Trans. MTT, vol. 26,
  105. * no. 2, pp. 75-82, Feb. 1978
  106. */
  107. void C_MICROSTRIP::delta_u_thickness()
  108. {
  109. double e_r, u, g, t_h;
  110. double delta_u, delta_t, delta_u_e, delta_u_o;
  111. e_r = m_parameters[EPSILONR_PRM];
  112. u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM]; /* normalized line width */
  113. g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalized line spacing */
  114. t_h = m_parameters[T_PRM] / m_parameters[H_PRM]; /* normalized strip thickness */
  115. if( t_h > 0.0 )
  116. {
  117. /* single microstrip correction for finite strip thickness */
  118. delta_u = delta_u_thickness_single( u, t_h );
  119. delta_t = t_h / ( g * e_r );
  120. /* thickness correction for the even- and odd-mode */
  121. delta_u_e = delta_u * ( 1.0 - 0.5 * exp( -0.69 * delta_u / delta_t ) );
  122. delta_u_o = delta_u_e + delta_t;
  123. }
  124. else
  125. {
  126. delta_u_e = delta_u_o = 0.0;
  127. }
  128. w_t_e = m_parameters[PHYS_WIDTH_PRM] + delta_u_e * m_parameters[H_PRM];
  129. w_t_o = m_parameters[PHYS_WIDTH_PRM] + delta_u_o * m_parameters[H_PRM];
  130. }
  131. /*
  132. * compute various parameters for a single line
  133. */
  134. void C_MICROSTRIP::compute_single_line()
  135. {
  136. if( aux_ms == NULL )
  137. aux_ms = new MICROSTRIP();
  138. /* prepare parameters for single microstrip computations */
  139. aux_ms->m_parameters[EPSILONR_PRM] = m_parameters[EPSILONR_PRM];
  140. aux_ms->m_parameters[PHYS_WIDTH_PRM] = m_parameters[PHYS_WIDTH_PRM];
  141. aux_ms->m_parameters[H_PRM] = m_parameters[H_PRM];
  142. aux_ms->m_parameters[T_PRM] = 0.0;
  143. //aux_ms->m_parameters[H_T_PRM] = m_parameters[H_T_PRM];
  144. aux_ms->m_parameters[H_T_PRM] = 1e12; /* arbitrarily high */
  145. aux_ms->m_parameters[FREQUENCY_PRM] = m_parameters[FREQUENCY_PRM];
  146. aux_ms->m_parameters[MURC_PRM] = m_parameters[MURC_PRM];
  147. aux_ms->microstrip_Z0();
  148. aux_ms->dispersion();
  149. }
  150. /*
  151. * filling_factor_even() - compute the filling factor for the coupled
  152. * microstrips even-mode without cover and zero conductor thickness
  153. */
  154. double C_MICROSTRIP::filling_factor_even( double u, double g, double e_r )
  155. {
  156. double v, v3, v4, a_e, b_e, q_inf;
  157. v = u * ( 20.0 + g * g ) / ( 10.0 + g * g ) + g * exp( -g );
  158. v3 = v * v * v;
  159. v4 = v3 * v;
  160. a_e = 1.0 + log( ( v4 + v * v / 2704.0 ) / ( v4 + 0.432 ) ) / 49.0
  161. + log( 1.0 + v3 / 5929.741 ) / 18.7;
  162. b_e = 0.564 * pow( ( ( e_r - 0.9 ) / ( e_r + 3.0 ) ), 0.053 );
  163. /* filling factor, with width corrected for thickness */
  164. q_inf = pow( ( 1.0 + 10.0 / v ), -a_e * b_e );
  165. return q_inf;
  166. }
  167. /**
  168. * filling_factor_odd() - compute the filling factor for the coupled
  169. * microstrips odd-mode without cover and zero conductor thickness
  170. */
  171. double C_MICROSTRIP::filling_factor_odd( double u, double g, double e_r )
  172. {
  173. double b_odd = 0.747 * e_r / ( 0.15 + e_r );
  174. double c_odd = b_odd - ( b_odd - 0.207 ) * exp( -0.414 * u );
  175. double d_odd = 0.593 + 0.694 * exp( -0.562 * u );
  176. /* filling factor, with width corrected for thickness */
  177. double q_inf = exp( -c_odd * pow( g, d_odd ) );
  178. return q_inf;
  179. }
  180. /*
  181. * delta_q_cover_even() - compute the cover effect on filling factor
  182. * for the even-mode
  183. */
  184. double C_MICROSTRIP::delta_q_cover_even( double h2h )
  185. {
  186. double q_c;
  187. if( h2h <= 39 )
  188. {
  189. q_c = tanh( 1.626 + 0.107 * h2h - 1.733 / sqrt( h2h ) );
  190. }
  191. else
  192. {
  193. q_c = 1.0;
  194. }
  195. return q_c;
  196. }
  197. /*
  198. * delta_q_cover_odd() - compute the cover effect on filling factor
  199. * for the odd-mode
  200. */
  201. double C_MICROSTRIP::delta_q_cover_odd( double h2h )
  202. {
  203. double q_c;
  204. if( h2h <= 7 )
  205. {
  206. q_c = tanh( 9.575 / ( 7.0 - h2h ) - 2.965 + 1.68 * h2h - 0.311 * h2h * h2h );
  207. }
  208. else
  209. {
  210. q_c = 1.0;
  211. }
  212. return q_c;
  213. }
  214. /**
  215. * er_eff_static() - compute the static effective dielectric constants
  216. *
  217. * References: Manfred Kirschning and Rolf Jansen, "Accurate
  218. * Wide-Range Design Equations for the Frequency-Dependent
  219. * Characteristic of Parallel Coupled Microstrip Lines", IEEE
  220. * Trans. MTT, vol. 32, no. 1, Jan. 1984
  221. */
  222. void C_MICROSTRIP::er_eff_static()
  223. {
  224. double u_t_e, u_t_o, g, h2, h2h;
  225. double a_o, t_h, q, q_c, q_t, q_inf;
  226. double er_eff_single;
  227. double er;
  228. er = m_parameters[EPSILONR_PRM];
  229. /* compute zero-thickness single line parameters */
  230. compute_single_line();
  231. er_eff_single = aux_ms->er_eff_0;
  232. h2 = m_parameters[H_T_PRM];
  233. u_t_e = w_t_e / m_parameters[H_PRM]; /* normalized even_mode line width */
  234. u_t_o = w_t_o / m_parameters[H_PRM]; /* normalized odd_mode line width */
  235. g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalized line spacing */
  236. h2h = h2 / m_parameters[H_PRM]; /* normalized cover height */
  237. t_h = m_parameters[T_PRM] / m_parameters[H_PRM]; /* normalized strip thickness */
  238. /* filling factor, computed with thickness corrected width */
  239. q_inf = filling_factor_even( u_t_e, g, er );
  240. /* cover effect */
  241. q_c = delta_q_cover_even( h2h );
  242. /* thickness effect */
  243. q_t = aux_ms->delta_q_thickness( u_t_e, t_h );
  244. /* resultant filling factor */
  245. q = ( q_inf - q_t ) * q_c;
  246. /* static even-mode effective dielectric constant */
  247. er_eff_e_0 = 0.5 * ( er + 1.0 ) + 0.5 * ( er - 1.0 ) * q;
  248. /* filling factor, with width corrected for thickness */
  249. q_inf = filling_factor_odd( u_t_o, g, er );
  250. /* cover effect */
  251. q_c = delta_q_cover_odd( h2h );
  252. /* thickness effect */
  253. q_t = aux_ms->delta_q_thickness( u_t_o, t_h );
  254. /* resultant filling factor */
  255. q = ( q_inf - q_t ) * q_c;
  256. a_o = 0.7287 * ( er_eff_single - 0.5 * ( er + 1.0 ) ) * ( 1.0 - exp( -0.179 * u_t_o ) );
  257. /* static odd-mode effective dielectric constant */
  258. er_eff_o_0 = ( 0.5 * ( er + 1.0 ) + a_o - er_eff_single ) * q + er_eff_single;
  259. }
  260. /**
  261. * delta_Z0_even_cover() - compute the even-mode impedance correction
  262. * for a homogeneous microstrip due to the cover
  263. *
  264. * References: S. March, "Microstrip Packaging: Watch the Last Step",
  265. * Microwaves, vol. 20, no. 13, pp. 83.94, Dec. 1981.
  266. */
  267. double C_MICROSTRIP::delta_Z0_even_cover( double g, double u, double h2h )
  268. {
  269. double f_e, g_e, delta_Z0_even;
  270. double x, y, A, B, C, D, E, F;
  271. A = -4.351 / pow( 1.0 + h2h, 1.842 );
  272. B = 6.639 / pow( 1.0 + h2h, 1.861 );
  273. C = -2.291 / pow( 1.0 + h2h, 1.90 );
  274. f_e = 1.0 - atanh( A + ( B + C * u ) * u );
  275. x = pow( 10.0, 0.103 * g - 0.159 );
  276. y = pow( 10.0, 0.0492 * g - 0.073 );
  277. D = 0.747 / sin( 0.5 * M_PI * x );
  278. E = 0.725 * sin( 0.5 * M_PI * y );
  279. F = pow( 10.0, 0.11 - 0.0947 * g );
  280. g_e = 270.0 * ( 1.0 - tanh( D + E * sqrt( 1.0 + h2h ) - F / ( 1.0 + h2h ) ) );
  281. delta_Z0_even = f_e * g_e;
  282. return delta_Z0_even;
  283. }
  284. /**
  285. * delta_Z0_odd_cover() - compute the odd-mode impedance correction
  286. * for a homogeneous microstrip due to the cover
  287. *
  288. * References: S. March, "Microstrip Packaging: Watch the Last Step",
  289. * Microwaves, vol. 20, no. 13, pp. 83.94, Dec. 1981.
  290. */
  291. double C_MICROSTRIP::delta_Z0_odd_cover( double g, double u, double h2h )
  292. {
  293. double f_o, g_o, delta_Z0_odd;
  294. double G, J, K, L;
  295. J = tanh( pow( 1.0 + h2h, 1.585 ) / 6.0 );
  296. f_o = pow( u, J );
  297. G = 2.178 - 0.796 * g;
  298. if( g > 0.858 )
  299. {
  300. K = log10( 20.492 * pow( g, 0.174 ) );
  301. }
  302. else
  303. {
  304. K = 1.30;
  305. }
  306. if( g > 0.873 )
  307. {
  308. L = 2.51 * pow( g, -0.462 );
  309. }
  310. else
  311. {
  312. L = 2.674;
  313. }
  314. g_o = 270.0 * ( 1.0 - tanh( G + K * sqrt( 1.0 + h2h ) - L / ( 1.0 + h2h ) ) );
  315. delta_Z0_odd = f_o * g_o;
  316. return delta_Z0_odd;
  317. }
  318. /**
  319. * Z0_even_odd() - compute the static even- and odd-mode static
  320. * impedances
  321. *
  322. * References: Manfred Kirschning and Rolf Jansen, "Accurate
  323. * Wide-Range Design Equations for the Frequency-Dependent
  324. * Characteristic of Parallel Coupled Microstrip Lines", IEEE
  325. * Trans. MTT, vol. 32, no. 1, Jan. 1984
  326. */
  327. void C_MICROSTRIP::Z0_even_odd()
  328. {
  329. double er_eff, h2, u_t_e, u_t_o, g, h2h;
  330. double Q_1, Q_2, Q_3, Q_4, Q_5, Q_6, Q_7, Q_8, Q_9, Q_10;
  331. double delta_Z0_e_0, delta_Z0_o_0, Z0_single, er_eff_single;
  332. h2 = m_parameters[H_T_PRM];
  333. u_t_e = w_t_e / m_parameters[H_PRM]; /* normalized even-mode line width */
  334. u_t_o = w_t_o / m_parameters[H_PRM]; /* normalized odd-mode line width */
  335. g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalized line spacing */
  336. h2h = h2 / m_parameters[H_PRM]; /* normalized cover height */
  337. Z0_single = aux_ms->Z0_0;
  338. er_eff_single = aux_ms->er_eff_0;
  339. /* even-mode */
  340. er_eff = er_eff_e_0;
  341. Q_1 = 0.8695 * pow( u_t_e, 0.194 );
  342. Q_2 = 1.0 + 0.7519 * g + 0.189 * pow( g, 2.31 );
  343. Q_3 = 0.1975 + pow( ( 16.6 + pow( ( 8.4 / g ), 6.0 ) ), -0.387 )
  344. + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 3.4, 10.0 ) ) ) / 241.0;
  345. Q_4 = 2.0 * Q_1
  346. / ( Q_2 * ( exp( -g ) * pow( u_t_e, Q_3 ) + ( 2.0 - exp( -g ) ) * pow( u_t_e, -Q_3 ) ) );
  347. /* static even-mode impedance */
  348. Z0_e_0 = Z0_single * sqrt( er_eff_single / er_eff )
  349. / ( 1.0 - sqrt( er_eff_single ) * Q_4 * Z0_single / ZF0 );
  350. /* correction for cover */
  351. delta_Z0_e_0 = delta_Z0_even_cover( g, u_t_e, h2h ) / sqrt( er_eff );
  352. Z0_e_0 = Z0_e_0 - delta_Z0_e_0;
  353. /* odd-mode */
  354. er_eff = er_eff_o_0;
  355. Q_5 = 1.794 + 1.14 * log( 1.0 + 0.638 / ( g + 0.517 * pow( g, 2.43 ) ) );
  356. Q_6 = 0.2305 + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 5.8, 10.0 ) ) ) / 281.3
  357. + log( 1.0 + 0.598 * pow( g, 1.154 ) ) / 5.1;
  358. Q_7 = ( 10.0 + 190.0 * g * g ) / ( 1.0 + 82.3 * g * g * g );
  359. Q_8 = exp( -6.5 - 0.95 * log( g ) - pow( g / 0.15, 5.0 ) );
  360. Q_9 = log( Q_7 ) * ( Q_8 + 1.0 / 16.5 );
  361. Q_10 = ( Q_2 * Q_4 - Q_5 * exp( log( u_t_o ) * Q_6 * pow( u_t_o, -Q_9 ) ) ) / Q_2;
  362. /* static odd-mode impedance */
  363. Z0_o_0 = Z0_single * sqrt( er_eff_single / er_eff )
  364. / ( 1.0 - sqrt( er_eff_single ) * Q_10 * Z0_single / ZF0 );
  365. /* correction for cover */
  366. delta_Z0_o_0 = delta_Z0_odd_cover( g, u_t_o, h2h ) / sqrt( er_eff );
  367. Z0_o_0 = Z0_o_0 - delta_Z0_o_0;
  368. }
  369. /*
  370. * er_eff_freq() - compute er_eff as a function of frequency
  371. */
  372. void C_MICROSTRIP::er_eff_freq()
  373. {
  374. double P_1, P_2, P_3, P_4, P_5, P_6, P_7;
  375. double P_8, P_9, P_10, P_11, P_12, P_13, P_14, P_15;
  376. double F_e, F_o;
  377. double er_eff, u, g, f_n;
  378. u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM]; /* normalize line width */
  379. g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalize line spacing */
  380. /* normalized frequency [GHz * mm] */
  381. f_n = m_parameters[FREQUENCY_PRM] * m_parameters[H_PRM] / 1e06;
  382. er_eff = er_eff_e_0;
  383. P_1 = 0.27488 + ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) * u
  384. - 0.065683 * exp( -8.7513 * u );
  385. P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * m_parameters[EPSILONR_PRM] ) );
  386. P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
  387. P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( m_parameters[EPSILONR_PRM] / 15.916, 8.0 ) ) );
  388. P_5 = 0.334 * exp( -3.3 * pow( m_parameters[EPSILONR_PRM] / 15.0, 3.0 ) ) + 0.746;
  389. P_6 = P_5 * exp( -pow( f_n / 18.0, 0.368 ) );
  390. P_7 = 1.0
  391. + 4.069 * P_6 * pow( g, 0.479 ) * exp( -1.347 * pow( g, 0.595 ) - 0.17 * pow( g, 2.5 ) );
  392. F_e = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 * P_7 ) * f_n, 1.5763 );
  393. /* even-mode effective dielectric constant */
  394. er_eff_e = m_parameters[EPSILONR_PRM] - ( m_parameters[EPSILONR_PRM] - er_eff ) / ( 1.0 + F_e );
  395. er_eff = er_eff_o_0;
  396. P_8 = 0.7168 * ( 1.0 + 1.076 / ( 1.0 + 0.0576 * ( m_parameters[EPSILONR_PRM] - 1.0 ) ) );
  397. P_9 = P_8
  398. - 0.7913 * ( 1.0 - exp( -pow( f_n / 20.0, 1.424 ) ) )
  399. * atan( 2.481 * pow( m_parameters[EPSILONR_PRM] / 8.0, 0.946 ) );
  400. P_10 = 0.242 * pow( m_parameters[EPSILONR_PRM] - 1.0, 0.55 );
  401. P_11 = 0.6366 * ( exp( -0.3401 * f_n ) - 1.0 ) * atan( 1.263 * pow( u / 3.0, 1.629 ) );
  402. P_12 = P_9 + ( 1.0 - P_9 ) / ( 1.0 + 1.183 * pow( u, 1.376 ) );
  403. P_13 = 1.695 * P_10 / ( 0.414 + 1.605 * P_10 );
  404. P_14 = 0.8928 + 0.1072 * ( 1.0 - exp( -0.42 * pow( f_n / 20.0, 3.215 ) ) );
  405. P_15 = fabs( 1.0 - 0.8928 * ( 1.0 + P_11 ) * P_12 * exp( -P_13 * pow( g, 1.092 ) ) / P_14 );
  406. F_o = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n * P_15, 1.5763 );
  407. /* odd-mode effective dielectric constant */
  408. er_eff_o = m_parameters[EPSILONR_PRM] - ( m_parameters[EPSILONR_PRM] - er_eff ) / ( 1.0 + F_o );
  409. }
  410. /*
  411. * conductor_losses() - compute microstrips conductor losses per unit
  412. * length
  413. */
  414. void C_MICROSTRIP::conductor_losses()
  415. {
  416. double e_r_eff_e_0, e_r_eff_o_0, Z0_h_e, Z0_h_o, delta;
  417. double K, R_s, Q_c_e, Q_c_o, alpha_c_e, alpha_c_o;
  418. e_r_eff_e_0 = er_eff_e_0;
  419. e_r_eff_o_0 = er_eff_o_0;
  420. Z0_h_e = Z0_e_0 * sqrt( e_r_eff_e_0 ); /* homogeneous stripline impedance */
  421. Z0_h_o = Z0_o_0 * sqrt( e_r_eff_o_0 ); /* homogeneous stripline impedance */
  422. delta = m_parameters[SKIN_DEPTH_PRM];
  423. if( m_parameters[FREQUENCY_PRM] > 0.0 )
  424. {
  425. /* current distribution factor (same for the two modes) */
  426. K = exp( -1.2 * pow( ( Z0_h_e + Z0_h_o ) / ( 2.0 * ZF0 ), 0.7 ) );
  427. /* skin resistance */
  428. R_s = 1.0 / ( m_parameters[SIGMA_PRM] * delta );
  429. /* correction for surface roughness */
  430. R_s *= 1.0
  431. + ( ( 2.0 / M_PI )
  432. * atan( 1.40 * pow( ( m_parameters[ROUGH_PRM] / delta ), 2.0 ) ) );
  433. /* even-mode strip inductive quality factor */
  434. Q_c_e = ( M_PI * Z0_h_e * m_parameters[PHYS_WIDTH_PRM] * m_parameters[FREQUENCY_PRM] )
  435. / ( R_s * C0 * K );
  436. /* even-mode losses per unith length */
  437. alpha_c_e = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM]
  438. * sqrt( e_r_eff_e_0 ) / ( C0 * Q_c_e );
  439. /* odd-mode strip inductive quality factor */
  440. Q_c_o = ( M_PI * Z0_h_o * m_parameters[PHYS_WIDTH_PRM] * m_parameters[FREQUENCY_PRM] )
  441. / ( R_s * C0 * K );
  442. /* odd-mode losses per unith length */
  443. alpha_c_o = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM]
  444. * sqrt( e_r_eff_o_0 ) / ( C0 * Q_c_o );
  445. }
  446. else
  447. {
  448. alpha_c_e = alpha_c_o = 0.0;
  449. }
  450. atten_cond_e = alpha_c_e * m_parameters[PHYS_LEN_PRM];
  451. atten_cond_o = alpha_c_o * m_parameters[PHYS_LEN_PRM];
  452. }
  453. /*
  454. * dielectric_losses() - compute microstrips dielectric losses per
  455. * unit length
  456. */
  457. void C_MICROSTRIP::dielectric_losses()
  458. {
  459. double e_r, e_r_eff_e_0, e_r_eff_o_0;
  460. double alpha_d_e, alpha_d_o;
  461. e_r = m_parameters[EPSILONR_PRM];
  462. e_r_eff_e_0 = er_eff_e_0;
  463. e_r_eff_o_0 = er_eff_o_0;
  464. alpha_d_e = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
  465. * ( e_r / sqrt( e_r_eff_e_0 ) ) * ( ( e_r_eff_e_0 - 1.0 ) / ( e_r - 1.0 ) )
  466. * m_parameters[TAND_PRM];
  467. alpha_d_o = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
  468. * ( e_r / sqrt( e_r_eff_o_0 ) ) * ( ( e_r_eff_o_0 - 1.0 ) / ( e_r - 1.0 ) )
  469. * m_parameters[TAND_PRM];
  470. atten_dielectric_e = alpha_d_e * m_parameters[PHYS_LEN_PRM];
  471. atten_dielectric_o = alpha_d_o * m_parameters[PHYS_LEN_PRM];
  472. }
  473. /*
  474. * c_microstrip_attenuation() - compute attenuation of coupled
  475. * microstrips
  476. */
  477. void C_MICROSTRIP::attenuation()
  478. {
  479. m_parameters[SKIN_DEPTH_PRM] = skin_depth();
  480. conductor_losses();
  481. dielectric_losses();
  482. }
  483. /*
  484. * line_angle() - calculate strips electrical lengths in radians
  485. */
  486. void C_MICROSTRIP::line_angle()
  487. {
  488. double e_r_eff_e, e_r_eff_o;
  489. double v_e, v_o, lambda_g_e, lambda_g_o;
  490. e_r_eff_e = er_eff_e;
  491. e_r_eff_o = er_eff_o;
  492. /* even-mode velocity */
  493. v_e = C0 / sqrt( e_r_eff_e );
  494. /* odd-mode velocity */
  495. v_o = C0 / sqrt( e_r_eff_o );
  496. /* even-mode wavelength */
  497. lambda_g_e = v_e / m_parameters[FREQUENCY_PRM];
  498. /* odd-mode wavelength */
  499. lambda_g_o = v_o / m_parameters[FREQUENCY_PRM];
  500. /* electrical angles */
  501. ang_l_e = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g_e; /* in radians */
  502. ang_l_o = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g_o; /* in radians */
  503. }
  504. void C_MICROSTRIP::syn_err_fun(
  505. double* f1, double* f2, double s_h, double w_h, double e_r, double w_h_se, double w_h_so )
  506. {
  507. double g, he;
  508. g = cosh( 0.5 * M_PI * s_h );
  509. he = cosh( M_PI * w_h + 0.5 * M_PI * s_h );
  510. *f1 = ( 2.0 / M_PI ) * acosh( ( 2.0 * he - g + 1.0 ) / ( g + 1.0 ) );
  511. *f2 = ( 2.0 / M_PI ) * acosh( ( 2.0 * he - g - 1.0 ) / ( g - 1.0 ) );
  512. if( e_r <= 6.0 )
  513. {
  514. *f2 += ( 4.0 / ( M_PI * ( 1.0 + e_r / 2.0 ) ) ) * acosh( 1.0 + 2.0 * w_h / s_h );
  515. }
  516. else
  517. {
  518. *f2 += ( 1.0 / M_PI ) * acosh( 1.0 + 2.0 * w_h / s_h );
  519. }
  520. *f1 -= w_h_se;
  521. *f2 -= w_h_so;
  522. }
  523. /*
  524. * synth_width - calculate widths given Z0 and e_r
  525. * from Akhtarzad S. et al., "The design of coupled microstrip lines",
  526. * IEEE Trans. MTT-23, June 1975 and
  527. * Hinton, J.H., "On design of coupled microstrip lines", IEEE Trans.
  528. * MTT-28, March 1980
  529. */
  530. void C_MICROSTRIP::synth_width()
  531. {
  532. double Z0, e_r;
  533. double w_h_se, w_h_so, w_h, a, ce, co, s_h;
  534. double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
  535. double eps = 1e-04;
  536. f1 = f2 = 0;
  537. e_r = m_parameters[EPSILONR_PRM];
  538. Z0 = m_parameters[Z0_E_PRM] / 2.0;
  539. /* Wheeler formula for single microstrip synthesis */
  540. a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0;
  541. w_h_se = 8.0 * sqrt( a * ( ( 7.0 + 4.0 / e_r ) / 11.0 ) + ( ( 1.0 + 1.0 / e_r ) / 0.81 ) ) / a;
  542. Z0 = m_parameters[Z0_O_PRM] / 2.0;
  543. /* Wheeler formula for single microstrip synthesis */
  544. a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0;
  545. w_h_so = 8.0 * sqrt( a * ( ( 7.0 + 4.0 / e_r ) / 11.0 ) + ( ( 1.0 + 1.0 / e_r ) / 0.81 ) ) / a;
  546. ce = cosh( 0.5 * M_PI * w_h_se );
  547. co = cosh( 0.5 * M_PI * w_h_so );
  548. /* first guess at m_parameters[PHYS_S_PRM]/h */
  549. s_h = ( 2.0 / M_PI ) * acosh( ( ce + co - 2.0 ) / ( co - ce ) );
  550. /* first guess at w/h */
  551. w_h = acosh( ( ce * co - 1.0 ) / ( co - ce ) ) / M_PI - s_h / 2.0;
  552. m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
  553. m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
  554. syn_err_fun( &f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so );
  555. /* rather crude Newton-Rhapson; we need this beacuse the estimate of */
  556. /* w_h is often quite far from the true value (see Akhtarzad S. et al.) */
  557. do
  558. {
  559. /* compute Jacobian */
  560. syn_err_fun( &ft1, &ft2, s_h + eps, w_h, e_r, w_h_se, w_h_so );
  561. j11 = ( ft1 - f1 ) / eps;
  562. j21 = ( ft2 - f2 ) / eps;
  563. syn_err_fun( &ft1, &ft2, s_h, w_h + eps, e_r, w_h_se, w_h_so );
  564. j12 = ( ft1 - f1 ) / eps;
  565. j22 = ( ft2 - f2 ) / eps;
  566. /* compute next step */
  567. d_s_h = ( -f1 * j22 + f2 * j12 ) / ( j11 * j22 - j21 * j12 );
  568. d_w_h = ( -f2 * j11 + f1 * j21 ) / ( j11 * j22 - j21 * j12 );
  569. //g_print("j11 = %e\tj12 = %e\tj21 = %e\tj22 = %e\n", j11, j12, j21, j22);
  570. //g_print("det = %e\n", j11*j22 - j21*j22);
  571. //g_print("d_s_h = %e\td_w_h = %e\n", d_s_h, d_w_h);
  572. s_h += d_s_h;
  573. w_h += d_w_h;
  574. /* chech the error */
  575. syn_err_fun( &f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so );
  576. err = sqrt( f1 * f1 + f2 * f2 );
  577. /* converged ? */
  578. } while( err > 1e-04 );
  579. m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
  580. m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
  581. }
  582. /*
  583. * Z0_dispersion() - calculate frequency dependency of characteristic
  584. * impedances
  585. */
  586. void C_MICROSTRIP::Z0_dispersion()
  587. {
  588. double Q_0;
  589. double Q_11, Q_12, Q_13, Q_14, Q_15, Q_16, Q_17, Q_18, Q_19, Q_20, Q_21;
  590. double Q_22, Q_23, Q_24, Q_25, Q_26, Q_27, Q_28, Q_29;
  591. double r_e, q_e, p_e, d_e, C_e;
  592. double e_r_eff_o_f, e_r_eff_o_0;
  593. double e_r_eff_single_f, e_r_eff_single_0, Z0_single_f;
  594. double f_n, g, u, e_r;
  595. double R_1, R_2, R_7, R_10, R_11, R_12, R_15, R_16, tmpf;
  596. e_r = m_parameters[EPSILONR_PRM];
  597. u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM]; /* normalize line width */
  598. g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalize line spacing */
  599. /* normalized frequency [GHz * mm] */
  600. f_n = m_parameters[FREQUENCY_PRM] * m_parameters[H_PRM] / 1e06;
  601. e_r_eff_single_f = aux_ms->er_eff;
  602. e_r_eff_single_0 = aux_ms->er_eff_0;
  603. Z0_single_f = aux_ms->m_parameters[Z0_PRM];
  604. e_r_eff_o_f = er_eff_o;
  605. e_r_eff_o_0 = er_eff_o_0;
  606. Q_11 = 0.893 * ( 1.0 - 0.3 / ( 1.0 + 0.7 * ( e_r - 1.0 ) ) );
  607. Q_12 = 2.121 * ( pow( f_n / 20.0, 4.91 ) / ( 1.0 + Q_11 * pow( f_n / 20.0, 4.91 ) ) )
  608. * exp( -2.87 * g ) * pow( g, 0.902 );
  609. Q_13 = 1.0 + 0.038 * pow( e_r / 8.0, 5.1 );
  610. Q_14 = 1.0 + 1.203 * pow( e_r / 15.0, 4.0 ) / ( 1.0 + pow( e_r / 15.0, 4.0 ) );
  611. Q_15 = 1.887 * exp( -1.5 * pow( g, 0.84 ) ) * pow( g, Q_14 )
  612. / ( 1.0
  613. + 0.41 * pow( f_n / 15.0, 3.0 ) * pow( u, 2.0 / Q_13 )
  614. / ( 0.125 + pow( u, 1.626 / Q_13 ) ) );
  615. Q_16 = ( 1.0 + 9.0 / ( 1.0 + 0.403 * pow( e_r - 1.0, 2 ) ) ) * Q_15;
  616. Q_17 = 0.394 * ( 1.0 - exp( -1.47 * pow( u / 7.0, 0.672 ) ) )
  617. * ( 1.0 - exp( -4.25 * pow( f_n / 20.0, 1.87 ) ) );
  618. Q_18 = 0.61 * ( 1.0 - exp( -2.13 * pow( u / 8.0, 1.593 ) ) ) / ( 1.0 + 6.544 * pow( g, 4.17 ) );
  619. Q_19 = 0.21 * g * g * g * g
  620. / ( ( 1.0 + 0.18 * pow( g, 4.9 ) ) * ( 1.0 + 0.1 * u * u )
  621. * ( 1.0 + pow( f_n / 24.0, 3.0 ) ) );
  622. Q_20 = ( 0.09 + 1.0 / ( 1.0 + 0.1 * pow( e_r - 1, 2.7 ) ) ) * Q_19;
  623. Q_21 = fabs( 1.0
  624. - 42.54 * pow( g, 0.133 ) * exp( -0.812 * g ) * pow( u, 2.5 )
  625. / ( 1.0 + 0.033 * pow( u, 2.5 ) ) );
  626. r_e = pow( f_n / 28.843, 12 );
  627. q_e = 0.016 + pow( 0.0514 * e_r * Q_21, 4.524 );
  628. p_e = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
  629. d_e = 5.086 * q_e * ( r_e / ( 0.3838 + 0.386 * q_e ) )
  630. * ( exp( -22.2 * pow( u, 1.92 ) ) / ( 1.0 + 1.2992 * r_e ) )
  631. * ( pow( e_r - 1.0, 6.0 ) / ( 1.0 + 10 * pow( e_r - 1.0, 6.0 ) ) );
  632. C_e = 1.0
  633. + 1.275
  634. * ( 1.0
  635. - exp( -0.004625 * p_e * pow( e_r, 1.674 )
  636. * pow( f_n / 18.365, 2.745 ) ) )
  637. - Q_12 + Q_16 - Q_17 + Q_18 + Q_20;
  638. R_1 = 0.03891 * pow( e_r, 1.4 );
  639. R_2 = 0.267 * pow( u, 7.0 );
  640. R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
  641. R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
  642. tmpf = pow( f_n / 19.47, 6.0 );
  643. R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
  644. R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
  645. R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
  646. R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
  647. Q_0 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
  648. /* even-mode frequency-dependent characteristic impedances */
  649. m_parameters[Z0_E_PRM] = Z0_e_0 * pow( 0.9408 * pow( e_r_eff_single_f, C_e ) - 0.9603, Q_0 )
  650. / pow( ( 0.9408 - d_e ) * pow( e_r_eff_single_0, C_e ) - 0.9603, Q_0 );
  651. Q_29 = 15.16 / ( 1.0 + 0.196 * pow( e_r - 1.0, 2.0 ) );
  652. tmpf = pow( e_r - 1.0, 3.0 );
  653. Q_28 = 0.149 * tmpf / ( 94.5 + 0.038 * tmpf );
  654. tmpf = pow( e_r - 1.0, 1.5 );
  655. Q_27 = 0.4 * pow( g, 0.84 ) * ( 1.0 + 2.5 * tmpf / ( 5.0 + tmpf ) );
  656. tmpf = pow( ( e_r - 1.0 ) / 13.0, 12.0 );
  657. Q_26 = 30.0 - 22.2 * ( tmpf / ( 1.0 + 3.0 * tmpf ) ) - Q_29;
  658. tmpf = ( e_r - 1.0 ) * ( e_r - 1.0 );
  659. Q_25 = ( 0.3 * f_n * f_n / ( 10.0 + f_n * f_n ) ) * ( 1.0 + 2.333 * tmpf / ( 5.0 + tmpf ) );
  660. Q_24 = 2.506 * Q_28 * pow( u, 0.894 ) * pow( ( 1.0 + 1.3 * u ) * f_n / 99.25, 4.29 )
  661. / ( 3.575 + pow( u, 0.894 ) );
  662. Q_23 = 1.0
  663. + 0.005 * f_n * Q_27
  664. / ( ( 1.0 + 0.812 * pow( f_n / 15.0, 1.9 ) ) * ( 1.0 + 0.025 * u * u ) );
  665. Q_22 = 0.925 * pow( f_n / Q_26, 1.536 ) / ( 1.0 + 0.3 * pow( f_n / 30.0, 1.536 ) );
  666. /* odd-mode frequency-dependent characteristic impedances */
  667. m_parameters[Z0_O_PRM] =
  668. Z0_single_f
  669. + ( Z0_o_0 * pow( e_r_eff_o_f / e_r_eff_o_0, Q_22 ) - Z0_single_f * Q_23 )
  670. / ( 1.0 + Q_24 + pow( 0.46 * g, 2.2 ) * Q_25 );
  671. }
  672. void C_MICROSTRIP::calcAnalyze()
  673. {
  674. /* compute thickness corrections */
  675. delta_u_thickness();
  676. /* get effective dielectric constants */
  677. er_eff_static();
  678. /* impedances for even- and odd-mode */
  679. Z0_even_odd();
  680. /* calculate freq dependence of er_eff_e, er_eff_o */
  681. er_eff_freq();
  682. /* calculate frequency dependence of Z0e, Z0o */
  683. Z0_dispersion();
  684. /* calculate losses */
  685. attenuation();
  686. /* calculate electrical lengths */
  687. line_angle();
  688. }
  689. void C_MICROSTRIP::showAnalyze()
  690. {
  691. setProperty( Z0_E_PRM, m_parameters[Z0_E_PRM] );
  692. setProperty( Z0_O_PRM, m_parameters[Z0_O_PRM] );
  693. setProperty( ANG_L_PRM, sqrt( ang_l_e * ang_l_o ) );
  694. //Check for errors
  695. if( !std::isfinite( m_parameters[Z0_O_PRM] ) || m_parameters[Z0_O_PRM] <= 0.0 )
  696. setErrorLevel( Z0_O_PRM, TRANSLINE_ERROR );
  697. if( !std::isfinite( m_parameters[Z0_E_PRM] ) || m_parameters[Z0_E_PRM] <= 0.0 )
  698. setErrorLevel( Z0_E_PRM, TRANSLINE_ERROR );
  699. if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] <= 0.0 )
  700. setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
  701. // Check for warnings
  702. if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0.0 )
  703. setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
  704. if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0.0 )
  705. setErrorLevel( PHYS_S_PRM, TRANSLINE_WARNING );
  706. if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] <= 0.0 )
  707. setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
  708. }
  709. void C_MICROSTRIP::showSynthesize()
  710. {
  711. setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
  712. setProperty( PHYS_S_PRM, m_parameters[PHYS_S_PRM] );
  713. setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
  714. //Check for errors
  715. if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0.0 )
  716. setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
  717. if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0.0 )
  718. setErrorLevel( PHYS_S_PRM, TRANSLINE_ERROR );
  719. if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] <= 0.0 )
  720. setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
  721. // Check for warnings
  722. if( !std::isfinite( m_parameters[Z0_O_PRM] ) || m_parameters[Z0_O_PRM] <= 0.0 )
  723. setErrorLevel( Z0_O_PRM, TRANSLINE_WARNING );
  724. if( !std::isfinite( m_parameters[Z0_E_PRM] ) || m_parameters[Z0_E_PRM] <= 0.0 )
  725. setErrorLevel( Z0_E_PRM, TRANSLINE_WARNING );
  726. if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] <= 0.0 )
  727. setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
  728. }
  729. void C_MICROSTRIP::show_results()
  730. {
  731. setResult( 0, er_eff_e, "" );
  732. setResult( 1, er_eff_o, "" );
  733. setResult( 2, atten_cond_e, "dB" );
  734. setResult( 3, atten_cond_o, "dB" );
  735. setResult( 4, atten_dielectric_e, "dB" );
  736. setResult( 5, atten_dielectric_o, "dB" );
  737. setResult( 6, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
  738. }
  739. void C_MICROSTRIP::syn_fun(
  740. double* f1, double* f2, double s_h, double w_h, double Z0_e, double Z0_o )
  741. {
  742. m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
  743. m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
  744. /* compute coupled microstrip parameters */
  745. calcAnalyze();
  746. *f1 = m_parameters[Z0_E_PRM] - Z0_e;
  747. *f2 = m_parameters[Z0_O_PRM] - Z0_o;
  748. }
  749. /*
  750. * synthesis function
  751. */
  752. void C_MICROSTRIP::calcSynthesize()
  753. {
  754. double Z0_e, Z0_o, ang_l_dest;
  755. double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
  756. double eps = 1e-04;
  757. double w_h, s_h, le, lo;
  758. /* required value of Z0_e and Z0_o */
  759. Z0_e = m_parameters[Z0_E_PRM];
  760. Z0_o = m_parameters[Z0_O_PRM];
  761. ang_l_e = m_parameters[ANG_L_PRM];
  762. ang_l_o = m_parameters[ANG_L_PRM];
  763. ang_l_dest = m_parameters[ANG_L_PRM];
  764. /* calculate width and use for initial value in Newton's method */
  765. synth_width();
  766. w_h = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM];
  767. s_h = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM];
  768. f1 = f2 = 0;
  769. /* rather crude Newton-Rhapson */
  770. do
  771. {
  772. /* compute Jacobian */
  773. syn_fun( &ft1, &ft2, s_h + eps, w_h, Z0_e, Z0_o );
  774. j11 = ( ft1 - f1 ) / eps;
  775. j21 = ( ft2 - f2 ) / eps;
  776. syn_fun( &ft1, &ft2, s_h, w_h + eps, Z0_e, Z0_o );
  777. j12 = ( ft1 - f1 ) / eps;
  778. j22 = ( ft2 - f2 ) / eps;
  779. /* compute next step; increments of s_h and w_h */
  780. d_s_h = ( -f1 * j22 + f2 * j12 ) / ( j11 * j22 - j21 * j12 );
  781. d_w_h = ( -f2 * j11 + f1 * j21 ) / ( j11 * j22 - j21 * j12 );
  782. s_h += d_s_h;
  783. w_h += d_w_h;
  784. /* compute the error with the new values of s_h and w_h */
  785. syn_fun( &f1, &f2, s_h, w_h, Z0_e, Z0_o );
  786. err = sqrt( f1 * f1 + f2 * f2 );
  787. /* converged ? */
  788. } while( err > 1e-04 );
  789. /* denormalize computed width and spacing */
  790. m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
  791. m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
  792. /* calculate physical length */
  793. le = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff_e ) * ang_l_dest / 2.0 / M_PI;
  794. lo = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff_o ) * ang_l_dest / 2.0 / M_PI;
  795. m_parameters[PHYS_LEN_PRM] = sqrt( le * lo );
  796. calcAnalyze();
  797. m_parameters[ANG_L_PRM] = ang_l_dest;
  798. m_parameters[Z0_E_PRM] = Z0_e;
  799. m_parameters[Z0_O_PRM] = Z0_o;
  800. }