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