My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
c_microstrip.cpp
Go to the documentation of this file.
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 
24 /* c_microstrip.c - Puts up window for coupled microstrips and
25  * performs the associated calculations
26  * Based on the original microstrip.c by Gopal Narayanan
27  */
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <math.h>
33 
34 #include "units.h"
35 #include "transline.h"
36 #include "microstrip.h"
37 #include "c_microstrip.h"
38 
40 {
41  aux_ms = NULL;
42 }
43 
45 {
46  if (aux_ms) delete aux_ms;
47 }
48 
49 /*
50  * delta_u_thickness_single() computes the thickness effect on
51  * normalized width for a single microstrip line
52  *
53  * References: H. A. Atwater, "Simplified Design Equations for
54  * Microstrip Line Parameters", Microwave Journal, pp. 109-115,
55  * November 1989.
56  */
57 double c_microstrip::delta_u_thickness_single(double u, double t_h)
58 {
59  double delta_u;
60 
61  if (t_h > 0.0) {
62  delta_u = (1.25 * t_h / M_PI) * (1.0 + log((2.0 + (4.0 * M_PI * u - 2.0) / (1.0 + exp(-100.0 * (u - 1.0 / (2.0 * M_PI))))) / t_h));
63  } else {
64  delta_u = 0.0;
65  }
66  return delta_u;
67 }
68 
69 /*
70  * delta_u_thickness() - compute the thickness effect on normalized
71  * width for coupled microstrips
72  *
73  * References: Rolf Jansen, "High-Speed Cmputation of Single and
74  * Coupled Microstrip Parameters Including Dispersion, High-Order
75  * Modes, Loss and Finite Strip Thickness", IEEE Trans. MTT, vol. 26,
76  * no. 2, pp. 75-82, Feb. 1978
77  */
78 void c_microstrip::delta_u_thickness()
79 {
80  double e_r, u, g, t_h;
81  double delta_u, delta_t, delta_u_e, delta_u_o;
82 
83  e_r = er;
84  u = w / h; /* normalized line width */
85  g = s / h; /* normalized line spacing */
86  t_h = t / h; /* normalized strip thickness */
87 
88  if (t_h > 0.0) {
89  /* single microstrip correction for finite strip thickness */
90  delta_u = delta_u_thickness_single(u, t_h);
91  delta_t = t_h / (g * e_r);
92  /* thickness correction for the even- and odd-mode */
93  delta_u_e = delta_u * (1.0 - 0.5 * exp(-0.69 * delta_u / delta_t));
94  delta_u_o = delta_u_e + delta_t;
95  } else {
96  delta_u_e = delta_u_o = 0.0;
97  }
98 
99  w_t_e = w + delta_u_e * h;
100  w_t_o = w + delta_u_o * h;
101 }
102 
103 /*
104  * compute various parameters for a single line
105  */
106 void c_microstrip::compute_single_line()
107 {
108  double w_h, ht_h;
109  double Z0_single, er_eff_single;
110 
111  ht_h = ht / h;
112  w_h = w / h;
113 
114  if (aux_ms == NULL)
115  aux_ms = new microstrip ();
116 
117  /* prepare parameters for single microstrip computations */
118  aux_ms->er = er;
119  aux_ms->w = w;
120  aux_ms->h = h;
121  aux_ms->t = 0.0;
122  //aux_ms->t = t;
123  aux_ms->ht = 1e12; /* arbitrarily high */
124  aux_ms->f = f;
125  aux_ms->mur = mur;
126  aux_ms->microstrip_Z0();
127  aux_ms->dispersion();
128 
129  er_eff_single = aux_ms->er_eff_0;
130  Z0_single = aux_ms->Z0_0;
131 }
132 
133 
134 /*
135  * filling_factor_even() - compute the filling factor for the coupled
136  * microstrips even-mode without cover and zero conductor thickness
137  */
138 double c_microstrip::filling_factor_even(double u, double g, double e_r)
139 {
140  double v, v3, v4, a_e, b_e, q_inf;
141 
142  v = u * (20.0 + g * g) / (10.0 + g * g) + g * exp(-g);
143  v3 = v * v * v;
144  v4 = v3 * v;
145  a_e = 1.0 + log((v4 + v * v / 2704.0) / (v4 + 0.432)) / 49.0 + log(1.0 + v3 / 5929.741)
146  / 18.7;
147  b_e = 0.564 * pow(((e_r - 0.9) / (e_r + 3.0)), 0.053);
148 
149  /* filling factor, with width corrected for thickness */
150  q_inf = pow((1.0 + 10.0 / v), -a_e * b_e);
151 
152  return q_inf;
153 }
154 
159 double c_microstrip::filling_factor_odd(double u, double g, double e_r)
160 {
161  double b_o, c_o, d_o, q_inf;
162 
163  b_o = 0.747 * e_r / (0.15 + e_r);
164  c_o = b_o - (b_o - 0.207) * exp(-0.414 * u);
165  d_o = 0.593 + 0.694 * exp(-0.562 * u);
166 
167  /* filling factor, with width corrected for thickness */
168  q_inf = exp(-c_o * pow(g, d_o));
169 
170  return q_inf;
171 }
172 
173 
174 /*
175  * delta_q_cover_even() - compute the cover effect on filling factor
176  * for the even-mode
177  */
178 double c_microstrip::delta_q_cover_even(double h2h)
179 {
180  double q_c;
181 
182  if (h2h <= 39) {
183  q_c = tanh(1.626 + 0.107 * h2h - 1.733 / sqrt(h2h));
184  } else {
185  q_c = 1.0;
186  }
187 
188  return q_c;
189 }
190 
191 /*
192  * delta_q_cover_odd() - compute the cover effect on filling factor
193  * for the odd-mode
194  */
195 double c_microstrip::delta_q_cover_odd(double h2h)
196 {
197  double q_c;
198 
199  if (h2h <= 7) {
200  q_c = tanh(9.575 / (7.0 - h2h) - 2.965 + 1.68 * h2h - 0.311 * h2h * h2h);
201  } else {
202  q_c = 1.0;
203  }
204 
205  return q_c;
206 }
207 
216 void c_microstrip::er_eff_static()
217 {
218  double u_t_e, u_t_o, g, h2, h2h;
219  double a_o, t_h, q, q_c, q_t, q_inf;
220  double er_eff_single;
221 
222  /* compute zero-thickness single line parameters */
223  compute_single_line();
224  er_eff_single = aux_ms->er_eff_0;
225 
226  h2 = ht;
227  u_t_e = w_t_e / h; /* normalized even_mode line width */
228  u_t_o = w_t_o / h; /* normalized odd_mode line width */
229  g = s / h; /* normalized line spacing */
230  h2h = h2 / h; /* normalized cover height */
231  t_h = t / h; /* normalized strip thickness */
232 
233  /* filling factor, computed with thickness corrected width */
234  q_inf = filling_factor_even(u_t_e, g, er);
235  /* cover effect */
236  q_c = delta_q_cover_even(h2h);
237  /* thickness effect */
238  q_t = aux_ms->delta_q_thickness(u_t_e, t_h);
239  /* resultant filling factor */
240  q = (q_inf - q_t) * q_c;
241  /* static even-mode effective dielectric constant */
242  er_eff_e_0 = 0.5 * (er + 1.0) + 0.5 * (er - 1.0) * q;
243 
244  /* filling factor, with width corrected for thickness */
245  q_inf = filling_factor_odd(u_t_o, g, er);
246  /* cover effect */
247  q_c = delta_q_cover_odd(h2h);
248  /* thickness effect */
249  q_t = aux_ms->delta_q_thickness(u_t_o, t_h);
250  /* resultant filling factor */
251  q = (q_inf - q_t) * q_c;
252 
253  a_o = 0.7287 * (er_eff_single - 0.5 * (er + 1.0)) * (1.0 - exp(-0.179 * u_t_o));
254 
255  /* static odd-mode effective dielectric constant */
256  er_eff_o_0 = (0.5 * (er + 1.0) + a_o - er_eff_single) * q + er_eff_single;
257 }
258 
259 
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 
272  A = -4.351 / pow(1.0 + h2h, 1.842);
273  B = 6.639 / pow(1.0 + h2h, 1.861);
274  C = -2.291 / pow(1.0 + h2h, 1.90);
275  f_e = 1.0 - atanh(A + (B + C * u) * u);
276 
277  x = pow(10.0, 0.103 * g - 0.159);
278  y = pow(10.0, 0.0492 * g - 0.073);
279  D = 0.747 / sin(0.5 * M_PI * x);
280  E = 0.725 * sin(0.5 * M_PI * y);
281  F = pow(10.0, 0.11 - 0.0947 * g);
282  g_e = 270.0 * (1.0 - tanh(D + E * sqrt(1.0 + h2h) - F / (1.0 + h2h)));
283 
284  delta_Z0_even = f_e * g_e;
285 
286  return delta_Z0_even;
287 }
288 
289 
297 double c_microstrip::delta_Z0_odd_cover(double g, double u, double h2h)
298 {
299  double f_o, g_o, delta_Z0_odd;
300  double G, J, K, L;
301 
302  J = tanh(pow(1.0 + h2h, 1.585) / 6.0);
303  f_o = pow(u, J);
304 
305  G = 2.178 - 0.796 * g;
306  if (g > 0.858) {
307  K = log10(20.492 * pow(g, 0.174));
308  } else {
309  K = 1.30;
310  }
311  if (g > 0.873) {
312  L = 2.51 * pow(g, -0.462);
313  } else {
314  L = 2.674;
315  }
316  g_o = 270.0 * (1.0 - tanh(G + K * sqrt(1.0 + h2h) - L / (1.0 + h2h)));
317 
318  delta_Z0_odd = f_o * g_o;
319 
320  return delta_Z0_odd;
321 }
322 
332 void c_microstrip::Z0_even_odd()
333 {
334  double er_eff, h2, u_t_e, u_t_o, g, h2h;
335  double Q_1, Q_2, Q_3, Q_4, Q_5, Q_6, Q_7, Q_8, Q_9, Q_10;
336  double delta_Z0_e_0, delta_Z0_o_0, Z0_single, er_eff_single;
337 
338  h2 = ht;
339  u_t_e = w_t_e / h; /* normalized even-mode line width */
340  u_t_o = w_t_o / h; /* normalized odd-mode line width */
341  g = s / h; /* normalized line spacing */
342  h2h = h2 / h; /* normalized cover height */
343 
344  Z0_single = aux_ms->Z0_0;
345  er_eff_single = aux_ms->er_eff_0;
346 
347  /* even-mode */
348  er_eff = er_eff_e_0;
349  Q_1 = 0.8695 * pow(u_t_e, 0.194);
350  Q_2 = 1.0 + 0.7519 * g + 0.189 * pow(g, 2.31);
351  Q_3 = 0.1975 + pow((16.6 + pow((8.4 / g), 6.0)), -0.387) + log(pow(g, 10.0) / (1.0 + pow(g / 3.4, 10.0))) / 241.0;
352  Q_4 = 2.0 * Q_1 / (Q_2 * (exp(-g) * pow(u_t_e, Q_3) + (2.0 - exp(-g)) * pow(u_t_e, -Q_3)));
353  /* static even-mode impedance */
354  Z0_e_0 = Z0_single * sqrt(er_eff_single / er_eff) / (1.0 - sqrt(er_eff_single) * Q_4 * Z0_single / ZF0);
355  /* correction for cover */
356  delta_Z0_e_0 = delta_Z0_even_cover(g, u_t_e, h2h) / sqrt(er_eff);
357 
358  Z0_e_0 = Z0_e_0 - delta_Z0_e_0;
359 
360  /* odd-mode */
361  er_eff = er_eff_o_0;
362  Q_5 = 1.794 + 1.14 * log(1.0 + 0.638 / (g + 0.517 * pow(g, 2.43)));
363  Q_6 = 0.2305 + log(pow(g, 10.0) / (1.0 + pow(g / 5.8, 10.0))) / 281.3 + log(1.0 + 0.598 * pow(g, 1.154)) / 5.1;
364  Q_7 = (10.0 + 190.0 * g * g) / (1.0 + 82.3 * g * g * g);
365  Q_8 = exp(-6.5 - 0.95 * log(g) - pow(g / 0.15, 5.0));
366  Q_9 = log(Q_7) * (Q_8 + 1.0 / 16.5);
367  Q_10 = (Q_2 * Q_4 - Q_5 * exp(log(u_t_o) * Q_6 * pow(u_t_o, -Q_9))) / Q_2;
368 
369  /* static odd-mode impedance */
370  Z0_o_0 = Z0_single * sqrt(er_eff_single / er_eff) / (1.0 - sqrt(er_eff_single) * Q_10 * Z0_single / ZF0);
371  /* correction for cover */
372  delta_Z0_o_0 = delta_Z0_odd_cover(g, u_t_o, h2h) / sqrt(er_eff);
373 
374  Z0_o_0 = Z0_o_0 - delta_Z0_o_0;
375 }
376 
377 
378 /*
379  * mur_eff() - returns effective magnetic permeability
380  */
381 double c_microstrip::calc_mur_eff()
382 {
383  double mureff;
384  mureff = mur; /* FIXME: ... */
385  return mureff;
386 }
387 
388 
389 /*
390  * er_eff_freq() - compute er_eff as a function of frequency
391  */
392 void c_microstrip::er_eff_freq()
393 {
394  double P_1, P_2, P_3, P_4, P_5, P_6, P_7;
395  double P_8, P_9, P_10, P_11, P_12, P_13, P_14, P_15;
396  double F_e, F_o;
397  double er_eff, u, g, f_n;
398 
399  u = w / h; /* normalize line width */
400  g = s / h; /* normalize line spacing */
401 
402  /* normalized frequency [GHz * mm] */
403  f_n = f * h / 1e06;
404 
405  er_eff = er_eff_e_0;
406  P_1 = 0.27488 + (0.6315 + 0.525 / pow(1.0 + 0.0157 * f_n, 20.0)) * u - 0.065683 * exp(-8.7513 * u);
407  P_2 = 0.33622 * (1.0 - exp(-0.03442 * er));
408  P_3 = 0.0363 * exp(-4.6 * u) * (1.0 - exp(-pow(f_n / 38.7, 4.97)));
409  P_4 = 1.0 + 2.751 * (1.0 - exp(-pow(er / 15.916, 8.0)));
410  P_5 = 0.334 * exp(-3.3 * pow(er / 15.0, 3.0)) + 0.746;
411  P_6 = P_5 * exp(-pow(f_n / 18.0, 0.368));
412  P_7 = 1.0 + 4.069 * P_6 * pow(g, 0.479) * exp(-1.347 * pow(g, 0.595) - 0.17 * pow(g, 2.5));
413 
414  F_e = P_1 * P_2 * pow((P_3 * P_4 + 0.1844 * P_7) * f_n, 1.5763);
415  /* even-mode effective dielectric constant */
416  er_eff_e = er - (er - er_eff) / (1.0 + F_e);
417 
418  er_eff = er_eff_o_0;
419  P_8 = 0.7168 * (1.0 + 1.076 / (1.0 + 0.0576 * (er - 1.0)));
420  P_9 = P_8 - 0.7913 * (1.0 - exp(-pow(f_n / 20.0, 1.424))) * atan(2.481 * pow(er / 8.0, 0.946));
421  P_10 = 0.242 * pow(er - 1.0, 0.55);
422  P_11 = 0.6366 * (exp(-0.3401 * f_n) - 1.0) * atan(1.263 * pow(u / 3.0, 1.629));
423  P_12 = P_9 + (1.0 - P_9) / (1.0 + 1.183 * pow(u, 1.376));
424  P_13 = 1.695 * P_10 / (0.414 + 1.605 * P_10);
425  P_14 = 0.8928 + 0.1072 * (1.0 - exp(-0.42 * pow(f_n / 20.0, 3.215)));
426  P_15 = fabs(1.0 - 0.8928 * (1.0 + P_11) * P_12 * exp(-P_13 * pow(g, 1.092)) / P_14);
427 
428  F_o = P_1 * P_2 * pow((P_3 * P_4 + 0.1844) * f_n * P_15, 1.5763);
429  /* odd-mode effective dielectric constant */
430  er_eff_o = er - (er - er_eff) / (1.0 + F_o);
431 }
432 
433 /*
434  * conductor_losses() - compute microstrips conductor losses per unit
435  * length
436  */
437 void c_microstrip::conductor_losses()
438 {
439  double e_r_eff_e_0, e_r_eff_o_0, Z0_h_e, Z0_h_o, delta;
440  double K, R_s, Q_c_e, Q_c_o, alpha_c_e, alpha_c_o;
441 
442  e_r_eff_e_0 = er_eff_e_0;
443  e_r_eff_o_0 = er_eff_o_0;
444  Z0_h_e = Z0_e_0 * sqrt(e_r_eff_e_0); /* homogeneous stripline impedance */
445  Z0_h_o = Z0_o_0 * sqrt(e_r_eff_o_0); /* homogeneous stripline impedance */
446  delta = skindepth;
447 
448  if (f > 0.0) {
449  /* current distribution factor (same for the two modes) */
450  K = exp(-1.2 * pow((Z0_h_e + Z0_h_o) / (2.0 * ZF0), 0.7));
451  /* skin resistance */
452  R_s = 1.0 / (sigma * delta);
453  /* correction for surface roughness */
454  R_s *= 1.0 + ((2.0 / M_PI) * atan(1.40 * pow((rough / delta), 2.0)));
455 
456  /* even-mode strip inductive quality factor */
457  Q_c_e = (M_PI * Z0_h_e * w * f) / (R_s * C0 * K);
458  /* even-mode losses per unith length */
459  alpha_c_e = (20.0 * M_PI / log(10.0)) * f * sqrt(e_r_eff_e_0) / (C0 * Q_c_e);
460 
461  /* odd-mode strip inductive quality factor */
462  Q_c_o = (M_PI * Z0_h_o * w * f) / (R_s * C0 * K);
463  /* odd-mode losses per unith length */
464  alpha_c_o = (20.0 * M_PI / log(10.0)) * f * sqrt(e_r_eff_o_0) / (C0 * Q_c_o);
465  } else {
466  alpha_c_e = alpha_c_o = 0.0;
467  }
468 
469  atten_cond_e = alpha_c_e * l;
470  atten_cond_o = alpha_c_o * l;
471 }
472 
473 
474 /*
475  * dielectric_losses() - compute microstrips dielectric losses per
476  * unit length
477  */
478 void c_microstrip::dielectric_losses()
479 {
480  double e_r, e_r_eff_e_0, e_r_eff_o_0;
481  double alpha_d_e, alpha_d_o;
482 
483  e_r = er;
484  e_r_eff_e_0 = er_eff_e_0;
485  e_r_eff_o_0 = er_eff_o_0;
486 
487  alpha_d_e = (20.0 * M_PI / log(10.0)) * (f / C0) * (e_r / sqrt(e_r_eff_e_0)) * ((e_r_eff_e_0 - 1.0) / (e_r - 1.0)) * tand;
488  alpha_d_o = (20.0 * M_PI / log(10.0)) * (f / C0) * (e_r / sqrt(e_r_eff_o_0)) * ((e_r_eff_o_0 - 1.0) / (e_r - 1.0)) * tand;
489 
490  atten_dielectric_e = alpha_d_e * l;
491  atten_dielectric_o = alpha_d_o * l;
492 }
493 
494 
495 /*
496  * c_microstrip_attenuation() - compute attenuation of coupled
497  * microstrips
498  */
499 void c_microstrip::attenuation()
500 {
501  skindepth = skin_depth();
502  conductor_losses();
503  dielectric_losses();
504 }
505 
506 
507 /*
508  * line_angle() - calculate strips electrical lengths in radians
509  */
510 void c_microstrip::line_angle()
511 {
512  double e_r_eff_e, e_r_eff_o;
513  double v_e, v_o, lambda_g_e, lambda_g_o;
514 
515  e_r_eff_e = er_eff_e;
516  e_r_eff_o = er_eff_o;
517 
518  /* even-mode velocity */
519  v_e = C0 / sqrt(e_r_eff_e);
520  /* odd-mode velocity */
521  v_o = C0 / sqrt(e_r_eff_o);
522  /* even-mode wavelength */
523  lambda_g_e = v_e / f;
524  /* odd-mode wavelength */
525  lambda_g_o = v_o / f;
526  /* electrical angles */
527  ang_l_e = 2.0 * M_PI * l / lambda_g_e; /* in radians */
528  ang_l_o = 2.0 * M_PI * l / lambda_g_o; /* in radians */
529 }
530 
531 
532 void c_microstrip::syn_err_fun(double *f1, double *f2, double s_h, double w_h, double e_r, double w_h_se, double w_h_so)
533 {
534 
535  double g, h;
536 
537  g = cosh(0.5 * M_PI * s_h);
538  h = cosh(M_PI * w_h + 0.5 * M_PI * s_h);
539 
540  *f1 = (2.0 / M_PI) * acosh((2.0 * h - g + 1.0) / (g + 1.0));
541  *f2 = (2.0 / M_PI) * acosh((2.0 * h - g - 1.0) / (g - 1.0));
542  if (e_r <= 6.0) {
543  *f2 += (4.0 / (M_PI * (1.0 + e_r / 2.0))) * acosh(1.0 + 2.0 * w_h / s_h);
544  } else {
545  *f2 += (1.0 / M_PI) * acosh(1.0 + 2.0 * w_h / s_h);
546  }
547  *f1 -= w_h_se;
548  *f2 -= w_h_so;
549 }
550 
551 /*
552  * synth_width - calculate widths given Z0 and e_r
553  * from Akhtarzad S. et al., "The design of coupled microstrip lines",
554  * IEEE Trans. MTT-23, June 1975 and
555  * Hinton, J.H., "On design of coupled microstrip lines", IEEE Trans.
556  * MTT-28, March 1980
557  */
558 void c_microstrip::synth_width()
559 {
560  double Z0, e_r;
561  double w_h_se, w_h_so, w_h, a, ce, co, s_h;
562  double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
563  double eps = 1e-04;
564 
565  f1 = f2 = 0;
566  e_r = er;
567 
568  Z0 = Z0e / 2.0;
569  /* Wheeler formula for single microstrip synthesis */
570  a = exp(Z0 * sqrt(e_r + 1.0) / 42.4) - 1.0;
571  w_h_se = 8.0 * sqrt(a * ((7.0 + 4.0 / e_r) / 11.0) + ((1.0 + 1.0 / e_r) / 0.81)) / a;
572 
573  Z0 = Z0o / 2.0;
574  /* Wheeler formula for single microstrip synthesis */
575  a = exp(Z0 * sqrt(e_r + 1.0) / 42.4) - 1.0;
576  w_h_so = 8.0 * sqrt(a * ((7.0 + 4.0 / e_r) / 11.0) + ((1.0 + 1.0 / e_r) / 0.81)) / a;
577 
578  ce = cosh(0.5 * M_PI * w_h_se);
579  co = cosh(0.5 * M_PI * w_h_so);
580  /* first guess at s/h */
581  s_h = (2.0 / M_PI) * acosh((ce + co - 2.0) / (co - ce));
582  /* first guess at w/h */
583  w_h = acosh((ce * co - 1.0) / (co - ce)) / M_PI - s_h / 2.0;
584 
585  s = s_h * h;
586  w = w_h * h;
587 
588  syn_err_fun(&f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so);
589 
590  /* rather crude Newton-Rhapson; we need this beacuse the estimate of */
591  /* w_h is often quite far from the true value (see Akhtarzad S. et al.) */
592  do {
593  /* compute Jacobian */
594  syn_err_fun(&ft1, &ft2, s_h + eps, w_h, e_r, w_h_se, w_h_so);
595  j11 = (ft1 - f1) / eps;
596  j21 = (ft2 - f2) / eps;
597  syn_err_fun(&ft1, &ft2, s_h, w_h + eps, e_r, w_h_se, w_h_so);
598  j12 = (ft1 - f1) / eps;
599  j22 = (ft2 - f2) / eps;
600 
601  /* compute next step */
602  d_s_h = (-f1 * j22 + f2 * j12) / (j11 * j22 - j21 * j12);
603  d_w_h = (-f2 * j11 + f1 * j21) / (j11 * j22 - j21 * j12);
604  //g_print("j11 = %e\tj12 = %e\tj21 = %e\tj22 = %e\n", j11, j12, j21, j22);
605  //g_print("det = %e\n", j11*j22 - j21*j22);
606  //g_print("d_s_h = %e\td_w_h = %e\n", d_s_h, d_w_h);
607 
608  s_h += d_s_h;
609  w_h += d_w_h;
610 
611  /* chech the error */
612  syn_err_fun(&f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so);
613 
614  err = sqrt(f1 * f1 + f2 * f2);
615  /* converged ? */
616  } while (err > 1e-04);
617 
618 
619  s = s_h * h;
620  w = w_h * h;
621 }
622 
623 
624 /*
625  * Z0_dispersion() - calculate frequency dependency of characteristic
626  * impedances
627  */
628 void c_microstrip::Z0_dispersion()
629 {
630  double Q_0;
631  double Q_11, Q_12, Q_13, Q_14, Q_15, Q_16, Q_17, Q_18, Q_19, Q_20, Q_21;
632  double Q_22, Q_23, Q_24, Q_25, Q_26, Q_27, Q_28, Q_29;
633  double r_e, q_e, p_e, d_e, C_e;
634  double e_r_eff_o_f, e_r_eff_o_0;
635  double e_r_eff_single_f, e_r_eff_single_0, Z0_single_f;
636  double f_n, g, u, e_r;
637  double R_1, R_2, R_7, R_10, R_11, R_12, R_15, R_16, tmpf;
638 
639  e_r = er;
640 
641  u = w / h; /* normalize line width */
642  g = s / h; /* normalize line spacing */
643 
644  /* normalized frequency [GHz * mm] */
645  f_n = f * h / 1e06;
646 
647  e_r_eff_single_f = aux_ms->er_eff;
648  e_r_eff_single_0 = aux_ms->er_eff_0;
649  Z0_single_f = aux_ms->Z0;
650 
651  e_r_eff_o_f = er_eff_o;
652  e_r_eff_o_0 = er_eff_o_0;
653 
654  Q_11 = 0.893 * (1.0 - 0.3 / (1.0 + 0.7 * (e_r - 1.0)));
655  Q_12 = 2.121 * (pow(f_n / 20.0, 4.91) / (1.0 + Q_11 * pow(f_n / 20.0, 4.91))) * exp(-2.87 * g) * pow(g, 0.902);
656  Q_13 = 1.0 + 0.038 * pow(e_r / 8.0, 5.1);
657  Q_14 = 1.0 + 1.203 * pow(e_r / 15.0, 4.0) / (1.0 + pow(e_r / 15.0, 4.0));
658  Q_15 = 1.887 * exp(-1.5 * pow(g, 0.84)) * pow(g, Q_14) / (1.0 + 0.41 * pow(f_n / 15.0, 3.0) * pow(u, 2.0 / Q_13) / (0.125 + pow(u, 1.626 / Q_13)));
659  Q_16 = (1.0 + 9.0 / (1.0 + 0.403 * pow(e_r - 1.0, 2))) * Q_15;
660  Q_17 = 0.394 * (1.0 - exp(-1.47 * pow(u / 7.0, 0.672))) * (1.0 - exp(-4.25 * pow(f_n / 20.0, 1.87)));
661  Q_18 = 0.61 * (1.0 - exp(-2.13 * pow(u / 8.0, 1.593))) / (1.0 + 6.544 * pow(g, 4.17));
662  Q_19 = 0.21 * g * g * g * g / ((1.0 + 0.18 * pow(g, 4.9)) * (1.0 + 0.1 * u * u) * (1.0 + pow(f_n / 24.0, 3.0)));
663  Q_20 = (0.09 + 1.0 / (1.0 + 0.1 * pow(e_r - 1, 2.7))) * Q_19;
664  Q_21 = fabs(1.0 - 42.54 * pow(g, 0.133) * exp(-0.812 * g) * pow(u, 2.5) / (1.0 + 0.033 * pow(u, 2.5)));
665 
666  r_e = pow(f_n / 28.843, 12);
667  q_e = 0.016 + pow(0.0514 * e_r * Q_21, 4.524);
668  p_e = 4.766 * exp(-3.228 * pow(u, 0.641));
669  d_e = 5.086 * q_e * (r_e / (0.3838 + 0.386 * q_e)) * (exp(-22.2 * pow(u, 1.92)) / (1.0 + 1.2992 * r_e)) * (pow(e_r - 1.0, 6.0) / (1.0 + 10 * pow(e_r - 1.0, 6.0)));
670  C_e = 1.0 + 1.275 * (1.0 - exp(-0.004625 * p_e * pow(e_r, 1.674) * pow(f_n / 18.365, 2.745))) - Q_12 + Q_16 - Q_17 + Q_18 + Q_20;
671 
672 
673  R_1 = 0.03891 * pow(e_r, 1.4);
674  R_2 = 0.267 * pow(u, 7.0);
675  R_7 = 1.206 - 0.3144 * exp(-R_1) * (1.0 - exp(-R_2));
676  R_10 = 0.00044 * pow(e_r, 2.136) + 0.0184;
677  tmpf = pow(f_n / 19.47, 6.0);
678  R_11 = tmpf / (1.0 + 0.0962 * tmpf);
679  R_12 = 1.0 / (1.0 + 0.00245 * u * u);
680  R_15 = 0.707 * R_10 * pow(f_n / 12.3, 1.097);
681  R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * (1.0 - exp(-pow(u / 15.0, 6.0)));
682  Q_0 = R_7 * (1.0 - 1.1241 * (R_12 / R_16) * exp(-0.026 * pow(f_n, 1.15656) - R_15));
683 
684  /* even-mode frequency-dependent characteristic impedances */
685  Z0e = Z0_e_0 * pow(0.9408 * pow(e_r_eff_single_f, C_e) - 0.9603, Q_0) / pow((0.9408 - d_e) * pow(e_r_eff_single_0, C_e) - 0.9603, Q_0);
686 
687  Q_29 = 15.16 / (1.0 + 0.196 * pow(e_r - 1.0, 2.0));
688  tmpf = pow(e_r - 1.0, 3.0);
689  Q_28 = 0.149 * tmpf / (94.5 + 0.038 * tmpf);
690  tmpf = pow(e_r - 1.0, 1.5);
691  Q_27 = 0.4 * pow(g, 0.84) * (1.0 + 2.5 * tmpf / (5.0 + tmpf));
692  tmpf = pow((e_r - 1.0) / 13.0, 12.0);
693  Q_26 = 30.0 - 22.2 * (tmpf / (1.0 + 3.0 * tmpf)) - Q_29;
694  tmpf = (e_r - 1.0) * (e_r - 1.0);
695  Q_25 = (0.3 * f_n * f_n / (10.0 + f_n * f_n)) * (1.0 + 2.333 * tmpf / (5.0 + tmpf));
696  Q_24 = 2.506 * Q_28 * pow(u, 0.894) * pow((1.0 + 1.3 * u) * f_n / 99.25, 4.29) / (3.575 + pow(u, 0.894));
697  Q_23 = 1.0 + 0.005 * f_n * Q_27 / ((1.0 + 0.812 * pow(f_n / 15.0, 1.9)) * (1.0 + 0.025 * u * u));
698  Q_22 = 0.925 * pow(f_n / Q_26, 1.536) / (1.0 + 0.3 * pow(f_n / 30.0, 1.536));
699 
700  /* odd-mode frequency-dependent characteristic impedances */
701  Z0o = Z0_single_f + (Z0_o_0 * pow(e_r_eff_o_f / e_r_eff_o_0, Q_22) - Z0_single_f * Q_23) / (1.0 + Q_24 + pow(0.46 * g, 2.2) * Q_25);
702 }
703 
704 
705 void c_microstrip::calc()
706 {
707  /* compute thickness corrections */
708  delta_u_thickness();
709  /* get effective dielectric constants */
710  er_eff_static();
711  /* impedances for even- and odd-mode */
712  Z0_even_odd();
713  /* calculate freq dependence of er_eff_e, er_eff_o */
714  er_eff_freq();
715  /* FIXME: (not used) Get effective magnetic permeability */
716  mur_eff = calc_mur_eff();
717  /* calculate frequency dependence of Z0e, Z0o */
718  Z0_dispersion();
719  /* calculate losses */
720  attenuation();
721  /* calculate electrical lengths */
722  line_angle();
723 }
724 
725 /*
726  * get_microstrip_sub
727  * get and assign microstrip substrate parameters
728  * into microstrip structure
729  */
730 void c_microstrip::get_c_microstrip_sub()
731 {
732  er = getProperty ("Er");
733  mur = getProperty ("Mur");
734  h = getProperty ("H", UNIT_LENGTH, LENGTH_M);
735  ht = getProperty ("H_t", UNIT_LENGTH, LENGTH_M);
736  t = getProperty ("T", UNIT_LENGTH, LENGTH_M);
737  sigma = getProperty ("Cond");
738  tand = getProperty ("Tand");
739  rough = getProperty ("Rough", UNIT_LENGTH, LENGTH_M);
740 }
741 
742 /*
743  * get_c_microstrip_comp
744  * get and assign microstrip component parameters
745  * into microstrip structure
746  */
747 void c_microstrip::get_c_microstrip_comp()
748 {
749  f = getProperty ("Freq", UNIT_FREQ, FREQ_HZ);
750 }
751 
752 /*
753  * get_c_microstrip_elec
754  * get and assign microstrip electrical parameters
755  * into microstrip structure
756  */
757 void c_microstrip::get_c_microstrip_elec()
758 {
759  Z0e = getProperty ("Z0e", UNIT_RES, RES_OHM);
760  Z0o = getProperty ("Z0o", UNIT_RES, RES_OHM);
761  ang_l_e = getProperty ("Ang_l", UNIT_ANG, ANG_RAD);
762  ang_l_o = getProperty ("Ang_l", UNIT_ANG, ANG_RAD);
763 }
764 
765 
766 /*
767  * get_c_microstrip_phys
768  * get and assign microstrip physical parameters
769  * into microstrip structure
770  */
771 void c_microstrip::get_c_microstrip_phys()
772 {
773  w = getProperty ("W", UNIT_LENGTH, LENGTH_M);
774  s = getProperty ("S", UNIT_LENGTH, LENGTH_M);
775  l = getProperty ("L", UNIT_LENGTH, LENGTH_M);
776 }
777 
778 
779 void c_microstrip::show_results()
780 {
781  setProperty ("Z0e", Z0e, UNIT_RES, RES_OHM);
782  setProperty ("Z0o", Z0o, UNIT_RES, RES_OHM);
783  setProperty ("Ang_l", sqrt (ang_l_e * ang_l_o), UNIT_ANG, ANG_RAD);
784 
785  setResult (0, er_eff_e, "");
786  setResult (1, er_eff_o, "");
787  setResult (2, atten_cond_e, "dB");
788  setResult (3, atten_cond_o, "dB");
789  setResult (4, atten_dielectric_e, "dB");
790  setResult (5, atten_dielectric_o, "dB");
791 
792  double val = convertProperty ("T", skindepth, UNIT_LENGTH, LENGTH_M);
793  setResult (6, val, getUnit ("T"));
794 }
795 
796 
797 /*
798  * analysis function
799  */
801 {
802  /* Get and assign substrate parameters */
803  get_c_microstrip_sub();
804  /* Get and assign component parameters */
805  get_c_microstrip_comp();
806  /* Get and assign physical parameters */
807  get_c_microstrip_phys();
808 
809  /* compute coupled microstrip parameters */
810  calc();
811  /* print results in the subwindow */
812  show_results();
813 }
814 
815 
816 void c_microstrip::syn_fun(double *f1, double *f2, double s_h, double w_h, double Z0_e, double Z0_o)
817 {
818  s = s_h * h;
819  w = w_h * h;
820 
821  /* compute coupled microstrip parameters */
822  calc();
823 
824  *f1 = Z0e - Z0_e;
825  *f2 = Z0o - Z0_o;
826 }
827 
828 /*
829  * synthesis function
830  */
832 {
833  double Z0_e, Z0_o;
834  double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
835  double eps = 1e-04;
836  double w_h, s_h, le, lo;
837 
838  /* Get and assign substrate parameters */
839  get_c_microstrip_sub();
840 
841  /* Get and assign component parameters */
842  get_c_microstrip_comp();
843 
844  /* Get and assign electrical parameters */
845  get_c_microstrip_elec();
846 
847  /* Get and assign physical parameters */
848  /* at present it is required only for getting strips length */
849  get_c_microstrip_phys();
850 
851 
852  /* required value of Z0_e and Z0_o */
853  Z0_e = Z0e;
854  Z0_o = Z0o;
855 
856  /* calculate width and use for initial value in Newton's method */
857  synth_width();
858  w_h = w / h;
859  s_h = s / h;
860  f1 = f2 = 0;
861 
862  /* rather crude Newton-Rhapson */
863  do {
864  /* compute Jacobian */
865  syn_fun(&ft1, &ft2, s_h + eps, w_h, Z0_e, Z0_o);
866  j11 = (ft1 - f1) / eps;
867  j21 = (ft2 - f2) / eps;
868  syn_fun(&ft1, &ft2, s_h, w_h + eps, Z0_e, Z0_o);
869  j12 = (ft1 - f1) / eps;
870  j22 = (ft2 - f2) / eps;
871 
872  /* compute next step; increments of s_h and w_h */
873  d_s_h = (-f1 * j22 + f2 * j12) / (j11 * j22 - j21 * j12);
874  d_w_h = (-f2 * j11 + f1 * j21) / (j11 * j22 - j21 * j12);
875 
876  s_h += d_s_h;
877  w_h += d_w_h;
878 
879  /* compute the error with the new values of s_h and w_h */
880  syn_fun(&f1, &f2, s_h, w_h, Z0_e, Z0_o);
881  err = sqrt(f1 * f1 + f2 * f2);
882 
883  /* converged ? */
884  } while (err > 1e-04);
885 
886  /* denormalize computed width and spacing */
887  s = s_h * h;
888  w = w_h * h;
889 
890  setProperty ("W", w, UNIT_LENGTH, LENGTH_M);
891  setProperty ("S", s, UNIT_LENGTH, LENGTH_M);
892 
893  /* calculate physical length */
894  ang_l_e = getProperty ("Ang_l", UNIT_ANG, ANG_RAD);
895  ang_l_o = getProperty ("Ang_l", UNIT_ANG, ANG_RAD);
896  le = C0 / f / sqrt(er_eff_e * mur_eff) * ang_l_e / 2.0 / M_PI;
897  lo = C0 / f / sqrt(er_eff_o * mur_eff) * ang_l_o / 2.0 / M_PI;
898  l = sqrt (le * lo);
899  setProperty ("L", l, UNIT_LENGTH, LENGTH_M);
900 
901  calc();
902  /* print results in the subwindow */
903  show_results();
904 }