Branch data Line data Source code
1 : : /*
2 : : * mslange.cpp - parallel coupled microstrip lines 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: mslange.cpp,v 1.25 2008/10/07 20:15:33 ela Exp $
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 : : #include "mslange.h"
33 : :
34 : : using namespace qucs;
35 : :
36 : 0 : mslange::mslange () : circuit (4) {
37 : 0 : type = CIR_MSLANGE;
38 : 0 : }
39 : :
40 : 0 : void mslange::calcPropagation (nr_double_t frequency) {
41 : :
42 : : // fetch line properties
43 [ # # ]: 0 : nr_double_t W = getPropertyDouble ("W");
44 [ # # ]: 0 : nr_double_t s = getPropertyDouble ("S");
45 [ # # ]: 0 : const char * const SModel = getPropertyString ("Model");
46 [ # # ]: 0 : const char * const DModel = getPropertyString ("DispModel");
47 : :
48 : : // fetch substrate properties
49 [ # # ]: 0 : substrate * subst = getSubstrate ();
50 [ # # ]: 0 : nr_double_t er = subst->getPropertyDouble ("er");
51 [ # # ]: 0 : nr_double_t h = subst->getPropertyDouble ("h");
52 [ # # ]: 0 : nr_double_t t = subst->getPropertyDouble ("t");
53 [ # # ]: 0 : nr_double_t tand = subst->getPropertyDouble ("tand");
54 [ # # ]: 0 : nr_double_t rho = subst->getPropertyDouble ("rho");
55 [ # # ]: 0 : nr_double_t D = subst->getPropertyDouble ("D");
56 : :
57 : : // quasi-static analysis
58 : : nr_double_t Zle, ErEffe, Zlo, ErEffo;
59 [ # # ]: 0 : analysQuasiStatic (W, h, s, t, er, SModel, Zle, Zlo, ErEffe, ErEffo);
60 : :
61 : : // analyse dispersion of Zl and Er
62 : : nr_double_t ZleFreq, ErEffeFreq, ZloFreq, ErEffoFreq;
63 : : analyseDispersion (W, h, s, er, Zle, Zlo, ErEffe, ErEffo, frequency, DModel,
64 [ # # ]: 0 : ZleFreq, ZloFreq, ErEffeFreq, ErEffoFreq);
65 : :
66 : : // analyse losses of line
67 : : nr_double_t ace, aco, ade, ado;
68 : : msline::analyseLoss (W, t, er, rho, D, tand, Zle, Zlo, ErEffe,
69 [ # # ]: 0 : frequency, "Hammerstad", ace, ade);
70 : : msline::analyseLoss (W, t, er, rho, D, tand, Zlo, Zle, ErEffo,
71 [ # # ]: 0 : frequency, "Hammerstad", aco, ado);
72 : :
73 : : // compute propagation constants for even and odd mode
74 : 0 : nr_double_t k0 = 2 * M_PI * frequency / C0;
75 : 0 : ae = ace + ade;
76 : 0 : ao = aco + ado;
77 [ # # ]: 0 : be = qucs::sqrt (ErEffeFreq) * k0;
78 [ # # ]: 0 : bo = qucs::sqrt (ErEffoFreq) * k0;
79 : 0 : ze = ZleFreq;
80 : 0 : zo = ZloFreq;
81 : 0 : ee = ErEffeFreq;
82 : 0 : eo = ErEffoFreq;
83 : 0 : }
84 : :
85 : 0 : void mslange::saveCharacteristics (nr_double_t) {
86 : 0 : setCharacteristic ("ZlEven", ze);
87 : 0 : setCharacteristic ("ErEven", ee);
88 : 0 : setCharacteristic ("ZlOdd", zo);
89 : 0 : setCharacteristic ("ErOdd", eo);
90 : 0 : }
91 : :
92 : 0 : void mslange::calcSP (nr_double_t frequency) {
93 : : // fetch line properties
94 [ # # ]: 0 : nr_double_t l = getPropertyDouble ("L");
95 : :
96 : : // compute propagation constants for even and odd mode
97 [ # # ]: 0 : calcPropagation (frequency);
98 : 0 : nr_complex_t ge = nr_complex_t (ae, be);
99 : 0 : nr_complex_t go = nr_complex_t (ao, bo);
100 : :
101 : : // compute abbreviations
102 : 0 : nr_complex_t Ee, Eo, De, Do, Xe, Xo, Ye, Yo;
103 [ # # ][ # # ]: 0 : Ee = (sqr (ze) + sqr (z0)) * qucs::sinh (ge * l);
[ # # ]
104 [ # # ][ # # ]: 0 : Eo = (sqr (zo) + sqr (z0)) * qucs::sinh (go * l);
[ # # ]
105 [ # # ][ # # ]: 0 : De = 2 * ze * z0 * cosh (ge * l) + Ee;
106 [ # # ][ # # ]: 0 : Do = 2 * zo * z0 * cosh (go * l) + Eo;
107 [ # # ][ # # ]: 0 : Xe = (sqr (ze) - sqr (z0)) * qucs::sinh (ge * l) / 2.0 / De;
[ # # ][ # # ]
108 [ # # ][ # # ]: 0 : Xo = (sqr (zo) - sqr (z0)) * qucs::sinh (go * l) / 2.0 / Do;
[ # # ][ # # ]
109 [ # # ]: 0 : Ye = ze * z0 / De;
110 [ # # ]: 0 : Yo = zo * z0 / Do;
111 : :
112 : : // reflexion coefficients
113 [ # # ][ # # ]: 0 : setS (NODE_1, NODE_1, Xe + Xo); setS (NODE_2, NODE_2, Xe + Xo);
[ # # ][ # # ]
114 [ # # ][ # # ]: 0 : setS (NODE_3, NODE_3, Xe + Xo); setS (NODE_4, NODE_4, Xe + Xo);
[ # # ][ # # ]
115 : : // through paths
116 [ # # ][ # # ]: 0 : setS (NODE_1, NODE_2, Ye + Yo); setS (NODE_2, NODE_1, Ye + Yo);
[ # # ][ # # ]
117 [ # # ][ # # ]: 0 : setS (NODE_3, NODE_4, Ye + Yo); setS (NODE_4, NODE_3, Ye + Yo);
[ # # ][ # # ]
118 : : // coupled paths
119 [ # # ][ # # ]: 0 : setS (NODE_1, NODE_4, Xe - Xo); setS (NODE_4, NODE_1, Xe - Xo);
[ # # ][ # # ]
120 [ # # ][ # # ]: 0 : setS (NODE_2, NODE_3, Xe - Xo); setS (NODE_3, NODE_2, Xe - Xo);
[ # # ][ # # ]
121 : : // isolated paths
122 [ # # ][ # # ]: 0 : setS (NODE_1, NODE_3, Ye - Yo); setS (NODE_3, NODE_1, Ye - Yo);
[ # # ][ # # ]
123 [ # # ][ # # ]: 0 : setS (NODE_2, NODE_4, Ye - Yo); setS (NODE_4, NODE_2, Ye - Yo);
[ # # ][ # # ]
124 : 0 : }
125 : :
126 : 0 : void mslange::calcNoiseSP (nr_double_t) {
127 : : // calculate noise using Bosma's theorem
128 [ # # ]: 0 : nr_double_t T = getPropertyDouble ("Temp");
129 [ # # ]: 0 : matrix s = getMatrixS ();
130 [ # # ]: 0 : matrix e = eye (getSize ());
131 [ # # ][ # # ]: 0 : setMatrixN (kelvin (T) / T0 * (e - s * transpose (conj (s))));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
132 : 0 : }
133 : :
134 : : /* The function calculates the quasi-static dielectric constants and
135 : : characteristic impedances for the even and odd mode based upon the
136 : : given line and substrate properties for parallel coupled microstrip
137 : : lines. */
138 : 0 : void mslange::analysQuasiStatic (nr_double_t W, nr_double_t h, nr_double_t s,
139 : : nr_double_t t, nr_double_t er,
140 : : const char * const SModel, nr_double_t& Zle,
141 : : nr_double_t& Zlo, nr_double_t& ErEffe,
142 : : nr_double_t& ErEffo) {
143 : : // initialize default return values
144 : 0 : ErEffe = ErEffo = er;
145 : 0 : Zlo = 42.2; Zle = 55.7;
146 : :
147 : : // normalized width and gap
148 : 0 : nr_double_t u = W / h;
149 : 0 : nr_double_t g = s / h;
150 : :
151 : : // HAMMERSTAD and JENSEN
152 [ # # ]: 0 : if (!strcmp (SModel, "Hammerstad")) {
153 : : nr_double_t Zl1, Fe, Fo, a, b, fo, Mu, Alpha, Beta, ErEff;
154 : : nr_double_t Pe, Po, r, fo1, q, p, n, Psi, Phi, m, Theta;
155 : :
156 : : // modifying equations for even mode
157 [ # # ][ # # ]: 0 : m = 0.2175 + qucs::pow (4.113 + qucs::pow (20.36 / g, 6.), -0.251) +
158 [ # # ][ # # ]: 0 : qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 13.8, 10.))) / 323;
[ # # ]
159 [ # # ]: 0 : Alpha = 0.5 * qucs::exp (-g);
160 [ # # ]: 0 : Psi = 1 + g / 1.45 + qucs::pow (g, 2.09) / 3.95;
161 [ # # ]: 0 : Phi = 0.8645 * qucs::pow (u, 0.172);
162 [ # # ][ # # ]: 0 : Pe = Phi / (Psi * (Alpha * qucs::pow (u, m) + (1 - Alpha) * qucs::pow (u, -m)));
163 : : // TODO: is this ... Psi * (Alpha ... or ... Psi / (Alpha ... ?
164 : :
165 : : // modifying equations for odd mode
166 [ # # ][ # # ]: 0 : n = (1 / 17.7 + qucs::exp (-6.424 - 0.76 * qucs::log (g) - qucs::pow (g / 0.23, 5.))) *
[ # # ]
167 [ # # ][ # # ]: 0 : qucs::log ((10 + 68.3 * sqr (g)) / (1 + 32.5 * qucs::pow (g, 3.093)));
[ # # ]
168 [ # # ][ # # ]: 0 : Beta = 0.2306 + qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 3.73, 10.))) / 301.8 +
[ # # ]
169 [ # # ][ # # ]: 0 : qucs::log (1 + 0.646 * qucs::pow (g, 1.175)) / 5.3;
170 [ # # ][ # # ]: 0 : Theta = 1.729 + 1.175 * qucs::log (1 + 0.627 / (g + 0.327 * qucs::pow (g, 2.17)));
171 [ # # ][ # # ]: 0 : Po = Pe - Theta / Psi * qucs::exp (Beta * qucs::pow (u, -n) * qucs::log (u));
[ # # ]
172 : :
173 : : // further modifying equations
174 [ # # ][ # # ]: 0 : r = 1 + 0.15 * (1 - qucs::exp (1 - sqr (er - 1) / 8.2) / (1 + qucs::pow (g, -6.)));
[ # # ]
175 [ # # ]: 0 : fo1 = 1 - qucs::exp (-0.179 * qucs::pow (g, 0.15) -
176 [ # # ][ # # ]: 0 : 0.328 * qucs::pow (g, r) / qucs::log (M_E + qucs::pow (g / 7, 2.8)));
[ # # ][ # # ]
177 [ # # ]: 0 : q = qucs::exp (-1.366 - g);
178 [ # # ][ # # ]: 0 : p = qucs::exp (-0.745 * qucs::pow (g, 0.295)) / qucs::cosh (qucs::pow (g, 0.68));
[ # # ][ # # ]
179 [ # # ][ # # ]: 0 : fo = fo1 * qucs::exp (p * qucs::log (u) + q * qucs::sin (M_PI * qucs::log10 (u)));
[ # # ][ # # ]
180 : :
181 [ # # ][ # # ]: 0 : Mu = g * qucs::exp (-g) + u * (20 + sqr (g)) / (10 + sqr (g));
[ # # ]
182 [ # # ]: 0 : msline::Hammerstad_ab (Mu, er, a, b);
183 [ # # ]: 0 : Fe = qucs::pow (1 + 10 / Mu, -a * b);
184 [ # # ]: 0 : msline::Hammerstad_ab (u, er, a, b);
185 [ # # ]: 0 : Fo = fo * qucs::pow (1 + 10 / u, -a * b);
186 : :
187 : : // finally compute effective dielectric constants and impedances
188 : 0 : ErEffe = (er + 1) / 2 + (er - 1) / 2 * Fe;
189 : 0 : ErEffo = (er + 1) / 2 + (er - 1) / 2 * Fo;
190 : :
191 [ # # ]: 0 : msline::Hammerstad_er (u, er, a, b, ErEff); // single microstrip
192 : :
193 : : // first variant
194 [ # # ]: 0 : Zl1 = Z0 / (u + 1.98 * qucs::pow (u, 0.172));
195 [ # # ]: 0 : Zl1 /= qucs::sqrt (ErEff);
196 : :
197 : : // second variant
198 [ # # ]: 0 : msline::Hammerstad_zl (u, Zl1);
199 [ # # ]: 0 : Zl1 /= qucs::sqrt (ErEff);
200 : :
201 : 0 : Zle = Zl1 / (1 - Zl1 * Pe / Z0);
202 : 0 : Zlo = Zl1 / (1 - Zl1 * Po / Z0);
203 : : }
204 : : // KIRSCHNING and JANSEN
205 [ # # ]: 0 : else if (!strcmp (SModel, "Kirschning")) {
206 : : nr_double_t a, b, ae, be, ao, bo, v, co, d, ErEff, Zl1;
207 : : nr_double_t q1, q2, q3, q4, q5, q6, q7, q8, q9, q10;
208 : :
209 : : // consider effect of finite strip thickness (JANSEN only)
210 : 0 : nr_double_t ue = u;
211 : 0 : nr_double_t uo = u;
212 [ # # ][ # # ]: 0 : if (t != 0 && s > 10 * (2 * t)) {
213 : 0 : nr_double_t dW = 0;
214 : : // SCHNEIDER, referred by JANSEN
215 [ # # ][ # # ]: 0 : if (u >= M_1_PI / 2 && M_1_PI / 2 > 2 * t / h)
216 [ # # ]: 0 : dW = t * (1 + qucs::log (2 * h / t)) / M_PI;
217 [ # # ]: 0 : else if (W > 2 * t)
218 [ # # ]: 0 : dW = t * (1 + qucs::log (4 * M_PI * W / t)) / M_PI;
219 : : // JANSEN
220 : 0 : nr_double_t dt = 2 * t * h / s / er;
221 [ # # ]: 0 : nr_double_t We = W + dW * (1 - 0.5 * qucs::exp (-0.69 * dW / dt));
222 : 0 : nr_double_t Wo = We + dt;
223 : 0 : ue = We / h;
224 : 0 : uo = Wo / h;
225 : : }
226 : :
227 : : // even relative dielectric constant
228 [ # # ][ # # ]: 0 : v = ue * (20 + sqr (g)) / (10 + sqr (g)) + g * qucs::exp (-g);
[ # # ]
229 [ # # ]: 0 : msline::Hammerstad_ab (v, er, ae, be);
230 [ # # ]: 0 : msline::Hammerstad_er (v, er, ae, be, ErEffe);
231 : :
232 : : // odd relative dielectric constant
233 [ # # ]: 0 : msline::Hammerstad_ab (uo, er, a, b);
234 [ # # ]: 0 : msline::Hammerstad_er (uo, er, a, b, ErEff);
235 [ # # ]: 0 : d = 0.593 + 0.694 * qucs::exp (-0.562 * uo);
236 : 0 : bo = 0.747 * er / (0.15 + er);
237 [ # # ]: 0 : co = bo - (bo - 0.207) * qucs::exp (-0.414 * uo);
238 [ # # ]: 0 : ao = 0.7287 * (ErEff - (er + 1) / 2) * (1 - qucs::exp (-0.179 * uo));
239 [ # # ][ # # ]: 0 : ErEffo = ((er + 1) / 2 + ao - ErEff) * qucs::exp (-co * qucs::pow (g, d)) + ErEff;
240 : :
241 : : // characteristic impedance of single line
242 [ # # ]: 0 : msline::Hammerstad_zl (u, Zl1);
243 [ # # ]: 0 : Zl1 /= qucs::sqrt (ErEff);
244 : :
245 : : // even characteristic impedance
246 [ # # ]: 0 : q1 = 0.8695 * qucs::pow (ue, 0.194);
247 [ # # ]: 0 : q2 = 1 + 0.7519 * g + 0.189 * qucs::pow (g, 2.31);
248 [ # # ][ # # ]: 0 : q3 = 0.1975 + qucs::pow (16.6 + qucs::pow (8.4 / g, 6.), -0.387) +
249 [ # # ][ # # ]: 0 : qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 3.4, 10.))) / 241;
[ # # ]
250 : : q4 = q1 / q2 * 2 /
251 [ # # ][ # # ]: 0 : (qucs::exp (-g) * qucs::pow (ue, q3) + (2 - qucs::exp (-g)) * qucs::pow (ue, -q3));
[ # # ][ # # ]
252 [ # # ][ # # ]: 0 : Zle = qucs::sqrt (ErEff / ErEffe) * Zl1 / (1 - Zl1 * qucs::sqrt (ErEff) * q4 / Z0);
253 : :
254 : : // odd characteristic impedance
255 [ # # ][ # # ]: 0 : q5 = 1.794 + 1.14 * qucs::log (1 + 0.638 / (g + 0.517 * qucs::pow (g, 2.43)));
256 [ # # ][ # # ]: 0 : q6 = 0.2305 + qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 5.8, 10.))) / 281.3 +
[ # # ]
257 [ # # ][ # # ]: 0 : qucs::log (1 + 0.598 * qucs::pow (g, 1.154)) / 5.1;
258 [ # # ]: 0 : q7 = (10 + 190 * sqr (g)) / (1 + 82.3 * cubic (g));
259 [ # # ][ # # ]: 0 : q8 = qucs::exp (-6.5 - 0.95 * qucs::log (g) - qucs::pow (g / 0.15, 5.));
[ # # ]
260 [ # # ]: 0 : q9 = qucs::log (q7) * (q8 + 1 / 16.5);
261 [ # # ][ # # ]: 0 : q10 = (q2 * q4 - q5 * qucs::exp (qucs::log (uo) * q6 * qucs::pow (uo, -q9))) / q2;
[ # # ]
262 [ # # ][ # # ]: 0 : Zlo = qucs::sqrt (ErEff / ErEffo) * Zl1 / (1 - Zl1 * qucs::sqrt (ErEff) * q10 / Z0);
263 : : }
264 : : // nr_double_t Zle4, Zlo4, C, Z04;
265 : :
266 : 0 : Zle = ((Zlo+Zle)/(3*Zlo+Zle))*Zle; //Pozar - Microwave engineering: eq 7.79a
267 : 0 : Zlo = ((Zlo+Zle)/(3*Zle+Zlo))*Zlo; //Pozar - Microwave engineering: eq 7.79b
268 : :
269 : 0 : }
270 : :
271 : : /* The function computes the dispersion effects on the dielectric
272 : : constants and characteristic impedances for the even and odd mode
273 : : of parallel coupled microstrip lines. */
274 : 0 : void mslange::analyseDispersion (nr_double_t W, nr_double_t h, nr_double_t s,
275 : : nr_double_t er, nr_double_t Zle,
276 : : nr_double_t Zlo, nr_double_t ErEffe,
277 : : nr_double_t ErEffo, nr_double_t frequency,
278 : : const char * const DModel, nr_double_t& ZleFreq,
279 : : nr_double_t& ZloFreq,
280 : : nr_double_t& ErEffeFreq,
281 : : nr_double_t& ErEffoFreq) {
282 : :
283 : :
284 : : // initialize default return values
285 : 0 : ZleFreq = Zle;
286 : 0 : ErEffeFreq = ErEffe;
287 : 0 : ZloFreq = Zlo;
288 : 0 : ErEffoFreq = ErEffo;
289 : :
290 : : // normalized width and gap
291 : 0 : nr_double_t u = W / h;
292 : 0 : nr_double_t g = s / h;
293 : :
294 : : // GETSINGER
295 [ # # ]: 0 : if (!strcmp (DModel, "Getsinger")) {
296 : : // even mode dispersion
297 : : msline::Getsinger_disp (h, er, ErEffe, Zle / 2,
298 : 0 : frequency, ErEffeFreq, ZleFreq);
299 : 0 : ZleFreq *= 2;
300 : : // odd mode dispersion
301 : : msline::Getsinger_disp (h, er, ErEffo, Zlo * 2,
302 : 0 : frequency, ErEffoFreq, ZloFreq);
303 : 0 : ZloFreq /= 2;
304 : : }
305 : : // KIRSCHNING and JANSEN
306 [ # # ]: 0 : else if (!strcmp (DModel, "Kirschning")) {
307 : : nr_double_t p1, p2, p3, p4, p5, p6, p7, Fe;
308 : 0 : nr_double_t fn = frequency * h * 1e-6;
309 : :
310 : : // even relative dielectric constant dispersion
311 [ # # ]: 0 : p1 = 0.27488 * (0.6315 + 0.525 / qucs::pow (1 + 0.0157 * fn, 20.)) * u -
312 [ # # ]: 0 : 0.065683 * qucs::exp (-8.7513 * u);
313 [ # # ]: 0 : p2 = 0.33622 * (1 - qucs::exp (-0.03442 * er));
314 [ # # ][ # # ]: 0 : p3 = 0.0363 * qucs::exp (-4.6 * u) * (1 - qucs::exp (- qucs::pow (fn / 38.7, 4.97)));
[ # # ]
315 [ # # ][ # # ]: 0 : p4 = 1 + 2.751 * (1 - qucs::exp (- qucs::pow (er / 15.916, 8.)));
316 [ # # ]: 0 : p5 = 0.334 * qucs::exp (-3.3 * cubic (er / 15)) + 0.746;
317 [ # # ][ # # ]: 0 : p6 = p5 * qucs::exp (- qucs::pow (fn / 18, 0.368));
318 [ # # ]: 0 : p7 = 1 + 4.069 * p6 * qucs::pow (g, 0.479) *
319 [ # # ][ # # ]: 0 : qucs::exp (-1.347 * qucs::pow (g, 0.595) - 0.17 * qucs::pow (g, 2.5));
[ # # ]
320 [ # # ]: 0 : Fe = p1 * p2 * qucs::pow ((p3 * p4 + 0.1844 * p7) * fn, 1.5763);
321 : 0 : ErEffeFreq = er - (er - ErEffe) / (1 + Fe);
322 : :
323 : : // odd relative dielectric constant dispersion
324 : : nr_double_t p8, p9, p10, p11, p12, p13, p14, p15, Fo;
325 : 0 : p8 = 0.7168 * (1 + 1.076 / (1 + 0.0576 * (er - 1)));
326 [ # # ][ # # ]: 0 : p9 = p8 - 0.7913 * (1 - qucs::exp (- qucs::pow (fn / 20, 1.424))) *
327 [ # # ][ # # ]: 0 : qucs::atan (2.481 * qucs::pow (er / 8, 0.946));
328 [ # # ]: 0 : p10 = 0.242 * qucs::pow (er - 1, 0.55);
329 [ # # ]: 0 : p11 = 0.6366 * (qucs::exp (-0.3401 * fn) - 1) *
330 [ # # ][ # # ]: 0 : qucs::atan (1.263 * qucs::pow (u / 3, 1.629));
331 [ # # ]: 0 : p12 = p9 + (1 - p9) / (1 + 1.183 * qucs::pow (u, 1.376));
332 : 0 : p13 = 1.695 * p10 / (0.414 + 1.605 * p10);
333 [ # # ][ # # ]: 0 : p14 = 0.8928 + 0.1072 * (1 - qucs::exp (-0.42 * qucs::pow (fn / 20, 3.215)));
334 : : p15 = fabs (1 - 0.8928 * (1 + p11) *
335 [ # # ][ # # ]: 0 : qucs::exp (-p13 * qucs::pow (g, 1.092)) * p12 / p14);
336 [ # # ]: 0 : Fo = p1 * p2 * qucs::pow ((p3 * p4 + 0.1844) * fn * p15, 1.5763);
337 : 0 : ErEffoFreq = er - (er - ErEffo) / (1 + Fo);
338 : :
339 : : // dispersion of even characteristic impedance
340 : : nr_double_t t, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21;
341 : 0 : q11 = 0.893 * (1 - 0.3 / (1 + 0.7 * (er - 1)));
342 [ # # ]: 0 : t = qucs::pow (fn / 20, 4.91);
343 [ # # ][ # # ]: 0 : q12 = 2.121 * t / (1 + q11 * t) * qucs::exp (-2.87 * g) * qucs::pow (g, 0.902);
344 [ # # ]: 0 : q13 = 1 + 0.038 * qucs::pow (er / 8, 5.1);
345 [ # # ]: 0 : t = quadr (er / 15);
346 : 0 : q14 = 1 + 1.203 * t / (1 + t);
347 [ # # ][ # # ]: 0 : q15 = 1.887 * qucs::exp (-1.5 * qucs::pow (g, 0.84)) * qucs::pow (g, q14) /
[ # # ]
348 [ # # ]: 0 : (1 + 0.41 * qucs::pow (fn / 15, 3.) *
349 [ # # ][ # # ]: 0 : qucs::pow (u, 2 / q13) / (0.125 + qucs::pow (u, 1.626 / q13)));
350 [ # # ]: 0 : q16 = q15 * (1 + 9 / (1 + 0.403 * sqr (er - 1)));
351 [ # # ][ # # ]: 0 : q17 = 0.394 * (1 - qucs::exp (-1.47 * qucs::pow (u / 7, 0.672))) *
352 [ # # ][ # # ]: 0 : (1 - qucs::exp (-4.25 * qucs::pow (fn / 20, 1.87)));
353 [ # # ][ # # ]: 0 : q18 = 0.61 * (1 - qucs::exp (-2.31 * qucs::pow (u / 8, 1.593))) /
354 [ # # ]: 0 : (1 + 6.544 * qucs::pow (g, 4.17));
355 [ # # ][ # # ]: 0 : q19 = 0.21 * quadr (g) / (1 + 0.18 * qucs::pow (g, 4.9)) / (1 + 0.1 * sqr (u)) /
[ # # ]
356 [ # # ]: 0 : (1 + qucs::pow (fn / 24, 3.));
357 [ # # ]: 0 : q20 = q19 * (0.09 + 1 / (1 + 0.1 * qucs::pow (er - 1, 2.7)));
358 [ # # ]: 0 : t = qucs::pow (u, 2.5);
359 [ # # ][ # # ]: 0 : q21 = fabs (1 - 42.54 * qucs::pow (g, 0.133) * qucs::exp (-0.812 * g) * t /
360 : 0 : (1 + 0.033 * t));
361 : :
362 : : nr_double_t re, qe, pe, de, Ce, q0, ZlFreq, ErEffFreq;
363 [ # # ]: 0 : msline::Kirschning_er (u, fn, er, ErEffe, ErEffFreq);
364 [ # # ]: 0 : msline::Kirschning_zl (u, fn, er, ErEffe, ErEffFreq, Zle, q0, ZlFreq);
365 [ # # ]: 0 : re = qucs::pow (fn / 28.843, 12.);
366 [ # # ]: 0 : qe = 0.016 + qucs::pow (0.0514 * er * q21, 4.524);
367 [ # # ][ # # ]: 0 : pe = 4.766 * qucs::exp (-3.228 * qucs::pow (u, 0.641));
368 [ # # ]: 0 : t = qucs::pow (er - 1, 6.);
369 : : de = 5.086 * qe * re / (0.3838 + 0.386 * qe) *
370 [ # # ][ # # ]: 0 : qucs::exp (-22.2 * qucs::pow (u, 1.92)) / (1 + 1.2992 * re) * t / (1 + 10 * t);
371 [ # # ]: 0 : Ce = 1 + 1.275 * (1 - qucs::exp (-0.004625 * pe * qucs::pow (er, 1.674) *
372 [ # # ][ # # ]: 0 : qucs::pow (fn / 18.365, 2.745))) - q12 + q16 - q17 + q18 + q20;
373 [ # # ]: 0 : ZleFreq = Zle * qucs::pow ((0.9408 * qucs::pow (ErEffFreq, Ce) - 0.9603) /
374 [ # # ][ # # ]: 0 : ((0.9408 - de) * qucs::pow (ErEffe, Ce) - 0.9603), q0);
375 : :
376 : : // dispersion of odd characteristic impedance
377 : : nr_double_t q22, q23, q24, q25, q26, q27, q28, q29;
378 [ # # ]: 0 : msline::Kirschning_er (u, fn, er, ErEffo, ErEffFreq);
379 [ # # ]: 0 : msline::Kirschning_zl (u, fn, er, ErEffo, ErEffFreq, Zlo, q0, ZlFreq);
380 [ # # ]: 0 : q29 = 15.16 / (1 + 0.196 * sqr (er - 1));
381 [ # # ]: 0 : t = sqr (er - 1);
382 [ # # ][ # # ]: 0 : q25 = 0.3 * sqr (fn) / (10 + sqr (fn)) * (1 + 2.333 * t / (5 + t));
383 [ # # ]: 0 : t = qucs::pow ((er - 1) / 13, 12.);
384 : 0 : q26 = 30 - 22.2 * t / (1 + 3 * t) - q29;
385 [ # # ]: 0 : t = qucs::pow (er - 1, 1.5);
386 [ # # ]: 0 : q27 = 0.4 * qucs::pow (g, 0.84) * (1 + 2.5 * t / (5 + t));
387 [ # # ]: 0 : t = qucs::pow (er - 1, 3.);
388 : 0 : q28 = 0.149 * t / (94.5 + 0.038 * t);
389 [ # # ][ # # ]: 0 : q22 = 0.925 * qucs::pow (fn / q26, 1.536) / (1 + 0.3 * qucs::pow (fn / 30, 1.536));
390 [ # # ]: 0 : q23 = 1 + 0.005 * fn * q27 / (1 + 0.812 * qucs::pow (fn / 15, 1.9)) /
391 [ # # ]: 0 : (1 + 0.025 * sqr (u));
392 [ # # ]: 0 : t = qucs::pow (u, 0.894);
393 : : q24 = 2.506 * q28 * t / (3.575 + t) *
394 [ # # ]: 0 : qucs::pow ((1 + 1.3 * u) * fn / 99.25, 4.29);
395 [ # # ]: 0 : ZloFreq = ZlFreq + (Zlo * qucs::pow (ErEffoFreq / ErEffo, q22) - ZlFreq * q23) /
396 [ # # ]: 0 : (1 + q24 + qucs::pow (0.46 * g, 2.2) * q25);
397 : :
398 : : }
399 : 0 : }
400 : :
401 : 0 : void mslange::initDC (void) {
402 : 0 : nr_double_t l = getPropertyDouble ("L");
403 : 0 : nr_double_t W = getPropertyDouble ("W")/2;
404 : 0 : substrate * subst = getSubstrate ();
405 : 0 : nr_double_t t = subst->getPropertyDouble ("t");
406 : 0 : nr_double_t rho = subst->getPropertyDouble ("rho");
407 : :
408 [ # # ][ # # ]: 0 : if (t != 0.0 && rho != 0.0) {
409 : : // tiny resistances
410 : 0 : nr_double_t g = t * W / rho / l;
411 : 0 : setVoltageSources (0);
412 : 0 : allocMatrixMNA ();
413 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_1, +g); setY (NODE_2, NODE_2, +g);
414 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_2, -g); setY (NODE_2, NODE_1, -g);
415 [ # # ][ # # ]: 0 : setY (NODE_3, NODE_3, +g); setY (NODE_4, NODE_4, +g);
416 [ # # ][ # # ]: 0 : setY (NODE_3, NODE_4, -g); setY (NODE_4, NODE_3, -g);
417 : : }
418 : : else {
419 : : // DC shorts (voltage sources V = 0 volts)
420 : 0 : setVoltageSources (2);
421 : 0 : setInternalVoltageSource (1);
422 : 0 : allocMatrixMNA ();
423 : 0 : clearY ();
424 : 0 : voltageSource (VSRC_1, NODE_1, NODE_2);
425 : 0 : voltageSource (VSRC_2, NODE_3, NODE_4);
426 [ # # ][ # # ]: 0 : setD (VSRC_1, VSRC_2, 0.0); setD (VSRC_2, VSRC_1, 0.0);
427 : : }
428 : 0 : }
429 : :
430 : 0 : void mslange::initAC (void) {
431 : 0 : setVoltageSources (0);
432 : 0 : allocMatrixMNA ();
433 : 0 : }
434 : :
435 : 0 : void mslange::calcAC (nr_double_t frequency) {
436 : : // fetch line properties
437 [ # # ]: 0 : nr_double_t l = getPropertyDouble ("L");
438 : :
439 : : // compute propagation constants for even and odd mode
440 [ # # ]: 0 : calcPropagation (frequency);
441 : 0 : nr_complex_t ge = nr_complex_t (ae, be);
442 : 0 : nr_complex_t go = nr_complex_t (ao, bo);
443 : :
444 : : // compute abbreviations
445 : 0 : nr_complex_t De, Do, y1, y2, y3, y4;
446 [ # # ][ # # ]: 0 : De = 0.5 / (ze * qucs::sinh (ge * l));
447 [ # # ][ # # ]: 0 : Do = 0.5 / (zo * qucs::sinh (go * l));
448 [ # # ]: 0 : y2 = -De - Do;
449 [ # # ]: 0 : y3 = -De + Do;
450 [ # # ]: 0 : De *= cosh (ge * l);
451 [ # # ]: 0 : Do *= cosh (go * l);
452 [ # # ]: 0 : y1 = De + Do;
453 [ # # ]: 0 : y4 = De - Do;
454 : :
455 : : // store Y-parameters
456 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_1, y1); setY (NODE_2, NODE_2, y1);
457 [ # # ][ # # ]: 0 : setY (NODE_3, NODE_3, y1); setY (NODE_4, NODE_4, y1);
458 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_2, y2); setY (NODE_2, NODE_1, y2);
459 [ # # ][ # # ]: 0 : setY (NODE_3, NODE_4, y2); setY (NODE_4, NODE_3, y2);
460 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_3, y3); setY (NODE_2, NODE_4, y3);
461 [ # # ][ # # ]: 0 : setY (NODE_3, NODE_1, y3); setY (NODE_4, NODE_2, y3);
462 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_4, y4); setY (NODE_2, NODE_3, y4);
463 [ # # ][ # # ]: 0 : setY (NODE_3, NODE_2, y4); setY (NODE_4, NODE_1, y4);
464 : 0 : }
465 : :
466 : 0 : void mslange::calcNoiseAC (nr_double_t) {
467 : : // calculate noise using Bosma's theorem
468 : 0 : nr_double_t T = getPropertyDouble ("Temp");
469 [ # # ][ # # ]: 0 : setMatrixN (4 * kelvin (T) / T0 * real (getMatrixY ()));
[ # # ][ # # ]
[ # # ]
470 : 0 : }
471 : :
472 : : // properties
473 : : PROP_REQ [] = {
474 : : { "W", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
475 : : { "L", PROP_REAL, { 10e-3, PROP_NO_STR }, PROP_POS_RANGE },
476 : : { "S", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
477 : : { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
478 : : { "Model", PROP_STR, { PROP_NO_VAL, "Kirschning" },
479 : : PROP_RNG_STR2 ("Kirschning", "Hammerstad") },
480 : : { "DispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" },
481 : : PROP_RNG_STR2 ("Kirschning", "Getsinger") },
482 : : PROP_NO_PROP };
483 : : PROP_OPT [] = {
484 : : { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
485 : : PROP_NO_PROP };
486 : : struct define_t mslange::cirdef =
487 : : { "MLANGE", 4, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
|