My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
microstrip.cpp
Go to the documentation of this file.
1 /*
2  * microstrip.cpp - microstrip class implementation
3  *
4  * Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
5  * Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
6  * Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this package; see the file COPYING. If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 
26 /* microstrip.c - Puts up window for microstrip and
27  * performs the associated calculations
28  * Based on the original microstrip.c by Gopal Narayanan
29  */
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35 
36 #include "units.h"
37 #include "transline.h"
38 #include "microstrip.h"
39 
41 {
42 }
43 
45 {
46 }
47 
48 /*
49  * Z0_homogeneous() - compute the impedance for a stripline in a
50  * homogeneous medium, without cover effects
51  */
52 double microstrip::Z0_homogeneous(double u)
53 {
54  double f, Z0;
55  f = 6.0 + (2.0 * M_PI - 6.0) * exp(-pow(30.666 / u, 0.7528));
56  Z0 = (ZF0 / (2.0 * M_PI)) * log(f / u + sqrt(1.0 + 4.0 / (u * u)));
57  return Z0;
58 }
59 
60 
61 /*
62  * delta_Z0_cover() - compute the cover effect on impedance for a
63  * stripline in a homogeneous medium
64  */
65 double microstrip::delta_Z0_cover(double u, double h2h)
66 {
67  double P, Q;
68  double h2hp1;
69  h2hp1 = 1.0 + h2h;
70  P = 270.0 * (1.0 - tanh(1.192 + 0.706 * sqrt(h2hp1) - 1.389 / h2hp1));
71  Q = 1.0109 - atanh((0.012 * u + 0.177 * u * u - 0.027 * u * u * u) / (h2hp1 * h2hp1));
72  return (P * Q);
73 }
74 
75 
76 /*
77  * filling_factor() - compute the filling factor for a microstrip
78  * without cover and zero conductor thickness
79  */
80 double microstrip::filling_factor(double u, double e_r)
81 {
82  double a, b, q_inf;
83  double u2, u3, u4;
84  u2 = u * u;
85  u3 = u2 * u;
86  u4 = u3 * u;
87  a = 1.0 + log((u4 + u2 / 2704) / (u4 + 0.432)) / 49.0 + log(1.0 + u3 / 5929.741) / 18.7;
88  b = 0.564 * pow((e_r - 0.9) / (e_r + 3.0), 0.053);
89  q_inf = pow(1.0 + 10.0 / u, -a * b);
90  return q_inf;
91 }
92 
93 
94 /*
95  * delta_q_cover() - compute the cover effect on filling factor
96  */
97 double microstrip::delta_q_cover(double h2h)
98 {
99  double q_c;
100  q_c = tanh(1.043 + 0.121 * h2h - 1.164 / h2h);
101  return q_c;
102 }
103 
104 
105 /*
106  * delta_q_thickness() - compute the thickness effect on filling factor
107  */
108 double microstrip::delta_q_thickness(double u, double t_h)
109 {
110  double q_t;
111  q_t = (2.0 * log(2.0) / M_PI) * (t_h / sqrt(u));
112  return q_t;
113 }
114 
115 
116 /*
117  * e_r_effective() - compute effective dielectric constant from
118  * material e_r and filling factor
119  */
120 double microstrip::e_r_effective(double e_r, double q)
121 {
122  double e_r_eff;
123  e_r_eff = 0.5 * (e_r + 1.0) + 0.5 * q * (e_r - 1.0);
124  return e_r_eff;
125 }
126 
127 
128 /*
129  * delta_u_thickness - compute the thickness effect on normalized width
130  */
131 double microstrip::delta_u_thickness(double u, double t_h, double e_r)
132 {
133  double delta_u;
134  if (t_h > 0.0) {
135  /* correction for thickness for a homogeneous microstrip */
136  delta_u = (t_h / M_PI) * log(1.0 + (4.0 * M_E) * pow(tanh(sqrt(6.517 * u)), 2.0) / t_h);
137  /* correction for strip on a substrate with relative permettivity e_r */
138  delta_u = 0.5 * delta_u * (1.0 + 1.0 / cosh(sqrt(e_r - 1.0)));
139  } else {
140  delta_u = 0.0;
141  }
142  return delta_u;
143 }
144 
145 
146 /*
147  * microstrip_Z0() - compute microstrip static impedance
148  */
149 void microstrip::microstrip_Z0()
150 {
151  double e_r, h2, h2h, u, t_h;
152  double Z0_h_r, Z0;
153  double delta_u_1, delta_u_r, q_inf, q_c, q_t, e_r_eff, e_r_eff_t, q;
154 
155  e_r = er;
156  h2 = ht;
157  h2h = h2 / h;
158  u = w / h;
159  t_h = t / h;
160 
161  /* compute normalized width correction for e_r = 1.0 */
162  delta_u_1 = delta_u_thickness(u, t_h, 1.0);
163  /* compute homogeneous stripline impedance */
164  Z0_h_1 = Z0_homogeneous(u + delta_u_1);
165  /* compute normalized width corection */
166  delta_u_r = delta_u_thickness(u, t_h, e_r);
167  u += delta_u_r;
168  /* compute homogeneous stripline impedance */
169  Z0_h_r = Z0_homogeneous(u);
170 
171  /* filling factor, with width corrected for thickness */
172  q_inf = filling_factor(u, e_r);
173  /* cover effect */
174  q_c = delta_q_cover(h2h);
175  /* thickness effect */
176  q_t = delta_q_thickness(u, t_h);
177  /* resultant filling factor */
178  q = (q_inf - q_t) * q_c;
179 
180  /* e_r corrected for thickness and non homogeneous material */
181  e_r_eff_t = e_r_effective(e_r, q);
182 
183  /* effective dielectric constant */
184  e_r_eff = e_r_eff_t * pow(Z0_h_1 / Z0_h_r, 2.0);
185 
186  /* characteristic impedance, corrected for thickness, cover */
187  /* and non homogeneous material */
188  Z0 = Z0_h_r / sqrt(e_r_eff_t);
189 
190  w_eff = u * h;
191  er_eff_0 = e_r_eff;
192  Z0_0 = Z0;
193 }
194 
195 
196 /*
197  * e_r_dispersion() - computes the dispersion correction factor for
198  * the effective permeability
199  */
200 double microstrip::e_r_dispersion(double u, double e_r, double f_n)
201 {
202  double P_1, P_2, P_3, P_4, P;
203 
204  P_1 = 0.27488 + u * (0.6315 + 0.525 / pow(1.0 + 0.0157 * f_n, 20.0)) - 0.065683 * exp(-8.7513 * u);
205  P_2 = 0.33622 * (1.0 - exp(-0.03442 * e_r));
206  P_3 = 0.0363 * exp(-4.6 * u) * (1.0 - exp(-pow(f_n / 38.7, 4.97)));
207  P_4 = 1.0 + 2.751 * (1.0 - exp(-pow(e_r / 15.916, 8.0)));
208 
209  P = P_1 * P_2 * pow((P_3 * P_4 + 0.1844) * f_n, 1.5763);
210 
211  return P;
212 }
213 
214 
215 /*
216  * Z0_dispersion() - computes the dispersion correction factor for the
217  * characteristic impedance
218  */
219 double microstrip::Z0_dispersion(double u, double e_r, double e_r_eff_0, double e_r_eff_f, double f_n)
220 {
221  double R_1, R_2, R_3, R_4, R_5, R_6, R_7, R_8, R_9, R_10, R_11, R_12, R_13, R_14, R_15, R_16, R_17, D, tmpf;
222 
223  R_1 = 0.03891 * pow(e_r, 1.4);
224  R_2 = 0.267 * pow(u, 7.0);
225  R_3 = 4.766 * exp(-3.228 * pow(u, 0.641));
226  R_4 = 0.016 + pow(0.0514 * e_r, 4.524);
227  R_5 = pow(f_n / 28.843, 12.0);
228  R_6 = 22.2 * pow(u, 1.92);
229  R_7 = 1.206 - 0.3144 * exp(-R_1) * (1.0 - exp(-R_2));
230  R_8 = 1.0 + 1.275 * (1.0 - exp(-0.004625 * R_3 * pow(e_r, 1.674) * pow(f_n / 18.365, 2.745)));
231  tmpf = pow(e_r - 1.0, 6.0);
232  R_9 = 5.086 * R_4 * (R_5 / (0.3838 + 0.386 * R_4)) * (exp(-R_6) / (1.0 + 1.2992 * R_5)) * (tmpf / (1.0 + 10.0 * tmpf));
233  R_10 = 0.00044 * pow(e_r, 2.136) + 0.0184;
234  tmpf = pow(f_n / 19.47, 6.0);
235  R_11 = tmpf / (1.0 + 0.0962 * tmpf);
236  R_12 = 1.0 / (1.0 + 0.00245 * u * u);
237  R_13 = 0.9408 * pow(e_r_eff_f, R_8) - 0.9603;
238  R_14 = (0.9408 - R_9) * pow(e_r_eff_0, R_8) - 0.9603;
239  R_15 = 0.707 * R_10 * pow(f_n / 12.3, 1.097);
240  R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * (1.0 - exp(-pow(u / 15.0, 6.0)));
241  R_17 = R_7 * (1.0 - 1.1241 * (R_12 / R_16) * exp(-0.026 * pow(f_n, 1.15656) - R_15));
242 
243  D = pow(R_13 / R_14, R_17);
244 
245  return D;
246 }
247 
248 
249 /*
250  * dispersion() - compute frequency dependent parameters of
251  * microstrip
252  */
253 void microstrip::dispersion()
254 {
255  double e_r, e_r_eff_0;
256  double u, f_n, P, e_r_eff_f, D, Z0_f;
257 
258  e_r = er;
259  e_r_eff_0 = er_eff_0;
260  u = w / h;
261 
262  /* normalized frequency [GHz * mm] */
263  f_n = f * h / 1e06;
264 
265  P = e_r_dispersion(u, e_r, f_n);
266  /* effective dielectric constant corrected for dispersion */
267  e_r_eff_f = e_r - (e_r - e_r_eff_0) / (1.0 + P);
268 
269  D = Z0_dispersion(u, e_r, e_r_eff_0, e_r_eff_f, f_n);
270  Z0_f = Z0_0 * D;
271 
272  er_eff = e_r_eff_f;
273  Z0 = Z0_f;
274 }
275 
276 
277 /*
278  * conductor_losses() - compute microstrip conductor losses per unit
279  * length
280  */
281 double microstrip::conductor_losses()
282 {
283  double e_r_eff_0, delta;
284  double K, R_s, Q_c, alpha_c;
285 
286  e_r_eff_0 = er_eff_0;
287  delta = skindepth;
288 
289  if (f > 0.0) {
290  /* current distribution factor */
291  K = exp(-1.2 * pow(Z0_h_1 / ZF0, 0.7));
292  /* skin resistance */
293  R_s = 1.0 / (sigma * delta);
294 
295  /* correction for surface roughness */
296  R_s *= 1.0 + ((2.0 / M_PI) * atan(1.40 * pow((rough / delta), 2.0)));
297  /* strip inductive quality factor */
298  Q_c = (M_PI * Z0_h_1 * w * f) / (R_s * C0 * K);
299  alpha_c = (20.0 * M_PI / log(10.0)) * f * sqrt(e_r_eff_0) / (C0 * Q_c);
300  } else {
301  alpha_c = 0.0;
302  }
303 
304  return alpha_c;
305 }
306 
307 
308 /*
309  * dielectric_losses() - compute microstrip dielectric losses per unit
310  * length
311  */
312 double microstrip::dielectric_losses()
313 {
314  double e_r, e_r_eff_0;
315  double alpha_d;
316 
317  e_r = er;
318  e_r_eff_0 = er_eff_0;
319 
320  alpha_d = (20.0 * M_PI / log(10.0)) * (f / C0) * (e_r / sqrt(e_r_eff_0)) * ((e_r_eff_0 - 1.0) / (e_r - 1.0)) * tand;
321 
322  return alpha_d;
323 }
324 
325 
326 /*
327  * attenuation() - compute attenuation of microstrip
328  */
329 void microstrip::attenuation()
330 {
331  skindepth = skin_depth();
332 
333  atten_cond = conductor_losses() * l;
334  atten_dielectric = dielectric_losses() * l;
335 }
336 
337 
338 /*
339  * mur_eff_ms() - returns effective magnetic permeability
340  */
341 void microstrip::mur_eff_ms()
342 {
343  double mureff;
344 
345  mureff = (2.0 * mur) / ((1.0 + mur) + ((1.0 - mur) * pow((1.0 + (10.0 * h / w)), -0.5)));
346 
347  mur_eff = mureff;
348 }
349 
350 
351 /*
352  * synth_width - calculate width given Z0 and e_r
353  */
354 double microstrip::synth_width()
355 {
356  double e_r, a, b;
357  double w_h, w;
358 
359 
360  e_r = er;
361 
362 
363  a = ((Z0 / ZF0 / 2 / M_PI) * sqrt((e_r + 1) / 2.)) + ((e_r - 1) / (e_r + 1) * (0.23 + (0.11 / e_r)));
364  b = ZF0 / 2 * M_PI / (Z0 * sqrt(e_r));
365 
366  if (a > 1.52) {
367  w_h = 8 * exp(a) / (exp(2. * a) - 2);
368  } else {
369  w_h = (2. / M_PI) * (b - 1. - log((2 * b) - 1.) + ((e_r - 1) / (2 * e_r)) * (log(b - 1.) + 0.39 - 0.61 / e_r));
370  }
371 
372  if (h > 0.0) {
373  w = w_h * h;
374  return w;
375  } else {
376  w = 0;
377  }
378  return w;
379 }
380 
381 
382 /*
383  * line_angle() - calculate microstrip length in radians
384  */
385 void microstrip::line_angle()
386 {
387  double e_r_eff;
388  double v, lambda_g;
389 
390  e_r_eff = er_eff;
391 
392  /* velocity */
393  v = C0 / sqrt(e_r_eff * mur_eff);
394  /* wavelength */
395  lambda_g = v / f;
396  /* electrical angles */
397  ang_l = 2.0 * M_PI * l / lambda_g; /* in radians */
398 }
399 
400 
401 void microstrip::calc()
402 {
403  /* effective permeability */
404  mur_eff_ms();
405  /* static impedance */
406  microstrip_Z0();
407  /* calculate freq dependence of er and Z0 */
408  dispersion();
409  /* calculate electrical lengths */
410  line_angle();
411  /* calculate losses */
412  attenuation();
413 }
414 
415 
416 /*
417  * get_microstrip_sub () - get and assign microstrip substrate
418  * parameters into microstrip structure
419  */
420 void microstrip::get_microstrip_sub()
421 {
422  er = getProperty ("Er");
423  mur = getProperty ("Mur");
424  h = getProperty ("H", UNIT_LENGTH, LENGTH_M);
425  ht = getProperty ("H_t", UNIT_LENGTH, LENGTH_M);
426  t = getProperty ("T", UNIT_LENGTH, LENGTH_M);
427  sigma = getProperty ("Cond");
428  tand = getProperty ("Tand");
429  rough = getProperty ("Rough", UNIT_LENGTH, LENGTH_M);
430 }
431 
432 /*
433  * get_microstrip_comp() - get and assign microstrip component
434  * parameters into microstrip structure
435  */
436 void microstrip::get_microstrip_comp()
437 {
438  f = getProperty ("Freq", UNIT_FREQ, FREQ_HZ);
439 }
440 
441 /*
442  * get_microstrip_elec() - get and assign microstrip electrical
443  * parameters into microstrip structure
444  */
445 void microstrip::get_microstrip_elec()
446 {
447  Z0 = getProperty ("Z0", UNIT_RES, RES_OHM);
448  ang_l = getProperty ("Ang_l", UNIT_ANG, ANG_RAD);
449 }
450 
451 
452 /*
453  * get_microstrip_phys() - get and assign microstrip physical
454  * parameters into microstrip structure
455  */
456 void microstrip::get_microstrip_phys()
457 {
458  w = getProperty ("W", UNIT_LENGTH, LENGTH_M);
459  l = getProperty ("L", UNIT_LENGTH, LENGTH_M);
460 }
461 
462 
463 void microstrip::show_results()
464 {
465  setProperty ("Z0", Z0, UNIT_RES, RES_OHM);
466  setProperty ("Ang_l", ang_l, UNIT_ANG, ANG_RAD);
467 
468  setResult (0, er_eff, "");
469  setResult (1, atten_cond, "dB");
470  setResult (2, atten_dielectric, "dB");
471 
472  double val = convertProperty ("T", skindepth, UNIT_LENGTH, LENGTH_M);
473  setResult (3, val, getUnit ("T"));
474 }
475 
476 /*
477  * analysis function
478  */
480 {
481  /* Get and assign substrate parameters */
482  get_microstrip_sub();
483 
484  /* Get and assign component parameters */
485  get_microstrip_comp();
486 
487  /* Get and assign physical parameters */
488  get_microstrip_phys();
489 
490  /* compute microstrip parameters */
491  calc();
492 
493  /* print results in the subwindow */
494  show_results();
495 }
496 
497 
498 #define MAX_ERROR 0.000001
499 
500 /*
501  * synthesis function
502  */
504 {
505  double Z0_dest, Z0_current, Z0_result, increment, slope, error;
506  int iteration;
507 
508  /* Get and assign substrate parameters */
509  get_microstrip_sub();
510 
511  /* Get and assign component parameters */
512  get_microstrip_comp();
513 
514  /* Get and assign electrical parameters */
515  get_microstrip_elec();
516 
517  /* Get and assign physical parameters */
518  /* at present it is required only for getting strips length */
519  get_microstrip_phys();
520 
521 
522  /* calculate width and use for initial value in Newton's method */
523  w = synth_width();
524 
525  /* required value of Z0 */
526  Z0_dest = Z0;
527 
528  /* Newton's method */
529  iteration = 0;
530 
531  /* compute microstrip parameters */
532  calc();
533  Z0_current = Z0;
534 
535  error = fabs(Z0_dest - Z0_current);
536 
537  while (error > MAX_ERROR) {
538  iteration++;
539  increment = (w / 100.0);
540  w += increment;
541  /* compute microstrip parameters */
542  calc();
543  Z0_result = Z0;
544  /* f(w(n)) = Z0 - Z0(w(n)) */
545  /* f'(w(n)) = -f'(Z0(w(n))) */
546  /* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */
547  /* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
548  slope = (Z0_result - Z0_current) / increment;
549  /* printf("%g\n",slope); */
550  w += (Z0_dest - Z0_current) / slope - increment;
551  /* printf("ms->w = %g\n", ms->w); */
552  /* find new error */
553  /* compute microstrip parameters */
554  calc();
555  Z0_current = Z0;
556  error = fabs(Z0_dest - Z0_current);
557  /* printf("Iteration = %d\n",iteration);
558  printf("w = %g\t Z0 = %g\n",ms->w, Z0_current); */
559  if (iteration > 100)
560  break;
561  }
562 
563  setProperty ("W", w, UNIT_LENGTH, LENGTH_M);
564  /* calculate physical length */
565  ang_l = getProperty ("Ang_l", UNIT_ANG, ANG_RAD);
566  l = C0 / f / sqrt(er_eff * mur_eff) * ang_l / 2.0 / M_PI; /* in m */
567  setProperty ("L", l, UNIT_LENGTH, LENGTH_M);
568 
569  /* compute microstrip parameters */
570  calc();
571 
572  /* print results in the subwindow */
573  show_results();
574 
575 }