My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
msline.cpp
Go to the documentation of this file.
1 /*
2  * msline.cpp - microstrip transmission line class implementation
3  *
4  * Copyright (C) 2004, 2005, 2006, 2008 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: msline.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include "component.h"
30 #include "substrate.h"
31 #include "msline.h"
32 
33 msline::msline () : circuit (2) {
34  alpha = beta = zl = ereff = 0;
35  type = CIR_MSLINE;
36 }
37 
38 void msline::calcNoiseSP (nr_double_t) {
39  nr_double_t l = getPropertyDouble ("L");
40  if (l < 0) return;
41  // calculate noise using Bosma's theorem
42  nr_double_t T = getPropertyDouble ("Temp");
43  matrix s = getMatrixS ();
44  matrix e = eye (getSize ());
45  setMatrixN (kelvin (T) / T0 * (e - s * transpose (conj (s))));
46 }
47 
48 void msline::calcPropagation (nr_double_t frequency) {
49 
50  /* how to get properties of this component, e.g. L, W */
51  nr_double_t W = getPropertyDouble ("W");
52  char * SModel = getPropertyString ("Model");
53  char * DModel = getPropertyString ("DispModel");
54 
55  /* how to get properties of the substrate, e.g. Er, H */
56  substrate * subst = getSubstrate ();
57  nr_double_t er = subst->getPropertyDouble ("er");
58  nr_double_t h = subst->getPropertyDouble ("h");
59  nr_double_t t = subst->getPropertyDouble ("t");
60  nr_double_t tand = subst->getPropertyDouble ("tand");
61  nr_double_t rho = subst->getPropertyDouble ("rho");
62  nr_double_t D = subst->getPropertyDouble ("D");
63 
64  /* local variables */
65  nr_double_t ac, ad;
66  nr_double_t ZlEff, ErEff, WEff, ZlEffFreq, ErEffFreq;
67 
68  // quasi-static effective dielectric constant of substrate + line and
69  // the impedance of the microstrip line
70  analyseQuasiStatic (W, h, t, er, SModel, ZlEff, ErEff, WEff);
71 
72  // analyse dispersion of Zl and Er (use WEff here?)
73  analyseDispersion (W, h, er, ZlEff, ErEff, frequency, DModel,
74  ZlEffFreq, ErEffFreq);
75 
76  // analyse losses of line
77  analyseLoss (W, t, er, rho, D, tand, ZlEff, ZlEff, ErEff,
78  frequency, "Hammerstad", ac, ad);
79 
80  // calculate propagation constants and reference impedance
81  zl = ZlEffFreq;
82  ereff = ErEffFreq;
83  alpha = ac + ad;
84  beta = sqrt (ErEffFreq) * 2 * M_PI * frequency / C0;
85 }
86 
87 void msline::calcSP (nr_double_t frequency) {
88  nr_double_t l = getPropertyDouble ("L");
89 
90  // calculate propagation constants
91  calcPropagation (frequency);
92 
93  // calculate S-parameters
94  nr_double_t z = zl / z0;
95  nr_double_t y = 1 / z;
96  nr_complex_t g = rect (alpha, beta);
97  nr_complex_t n = 2.0 * cosh (g * l) + (z + y) * sinh (g * l);
98  nr_complex_t s11 = (z - y) * sinh (g * l) / n;
99  nr_complex_t s21 = 2.0 / n;
100  setS (NODE_1, NODE_1, s11); setS (NODE_2, NODE_2, s11);
101  setS (NODE_1, NODE_2, s21); setS (NODE_2, NODE_1, s21);
102 }
103 
104 void msline::saveCharacteristics (nr_double_t) {
105  setCharacteristic ("Zl", zl);
106  setCharacteristic ("Er", ereff);
107 }
108 
109 /* This function calculates the quasi-static impedance of a microstrip
110  line, the value of the effective dielectric constant and the
111  effective width due to the finite conductor thickness for the given
112  microstrip line and substrate properties. */
113 void msline::analyseQuasiStatic (nr_double_t W, nr_double_t h, nr_double_t t,
114  nr_double_t er, char * Model,
115  nr_double_t& ZlEff, nr_double_t& ErEff,
116  nr_double_t& WEff) {
117 
118  nr_double_t z, e;
119 
120  // default values
121  e = er;
122  z = z0;
123  WEff = W;
124 
125  // WHEELER
126  if (!strcmp (Model, "Wheeler")) {
127  nr_double_t a, b, c, d, x, dW1, dWr, Wr;
128 
129  // compute strip thickness effect
130  if (t != 0) {
131  dW1 = t / M_PI * log (4 * M_E / sqrt (sqr (t / h) +
132  sqr (M_1_PI / (W / t + 1.10))));
133  }
134  else dW1 = 0;
135  dWr = (1 + 1 / er) / 2 * dW1;
136  Wr = WEff = W + dWr;
137 
138  // compute characteristic impedance
139  if (W / h < 3.3) {
140  c = log (4 * h / Wr + sqrt (sqr (4 * h / Wr) + 2));
141  b = (er - 1) / (er + 1) / 2 * (log (M_PI_2) + log (2 * M_2_PI) / er);
142  z = (c - b) * Z0 / M_PI / sqrt (2 * (er + 1));
143  }
144  else {
145  c = 1 + log (M_PI_2) + log (Wr / h / 2 + 0.94);
146  d = M_1_PI / 2 * (1 + log (sqr (M_PI) / 16)) * (er - 1) / sqr (er);
147  x = 2 * M_LN2 / M_PI + Wr / h / 2 + (er + 1) / 2 / M_PI / er * c + d;
148  z = Z0 / 2 / x / sqrt (er);
149  }
150 
151  // compute effective dielectric constant
152  if (W / h < 1.3) {
153  a = log (8 * h / Wr) + sqr (Wr / h) / 32;
154  b = (er - 1) / (er + 1) / 2 * (log (M_PI_2) + log (2 * M_2_PI) / er);
155  e = (er + 1) / 2 * sqr (a / (a - b));
156  }
157  else {
158  a = (er - 1) / 2 / M_PI / er * (log (2.1349 * Wr / h + 4.0137) -
159  0.5169 / er);
160  b = Wr / h / 2 + M_1_PI * log (8.5397 * Wr / h + 16.0547);
161  e = er * sqr ((b - a) / b);
162  }
163  }
164  // SCHNEIDER
165  else if (!strcmp (Model, "Schneider")) {
166 
167  nr_double_t dW = 0, u = W / h;
168 
169  // consider strip thickness equations
170  if (t != 0 && t < W / 2) {
171  nr_double_t arg = (u < M_1_PI / 2) ? 2 * M_PI * W / t : h / t;
172  dW = t / M_PI * (1 + log (2 * arg));
173  if (t / dW >= 0.75) dW = 0;
174  }
175  WEff = W + dW; u = WEff / h;
176 
177  // effective dielectric constant
178  e = (er + 1) / 2 + (er - 1) / 2 / sqrt (1 + 10 / u);
179 
180  // characteristic impedance
181  if (u < 1.0) {
182  z = M_1_PI / 2 * log (8 / u + u / 4);
183  }
184  else {
185  z = 1 / (u + 2.42 - 0.44 / u + pow (1 - 1 / u, 6));
186  }
187  z = Z0 * z / sqrt (e);
188  }
189  // HAMMERSTAD and JENSEN
190  else if (!strcmp (Model, "Hammerstad")) {
191  nr_double_t a, b, du1, du, u, ur, u1, zr, z1;
192 
193  u = W / h; // normalized width
194  t = t / h; // normalized thickness
195 
196  // compute strip thickness effect
197  if (t != 0) {
198  du1 = t / M_PI * log (1 + 4 * M_E / t / sqr (coth (sqrt (6.517 * u))));
199  }
200  else du1 = 0;
201  du = du1 * (1 + sech (sqrt (er - 1))) / 2;
202  u1 = u + du1;
203  ur = u + du;
204  WEff = ur * h;
205 
206  // compute impedances for homogeneous medium
207  Hammerstad_zl (ur, zr);
208  Hammerstad_zl (u1, z1);
209 
210  // compute effective dielectric constant
211  Hammerstad_ab (ur, er, a, b);
212  Hammerstad_er (ur, er, a, b, e);
213 
214  // compute final characteristic impedance and dielectric constant
215  // including strip thickness effects
216  z = zr / sqrt (e);
217  e = e * sqr (z1 / zr);
218  }
219 
220  ZlEff = z;
221  ErEff = e;
222 }
223 
224 /* This function calculates the frequency dependent value of the
225  effective dielectric constant and the microstrip line impedance for
226  the given frequency. */
227 void msline::analyseDispersion (nr_double_t W, nr_double_t h, nr_double_t er,
228  nr_double_t ZlEff, nr_double_t ErEff,
229  nr_double_t frequency, char * Model,
230  nr_double_t& ZlEffFreq,
231  nr_double_t& ErEffFreq) {
232 
233  nr_double_t e, z;
234 
235  // default values
236  z = ZlEffFreq = ZlEff;
237  e = ErEffFreq = ErEff;
238 
239  // GETSINGER
240  if (!strcmp (Model, "Getsinger")) {
241  Getsinger_disp (h, er, ErEff, ZlEff, frequency, e, z);
242  }
243  // SCHNEIDER
244  else if (!strcmp (Model, "Schneider")) {
245  nr_double_t k, f;
246  k = sqrt (ErEff / er);
247  f = 4 * h * frequency / C0 * sqrt (er - 1);
248  f = sqr (f);
249  e = ErEff * sqr ((1 + f) / (1 + k * f));
250  z = ZlEff * sqrt (ErEff / e);
251  }
252  // YAMASHITA
253  else if (!strcmp (Model, "Yamashita")) {
254  nr_double_t k, f;
255  k = sqrt (er / ErEff);
256  f = 4 * h * frequency / C0 * sqrt (er - 1) *
257  (0.5 + sqr (1 + 2 * log10 (1 + W / h)));
258  e = ErEff * sqr ((1 + k * pow (f, 1.5) / 4) / (1 + pow (f, 1.5) / 4));
259  }
260  // KOBAYASHI
261  else if (!strcmp (Model, "Kobayashi")) {
262  nr_double_t n, no, nc, fh, fk;
263  fk = C0 * atan (er * sqrt ((ErEff - 1) / (er - ErEff))) /
264  (2 * M_PI * h * sqrt (er - ErEff));
265  fh = fk / (0.75 + (0.75 - 0.332 / pow (er, 1.73)) * W / h);
266  no = 1 + 1 / (1 + sqrt (W / h)) + 0.32 * cubic (1 / (1 + sqrt (W / h)));
267  if (W / h < 0.7) {
268  nc = 1 + 1.4 / (1 + W / h) * (0.15 - 0.235 *
269  exp (-0.45 * frequency / fh));
270  }
271  else nc = 1;
272  n = no * nc < 2.32 ? no * nc : 2.32;
273  e = er - (er - ErEff) / (1 + pow (frequency / fh, n));
274  }
275  // PRAMANICK and BHARTIA
276  else if (!strcmp (Model, "Pramanick")) {
277  nr_double_t Weff, We, f;
278  f = 2 * MU0 * h * frequency * sqrt (ErEff / er) / ZlEff;
279  e = er - (er - ErEff) / (1 + sqr (f));
280  Weff = Z0 * h / ZlEff / sqrt (ErEff);
281  We = W + (Weff - W) / (1 + sqr (f));
282  z = Z0 * h / We / sqrt (e);
283  }
284  // HAMMERSTAD and JENSEN
285  else if (!strcmp (Model, "Hammerstad")) {
286  nr_double_t f, g;
287  g = sqr (M_PI) / 12 * (er - 1) / ErEff * sqrt (2 * M_PI * ZlEff / Z0);
288  f = 2 * MU0 * h * frequency / ZlEff;
289  e = er - (er - ErEff) / (1 + g * sqr (f));
290  z = ZlEff * sqrt (ErEff / e) * (e - 1) / (ErEff - 1);
291  }
292  // KIRSCHNING and JANSEN
293  else if (!strcmp (Model, "Kirschning")) {
294  nr_double_t r17, u = W / h, fn = frequency * h / 1e6;
295 
296  // dispersion of dielectric constant
297  Kirschning_er (u, fn, er, ErEff, e);
298 
299  // dispersion of characteristic impedance
300  Kirschning_zl (u, fn, er, ErEff, e, ZlEff, r17, z);
301  }
302 
303  ZlEffFreq = z;
304  ErEffFreq = e;
305 }
306 
307 /* Computes the exponent factors a(u) and b(er) used within the
308  effective relative dielectric constant calculations for single and
309  coupled microstrip lines by Hammerstad and Jensen. */
310 void msline::Hammerstad_ab (nr_double_t u, nr_double_t er, nr_double_t& a,
311  nr_double_t& b) {
312  a = 1 + log ((quadr (u) + sqr (u / 52)) / (quadr (u) + 0.432)) / 49 +
313  log (1 + cubic (u / 18.1)) / 18.7;
314  b = 0.564 * pow ((er - 0.9) / (er + 3), 0.053);
315 }
316 
317 /* The function computes the effective dielectric constant of a single
318  microstrip. The equation is used in single and coupled microstrip
319  calculations. */
320 void msline::Hammerstad_er (nr_double_t u, nr_double_t er, nr_double_t a,
321  nr_double_t b, nr_double_t& e) {
322  e = (er + 1) / 2 + (er - 1) / 2 * pow (1 + 10 / u, -a * b);
323 }
324 
325 /* This function computes the characteristic impedance of single
326  microstrip line based upon the given width-height ratio. The
327  equation is used in single and coupled microstrip calculations as
328  well. */
329 void msline::Hammerstad_zl (nr_double_t u, nr_double_t& zl) {
330  nr_double_t fu = 6 + (2 * M_PI - 6) * exp (- pow (30.666 / u, 0.7528));
331  zl = Z0 / 2 / M_PI * log (fu / u + sqrt (1 + sqr (2 / u)));
332 }
333 
334 /* Calculates dispersion effects for effective dielectric constant and
335  characteristic impedance as defined by Getsinger (for single and
336  coupled microstrips). */
337 void msline::Getsinger_disp (nr_double_t h, nr_double_t er, nr_double_t ErEff,
338  nr_double_t ZlEff, nr_double_t frequency,
339  nr_double_t& e, nr_double_t& z) {
340  nr_double_t g, f, d;
341  g = 0.6 + 0.009 * ZlEff;
342  f = frequency * 2 * MU0 * h / ZlEff;
343  e = er - (er - ErEff) / (1 + g * sqr (f));
344  d = (er - e) * (e - ErEff) / e / (er - ErEff);
345  z = ZlEff * sqrt (e / ErEff) / (1 + d); // group delay model
346 }
347 
348 /* This function computes the dispersion of the effective dielectric
349  constant of a single microstrip line. It is defined in a separate
350  function because it is used within the coupled microstrip lines as
351  well. */
352 void msline::Kirschning_er (nr_double_t u, nr_double_t fn, nr_double_t er,
353  nr_double_t ErEff, nr_double_t& ErEffFreq) {
354  nr_double_t p, p1, p2, p3, p4;
355  p1 = 0.27488 + (0.6315 + 0.525 / pow (1 + 0.0157 * fn, 20)) * u -
356  0.065683 * exp (-8.7513 * u);
357  p2 = 0.33622 * (1 - exp (-0.03442 * er));
358  p3 = 0.0363 * exp (-4.6 * u) * (1 - exp (- pow (fn / 38.7, 4.97)));
359  p4 = 1 + 2.751 * (1 - exp (- pow (er / 15.916, 8)));
360  p = p1 * p2 * pow ((0.1844 + p3 * p4) * fn, 1.5763);
361  ErEffFreq = er - (er - ErEff) / (1 + p);
362 }
363 
364 /* Computes dispersion effects of characteristic impedance of a single
365  microstrip line according to Kirschning and Jansen. Also used in
366  coupled microstrip lines calculations. */
367 void msline::Kirschning_zl (nr_double_t u, nr_double_t fn, nr_double_t er,
368  nr_double_t ErEff, nr_double_t ErEffFreq,
369  nr_double_t ZlEff, nr_double_t& r17,
370  nr_double_t& ZlEffFreq) {
371  nr_double_t r1, r2, r3, r4, r5, r6, r7, r8, r9, r10;
372  nr_double_t r11, r12, r13, r14, r15, r16;
373  r1 = 0.03891 * pow (er, 1.4);
374  r2 = 0.267 * pow (u, 7);
375  r3 = 4.766 * exp (-3.228 * pow (u, 0.641));
376  r4 = 0.016 + pow (0.0514 * er, 4.524);
377  r5 = pow (fn / 28.843, 12);
378  r6 = 22.20 * pow (u, 1.92);
379  r7 = 1.206 - 0.3144 * exp (-r1) * (1 - exp (-r2));
380  r8 = 1 + 1.275 * (1 - exp (-0.004625 * r3 *
381  pow (er, 1.674) * pow (fn / 18.365, 2.745)));
382  r9 = 5.086 * r4 * r5 / (0.3838 + 0.386 * r4) *
383  exp (-r6) / (1 + 1.2992 * r5) *
384  pow (er - 1, 6) / (1 + 10 * pow (er - 1, 6));
385  r10 = 0.00044 * pow (er, 2.136) + 0.0184;
386  r11 = pow (fn / 19.47, 6) / (1 + 0.0962 * pow (fn / 19.47, 6));
387  r12 = 1 / (1 + 0.00245 * sqr (u));
388  r13 = 0.9408 * pow (ErEffFreq, r8) - 0.9603;
389  r14 = (0.9408 - r9) * pow (ErEff, r8) - 0.9603;
390  r15 = 0.707 * r10 * pow (fn / 12.3, 1.097);
391  r16 = 1 + 0.0503 * sqr (er) * r11 * (1 - exp (- pow (u / 15, 6)));
392  r17 = r7 * (1 - 1.1241 * r12 / r16 *
393  exp (-0.026 * pow (fn, 1.15656) - r15));
394  ZlEffFreq = ZlEff * pow (r13 / r14, r17);
395 }
396 
397 /* The function calculates the conductor and dielectric losses of a
398  single microstrip line. */
399 void msline::analyseLoss (nr_double_t W, nr_double_t t, nr_double_t er,
400  nr_double_t rho, nr_double_t D, nr_double_t tand,
401  nr_double_t ZlEff1, nr_double_t ZlEff2,
402  nr_double_t ErEff,
403  nr_double_t frequency, const char * Model,
404  nr_double_t& ac, nr_double_t& ad) {
405  ac = ad = 0;
406 
407  // HAMMERSTAD and JENSEN
408  if (!strcmp (Model, "Hammerstad")) {
409  nr_double_t Rs, ds, l0, Kr, Ki;
410 
411  // conductor losses
412  if (t != 0.0) {
413  Rs = sqrt (M_PI * frequency * MU0 * rho); // skin resistance
414  ds = rho / Rs; // skin depth
415  // valid for t > 3 * ds
416  if (t < 3 * ds) {
418  "WARNING: conductor loss calculation invalid for line "
419  "height t (%g) < 3 * skin depth (%g)\n", t, 3 * ds);
420  }
421  // current distribution factor
422  Ki = exp (-1.2 * pow ((ZlEff1 + ZlEff2) / 2 / Z0, 0.7));
423  // D is RMS surface roughness
424  Kr = 1 + M_2_PI * atan (1.4 * sqr (D / ds));
425  ac = Rs / (ZlEff1 * W) * Ki * Kr;
426  }
427 
428  // dielectric losses
429  l0 = C0 / frequency;
430  ad = M_PI * er / (er - 1) * (ErEff - 1) / sqrt (ErEff) * tand / l0;
431  }
432 }
433 
434 void msline::initDC (void) {
435  nr_double_t l = getPropertyDouble ("L");
436  nr_double_t W = getPropertyDouble ("W");
437  substrate * subst = getSubstrate ();
438  nr_double_t t = subst->getPropertyDouble ("t");
439  nr_double_t rho = subst->getPropertyDouble ("rho");
440 
441  if (t != 0.0 && rho != 0.0 && l != 0.0) {
442  // tiny resistance
443  nr_double_t g = t * W / rho / l;
444  setVoltageSources (0);
445  allocMatrixMNA ();
446  setY (NODE_1, NODE_1, +g); setY (NODE_2, NODE_2, +g);
447  setY (NODE_1, NODE_2, -g); setY (NODE_2, NODE_1, -g);
448  }
449  else {
450  // a DC short (voltage source V = 0 volts)
451  setVoltageSources (1);
453  allocMatrixMNA ();
454  clearY ();
456  }
457 }
458 
459 void msline::initAC (void) {
460  setVoltageSources (0);
461  allocMatrixMNA ();
462 }
463 
464 void msline::calcAC (nr_double_t frequency) {
465  nr_double_t l = getPropertyDouble ("L");
466 
467  // calculate propagation constants
468  calcPropagation (frequency);
469 
470  // calculate Y-parameters
471  nr_complex_t g = rect (alpha, beta);
472  nr_complex_t y11 = coth (g * l) / zl;
473  nr_complex_t y21 = -cosech (g * l) / zl;
474  setY (NODE_1, NODE_1, y11); setY (NODE_2, NODE_2, y11);
475  setY (NODE_1, NODE_2, y21); setY (NODE_2, NODE_1, y21);
476 }
477 
478 void msline::calcNoiseAC (nr_double_t) {
479  nr_double_t l = getPropertyDouble ("L");
480  if (l < 0) return;
481  // calculate noise using Bosma's theorem
482  nr_double_t T = getPropertyDouble ("Temp");
483  setMatrixN (4 * kelvin (T) / T0 * real (getMatrixY ()));
484 }
485 
486 // properties
487 PROP_REQ [] = {
488  { "W", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
489  { "L", PROP_REAL, { 10e-3, PROP_NO_STR }, PROP_POS_RANGE },
490  { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
491  { "DispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" }, PROP_RNG_DIS },
492  { "Model", PROP_STR, { PROP_NO_VAL, "Hammerstad" }, PROP_RNG_MOD },
493  PROP_NO_PROP };
494 PROP_OPT [] = {
495  { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
496  PROP_NO_PROP };
497 struct define_t msline::cirdef =