Qucs-core  0.0.19
mslange.cpp
Go to the documentation of this file.
00001 /*
00002  * mslange.cpp - parallel coupled microstrip lines class implementation
00003  *
00004  * Copyright (C) 2004, 2005, 2006, 2008 Stefan Jahn <stefan@lkcc.org>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  * $Id: mslange.cpp,v 1.25 2008/10/07 20:15:33 ela Exp $
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include "component.h"
00030 #include "substrate.h"
00031 #include "msline.h"
00032 #include "mslange.h"
00033 
00034 using namespace qucs;
00035 
00036 mslange::mslange () : circuit (4) {
00037   type = CIR_MSLANGE;
00038 }
00039 
00040 void mslange::calcPropagation (nr_double_t frequency) {
00041 
00042   // fetch line properties
00043   nr_double_t W = getPropertyDouble ("W");
00044   nr_double_t s = getPropertyDouble ("S");
00045   const char * const SModel = getPropertyString ("Model");
00046   const char * const DModel = getPropertyString ("DispModel");
00047 
00048   // fetch substrate properties
00049   substrate * subst = getSubstrate ();
00050   nr_double_t er    = subst->getPropertyDouble ("er");
00051   nr_double_t h     = subst->getPropertyDouble ("h");
00052   nr_double_t t     = subst->getPropertyDouble ("t");
00053   nr_double_t tand  = subst->getPropertyDouble ("tand");
00054   nr_double_t rho   = subst->getPropertyDouble ("rho");
00055   nr_double_t D     = subst->getPropertyDouble ("D");
00056 
00057   // quasi-static analysis
00058   nr_double_t Zle, ErEffe, Zlo, ErEffo;
00059   analysQuasiStatic (W, h, s, t, er, SModel, Zle, Zlo, ErEffe, ErEffo);
00060 
00061   // analyse dispersion of Zl and Er
00062   nr_double_t ZleFreq, ErEffeFreq, ZloFreq, ErEffoFreq;
00063   analyseDispersion (W, h, s, er, Zle, Zlo, ErEffe, ErEffo, frequency, DModel,
00064                      ZleFreq, ZloFreq, ErEffeFreq, ErEffoFreq);
00065 
00066   // analyse losses of line
00067   nr_double_t ace, aco, ade, ado;
00068   msline::analyseLoss (W, t, er, rho, D, tand, Zle, Zlo, ErEffe,
00069                        frequency, "Hammerstad", ace, ade);
00070   msline::analyseLoss (W, t, er, rho, D, tand, Zlo, Zle, ErEffo,
00071                        frequency, "Hammerstad", aco, ado);
00072 
00073   // compute propagation constants for even and odd mode
00074   nr_double_t k0 = 2 * pi * frequency / C0;
00075   ae = ace + ade;
00076   ao = aco + ado;
00077   be = qucs::sqrt (ErEffeFreq) * k0;
00078   bo = qucs::sqrt (ErEffoFreq) * k0;
00079   ze = ZleFreq;
00080   zo = ZloFreq;
00081   ee = ErEffeFreq;
00082   eo = ErEffoFreq;
00083 }
00084 
00085 void mslange::saveCharacteristics (nr_double_t) {
00086   setCharacteristic ("ZlEven", ze);
00087   setCharacteristic ("ErEven", ee);
00088   setCharacteristic ("ZlOdd", zo);
00089   setCharacteristic ("ErOdd", eo);
00090 }
00091 
00092 void mslange::calcSP (nr_double_t frequency) {
00093   // fetch line properties
00094   nr_double_t l = getPropertyDouble ("L");
00095 
00096   // compute propagation constants for even and odd mode
00097   calcPropagation (frequency);
00098   nr_complex_t ge = nr_complex_t (ae, be);
00099   nr_complex_t go = nr_complex_t (ao, bo);
00100 
00101   // compute abbreviations
00102   nr_complex_t Ee, Eo, De, Do, Xe, Xo, Ye, Yo;
00103   Ee = (sqr (ze) + sqr (z0)) * qucs::sinh (ge * l);
00104   Eo = (sqr (zo) + sqr (z0)) * qucs::sinh (go * l);
00105   De = 2 * ze * z0 * cosh (ge * l) + Ee;
00106   Do = 2 * zo * z0 * cosh (go * l) + Eo;
00107   Xe = (sqr (ze) - sqr (z0)) * qucs::sinh (ge * l) / 2.0 / De;
00108   Xo = (sqr (zo) - sqr (z0)) * qucs::sinh (go * l) / 2.0 / Do;
00109   Ye = ze * z0 / De;
00110   Yo = zo * z0 / Do;
00111 
00112   // reflexion coefficients
00113   setS (NODE_1, NODE_1, Xe + Xo); setS (NODE_2, NODE_2, Xe + Xo);
00114   setS (NODE_3, NODE_3, Xe + Xo); setS (NODE_4, NODE_4, Xe + Xo);
00115   // through paths
00116   setS (NODE_1, NODE_2, Ye + Yo); setS (NODE_2, NODE_1, Ye + Yo);
00117   setS (NODE_3, NODE_4, Ye + Yo); setS (NODE_4, NODE_3, Ye + Yo);
00118   // coupled paths
00119   setS (NODE_1, NODE_4, Xe - Xo); setS (NODE_4, NODE_1, Xe - Xo);
00120   setS (NODE_2, NODE_3, Xe - Xo); setS (NODE_3, NODE_2, Xe - Xo);
00121   // isolated paths
00122   setS (NODE_1, NODE_3, Ye - Yo); setS (NODE_3, NODE_1, Ye - Yo);
00123   setS (NODE_2, NODE_4, Ye - Yo); setS (NODE_4, NODE_2, Ye - Yo);
00124 }
00125 
00126 void mslange::calcNoiseSP (nr_double_t) {
00127   // calculate noise using Bosma's theorem
00128   nr_double_t T = getPropertyDouble ("Temp");
00129   matrix s = getMatrixS ();
00130   matrix e = eye (getSize ());
00131   setMatrixN (celsius2kelvin (T) / T0 * (e - s * transpose (conj (s))));
00132 }
00133 
00134 /* The function calculates the quasi-static dielectric constants and
00135    characteristic impedances for the even and odd mode based upon the
00136    given line and substrate properties for parallel coupled microstrip
00137    lines. */
00138 void mslange::analysQuasiStatic (nr_double_t W, nr_double_t h, nr_double_t s,
00139                                    nr_double_t t, nr_double_t er,
00140                                    const char * const SModel, nr_double_t& Zle,
00141                                    nr_double_t& Zlo, nr_double_t& ErEffe,
00142                                    nr_double_t& ErEffo) {
00143   // initialize default return values
00144   ErEffe = ErEffo = er;
00145   Zlo = 42.2; Zle = 55.7;
00146 
00147   // normalized width and gap
00148   nr_double_t u = W / h;
00149   nr_double_t g = s / h;
00150 
00151   // HAMMERSTAD and JENSEN
00152   if (!strcmp (SModel, "Hammerstad")) {
00153     nr_double_t Zl1, Fe, Fo, a, b, fo, Mu, Alpha, Beta, ErEff;
00154     nr_double_t Pe, Po, r, fo1, q, p, n, Psi, Phi, m, Theta;
00155 
00156     // modifying equations for even mode
00157     m = 0.2175 + qucs::pow (4.113 + qucs::pow (20.36 / g, 6.), -0.251) +
00158       qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 13.8, 10.))) / 323;
00159     Alpha = 0.5 * qucs::exp (-g);
00160     Psi = 1 + g / 1.45 + qucs::pow (g, 2.09) / 3.95;
00161     Phi = 0.8645 * qucs::pow (u, 0.172);
00162     Pe = Phi / (Psi * (Alpha * qucs::pow (u, m) + (1 - Alpha) * qucs::pow (u, -m)));
00163     // TODO: is this ... Psi * (Alpha ... or ... Psi / (Alpha ... ?
00164 
00165     // modifying equations for odd mode
00166     n = (1 / 17.7 + qucs::exp (-6.424 - 0.76 * qucs::log (g) - qucs::pow (g / 0.23, 5.))) *
00167       qucs::log ((10 + 68.3 * sqr (g)) / (1 + 32.5 * qucs::pow (g, 3.093)));
00168     Beta = 0.2306 + qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 3.73, 10.))) / 301.8 +
00169       qucs::log (1 + 0.646 * qucs::pow (g, 1.175)) / 5.3;
00170     Theta = 1.729 + 1.175 * qucs::log (1 + 0.627 / (g + 0.327 * qucs::pow (g, 2.17)));
00171     Po = Pe - Theta / Psi * qucs::exp (Beta * qucs::pow (u, -n) * qucs::log (u));
00172 
00173     // further modifying equations
00174     r = 1 + 0.15 * (1 - qucs::exp (1 - sqr (er - 1) / 8.2) / (1 + qucs::pow (g, -6.)));
00175     fo1 = 1 - qucs::exp (-0.179 * qucs::pow (g, 0.15) -
00176                    0.328 * qucs::pow (g, r) / qucs::log (euler + qucs::pow (g / 7, 2.8)));
00177     q = qucs::exp (-1.366 - g);
00178     p = qucs::exp (-0.745 * qucs::pow (g, 0.295)) / qucs::cosh (qucs::pow (g, 0.68));
00179     fo = fo1 * qucs::exp (p * qucs::log (u) + q * qucs::sin (pi * qucs::log10 (u)));
00180 
00181     Mu = g * qucs::exp (-g) + u * (20 + sqr (g)) / (10 + sqr (g));
00182     msline::Hammerstad_ab (Mu, er, a, b);
00183     Fe = qucs::pow (1 + 10 / Mu, -a * b);
00184     msline::Hammerstad_ab (u, er, a, b);
00185     Fo = fo * qucs::pow (1 + 10 / u, -a * b);
00186 
00187     // finally compute effective dielectric constants and impedances
00188     ErEffe = (er + 1) / 2 + (er - 1) / 2 * Fe;
00189     ErEffo = (er + 1) / 2 + (er - 1) / 2 * Fo;
00190 
00191     msline::Hammerstad_er (u, er, a, b, ErEff);  // single microstrip
00192 
00193     // first variant
00194     Zl1 = Z0 / (u + 1.98 * qucs::pow (u, 0.172));
00195     Zl1 /= qucs::sqrt (ErEff);
00196 
00197     // second variant
00198     msline::Hammerstad_zl (u, Zl1);
00199     Zl1 /= qucs::sqrt (ErEff);
00200 
00201     Zle = Zl1 / (1 - Zl1 * Pe / Z0);
00202     Zlo = Zl1 / (1 - Zl1 * Po / Z0);
00203   }
00204   // KIRSCHNING and JANSEN
00205   else if (!strcmp (SModel, "Kirschning")) {
00206     nr_double_t a, b, ae, be, ao, bo, v, co, d, ErEff, Zl1;
00207     nr_double_t q1, q2, q3, q4, q5, q6, q7, q8, q9, q10;
00208 
00209     // consider effect of finite strip thickness (JANSEN only)
00210     nr_double_t ue = u;
00211     nr_double_t uo = u;
00212     if (t != 0 && s > 10 * (2 * t)) {
00213       nr_double_t dW = 0;
00214       // SCHNEIDER, referred by JANSEN
00215       if (u >= one_over_pi / 2 && one_over_pi / 2 > 2 * t / h)
00216         dW = t * (1 + qucs::log (2 * h / t)) / pi;
00217       else if (W > 2 * t)
00218         dW = t * (1 + qucs::log (4 * pi * W / t)) / pi;
00219       // JANSEN
00220       nr_double_t dt = 2 * t * h / s / er;
00221       nr_double_t We = W + dW * (1 - 0.5 * qucs::exp (-0.69 * dW / dt));
00222       nr_double_t Wo = We + dt;
00223       ue = We / h;
00224       uo = Wo / h;
00225     }
00226 
00227     // even relative dielectric constant
00228     v = ue * (20 + sqr (g)) / (10 + sqr (g)) + g * qucs::exp (-g);
00229     msline::Hammerstad_ab (v, er, ae, be);
00230     msline::Hammerstad_er (v, er, ae, be, ErEffe);
00231 
00232     // odd relative dielectric constant
00233     msline::Hammerstad_ab (uo, er, a, b);
00234     msline::Hammerstad_er (uo, er, a, b, ErEff);
00235     d = 0.593 + 0.694 * qucs::exp (-0.562 * uo);
00236     bo = 0.747 * er / (0.15 + er);
00237     co = bo - (bo - 0.207) * qucs::exp (-0.414 * uo);
00238     ao = 0.7287 * (ErEff - (er + 1) / 2) * (1 - qucs::exp (-0.179 * uo));
00239     ErEffo = ((er + 1) / 2 + ao - ErEff) * qucs::exp (-co * qucs::pow (g, d)) + ErEff;
00240 
00241     // characteristic impedance of single line
00242     msline::Hammerstad_zl (u, Zl1);
00243     Zl1 /= qucs::sqrt (ErEff);
00244 
00245     // even characteristic impedance
00246     q1 = 0.8695 * qucs::pow (ue, 0.194);
00247     q2 = 1 + 0.7519 * g + 0.189 * qucs::pow (g, 2.31);
00248     q3 = 0.1975 + qucs::pow (16.6 + qucs::pow (8.4 / g, 6.), -0.387) +
00249       qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 3.4, 10.))) / 241;
00250     q4 = q1 / q2 * 2 /
00251       (qucs::exp (-g) * qucs::pow (ue, q3) + (2 - qucs::exp (-g)) * qucs::pow (ue, -q3));
00252     Zle = qucs::sqrt (ErEff / ErEffe) * Zl1 / (1 - Zl1 * qucs::sqrt (ErEff) * q4 / Z0);
00253 
00254     // odd characteristic impedance
00255     q5 = 1.794 + 1.14 * qucs::log (1 + 0.638 / (g + 0.517 * qucs::pow (g, 2.43)));
00256     q6 = 0.2305 + qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 5.8, 10.))) / 281.3 +
00257       qucs::log (1 + 0.598 * qucs::pow (g, 1.154)) / 5.1;
00258     q7 = (10 + 190 * sqr (g)) / (1 + 82.3 * cubic (g));
00259     q8 = qucs::exp (-6.5 - 0.95 * qucs::log (g) - qucs::pow (g / 0.15, 5.));
00260     q9 = qucs::log (q7) * (q8 + 1 / 16.5);
00261     q10 = (q2 * q4 - q5 * qucs::exp (qucs::log (uo) * q6 * qucs::pow (uo, -q9))) / q2;
00262     Zlo = qucs::sqrt (ErEff / ErEffo) * Zl1 / (1 - Zl1 * qucs::sqrt (ErEff) * q10 / Z0);
00263   }
00264 //  nr_double_t Zle4, Zlo4, C, Z04;
00265 
00266   Zle = ((Zlo+Zle)/(3*Zlo+Zle))*Zle;    //Pozar - Microwave engineering: eq 7.79a
00267   Zlo = ((Zlo+Zle)/(3*Zle+Zlo))*Zlo;    //Pozar - Microwave engineering: eq 7.79b
00268 
00269 }
00270 
00271 /* The function computes the dispersion effects on the dielectric
00272    constants and characteristic impedances for the even and odd mode
00273    of parallel coupled microstrip lines. */
00274 void mslange::analyseDispersion (nr_double_t W, nr_double_t h, nr_double_t s,
00275                                    nr_double_t er, nr_double_t Zle,
00276                                    nr_double_t Zlo, nr_double_t ErEffe,
00277                                    nr_double_t ErEffo, nr_double_t frequency,
00278                                    const char * const DModel, nr_double_t& ZleFreq,
00279                                    nr_double_t& ZloFreq,
00280                                    nr_double_t& ErEffeFreq,
00281                                    nr_double_t& ErEffoFreq) {
00282 
00283 
00284   // initialize default return values
00285   ZleFreq = Zle;
00286   ErEffeFreq = ErEffe;
00287   ZloFreq = Zlo;
00288   ErEffoFreq = ErEffo;
00289 
00290   // normalized width and gap
00291   nr_double_t u = W / h;
00292   nr_double_t g = s / h;
00293 
00294   // GETSINGER
00295   if (!strcmp (DModel, "Getsinger")) {
00296     // even mode dispersion
00297     msline::Getsinger_disp (h, er, ErEffe, Zle / 2,
00298                             frequency, ErEffeFreq, ZleFreq);
00299     ZleFreq *= 2;
00300     // odd mode dispersion
00301     msline::Getsinger_disp (h, er, ErEffo, Zlo * 2,
00302                             frequency, ErEffoFreq, ZloFreq);
00303     ZloFreq /= 2;
00304   }
00305   // KIRSCHNING and JANSEN
00306   else if (!strcmp (DModel, "Kirschning")) {
00307     nr_double_t p1, p2, p3, p4, p5, p6, p7, Fe;
00308     nr_double_t fn = frequency * h * 1e-6;
00309 
00310     // even relative dielectric constant dispersion
00311     p1 = 0.27488 * (0.6315 + 0.525 / qucs::pow (1 + 0.0157 * fn, 20.)) * u -
00312       0.065683 * qucs::exp (-8.7513 * u);
00313     p2 = 0.33622 * (1 - qucs::exp (-0.03442 * er));
00314     p3 = 0.0363 * qucs::exp (-4.6 * u) * (1 - qucs::exp (- qucs::pow (fn / 38.7, 4.97)));
00315     p4 = 1 + 2.751 * (1 - qucs::exp (- qucs::pow (er / 15.916, 8.)));
00316     p5 = 0.334 * qucs::exp (-3.3 * cubic (er / 15)) + 0.746;
00317     p6 = p5 * qucs::exp (- qucs::pow (fn / 18, 0.368));
00318     p7 = 1 + 4.069 * p6 * qucs::pow (g, 0.479) *
00319       qucs::exp (-1.347 * qucs::pow (g, 0.595) - 0.17 * qucs::pow (g, 2.5));
00320     Fe = p1 * p2 * qucs::pow ((p3 * p4 + 0.1844 * p7) * fn, 1.5763);
00321     ErEffeFreq = er - (er - ErEffe) / (1 + Fe);
00322 
00323     // odd relative dielectric constant dispersion
00324     nr_double_t p8, p9, p10, p11, p12, p13, p14, p15, Fo;
00325     p8 = 0.7168 * (1 + 1.076 / (1 + 0.0576 * (er - 1)));
00326     p9 = p8 - 0.7913 * (1 - qucs::exp (- qucs::pow (fn / 20, 1.424))) *
00327       qucs::atan (2.481 * qucs::pow (er / 8, 0.946));
00328     p10 = 0.242 * qucs::pow (er - 1, 0.55);
00329     p11 = 0.6366 * (qucs::exp (-0.3401 * fn) - 1) *
00330       qucs::atan (1.263 * qucs::pow (u / 3, 1.629));
00331     p12 = p9 + (1 - p9) / (1 + 1.183 * qucs::pow (u, 1.376));
00332     p13 = 1.695 * p10 / (0.414 + 1.605 * p10);
00333     p14 = 0.8928 + 0.1072 * (1 - qucs::exp (-0.42 * qucs::pow (fn / 20, 3.215)));
00334     p15 = fabs (1 - 0.8928 * (1 + p11) *
00335                 qucs::exp (-p13 * qucs::pow (g, 1.092)) * p12 / p14);
00336     Fo = p1 * p2 * qucs::pow ((p3 * p4 + 0.1844) * fn * p15, 1.5763);
00337     ErEffoFreq = er - (er - ErEffo) / (1 + Fo);
00338 
00339     // dispersion of even characteristic impedance
00340     nr_double_t t, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21;
00341     q11 = 0.893 * (1 - 0.3 / (1 + 0.7 * (er - 1)));
00342     t = qucs::pow (fn / 20, 4.91);
00343     q12 = 2.121 * t / (1 + q11 * t) * qucs::exp (-2.87 * g) * qucs::pow (g, 0.902);
00344     q13 = 1 + 0.038 * qucs::pow (er / 8, 5.1);
00345     t = quadr (er / 15);
00346     q14 = 1 + 1.203 * t / (1 + t);
00347     q15 = 1.887 * qucs::exp (-1.5 * qucs::pow (g, 0.84)) * qucs::pow (g, q14) /
00348       (1 + 0.41 * qucs::pow (fn / 15, 3.) *
00349        qucs::pow (u, 2 / q13) / (0.125 + qucs::pow (u, 1.626 / q13)));
00350     q16 = q15 * (1 + 9 / (1 + 0.403 * sqr (er - 1)));
00351     q17 = 0.394 * (1 - qucs::exp (-1.47 * qucs::pow (u / 7, 0.672))) *
00352       (1 - qucs::exp (-4.25 * qucs::pow (fn / 20, 1.87)));
00353     q18 = 0.61 * (1 - qucs::exp (-2.31 * qucs::pow (u / 8, 1.593))) /
00354       (1 + 6.544 * qucs::pow (g, 4.17));
00355     q19 = 0.21 * quadr (g) / (1 + 0.18 * qucs::pow (g, 4.9)) / (1 + 0.1 * sqr (u)) /
00356       (1 + qucs::pow (fn / 24, 3.));
00357     q20 = q19 * (0.09 + 1 / (1 + 0.1 * qucs::pow (er - 1, 2.7)));
00358     t = qucs::pow (u, 2.5);
00359     q21 = fabs (1 - 42.54 * qucs::pow (g, 0.133) * qucs::exp (-0.812 * g) * t /
00360                 (1 + 0.033 * t));
00361 
00362     nr_double_t re, qe, pe, de, Ce, q0, ZlFreq, ErEffFreq;
00363     msline::Kirschning_er (u, fn, er, ErEffe, ErEffFreq);
00364     msline::Kirschning_zl (u, fn, er, ErEffe, ErEffFreq, Zle, q0, ZlFreq);
00365     re = qucs::pow (fn / 28.843, 12.);
00366     qe = 0.016 + qucs::pow (0.0514 * er * q21, 4.524);
00367     pe = 4.766 * qucs::exp (-3.228 * qucs::pow (u, 0.641));
00368     t = qucs::pow (er - 1, 6.);
00369     de = 5.086 * qe * re / (0.3838 + 0.386 * qe) *
00370       qucs::exp (-22.2 * qucs::pow (u, 1.92)) / (1 + 1.2992 * re) * t / (1 + 10 * t);
00371     Ce = 1 + 1.275 * (1 - qucs::exp (-0.004625 * pe * qucs::pow (er, 1.674) *
00372          qucs::pow (fn / 18.365, 2.745))) - q12 + q16 - q17 + q18 + q20;
00373     ZleFreq = Zle * qucs::pow ((0.9408 * qucs::pow (ErEffFreq, Ce) - 0.9603) /
00374                          ((0.9408 - de) * qucs::pow (ErEffe, Ce) - 0.9603), q0);
00375 
00376     // dispersion of odd characteristic impedance
00377     nr_double_t q22, q23, q24, q25, q26, q27, q28, q29;
00378     msline::Kirschning_er (u, fn, er, ErEffo, ErEffFreq);
00379     msline::Kirschning_zl (u, fn, er, ErEffo, ErEffFreq, Zlo, q0, ZlFreq);
00380     q29 = 15.16 / (1 + 0.196 * sqr (er - 1));
00381     t = sqr (er - 1);
00382     q25 = 0.3 * sqr (fn) / (10 + sqr (fn)) * (1 + 2.333 * t / (5 + t));
00383     t = qucs::pow ((er - 1) / 13, 12.);
00384     q26 = 30 - 22.2 * t / (1 + 3 * t) - q29;
00385     t = qucs::pow (er - 1, 1.5);
00386     q27 = 0.4 * qucs::pow (g, 0.84) * (1 + 2.5 * t / (5 + t));
00387     t = qucs::pow (er - 1, 3.);
00388     q28 = 0.149 * t / (94.5 + 0.038 * t);
00389     q22 = 0.925 * qucs::pow (fn / q26, 1.536) / (1 + 0.3 * qucs::pow (fn / 30, 1.536));
00390     q23 = 1 + 0.005 * fn * q27 / (1 + 0.812 * qucs::pow (fn / 15, 1.9)) /
00391       (1 + 0.025 * sqr (u));
00392     t = qucs::pow (u, 0.894);
00393     q24 = 2.506 * q28 * t / (3.575 + t) *
00394       qucs::pow ((1 + 1.3 * u) * fn / 99.25, 4.29);
00395     ZloFreq = ZlFreq + (Zlo * qucs::pow (ErEffoFreq / ErEffo, q22) - ZlFreq * q23) /
00396       (1 + q24 + qucs::pow (0.46 * g, 2.2) * q25);
00397 
00398   }
00399 }
00400 
00401 void mslange::initDC (void) {
00402   nr_double_t l     = getPropertyDouble ("L");
00403   nr_double_t W     = getPropertyDouble ("W")/2;
00404   substrate * subst = getSubstrate ();
00405   nr_double_t t     = subst->getPropertyDouble ("t");
00406   nr_double_t rho   = subst->getPropertyDouble ("rho");
00407 
00408   if (t != 0.0 && rho != 0.0) {
00409     // tiny resistances
00410     nr_double_t g = t * W / rho / l;
00411     setVoltageSources (0);
00412     allocMatrixMNA ();
00413     setY (NODE_1, NODE_1, +g); setY (NODE_2, NODE_2, +g);
00414     setY (NODE_1, NODE_2, -g); setY (NODE_2, NODE_1, -g);
00415     setY (NODE_3, NODE_3, +g); setY (NODE_4, NODE_4, +g);
00416     setY (NODE_3, NODE_4, -g); setY (NODE_4, NODE_3, -g);
00417   }
00418   else {
00419     // DC shorts (voltage sources V = 0 volts)
00420     setVoltageSources (2);
00421     setInternalVoltageSource (1);
00422     allocMatrixMNA ();
00423     clearY ();
00424     voltageSource (VSRC_1, NODE_1, NODE_2);
00425     voltageSource (VSRC_2, NODE_3, NODE_4);
00426     setD (VSRC_1, VSRC_2, 0.0); setD (VSRC_2, VSRC_1, 0.0);
00427   }
00428 }
00429 
00430 void mslange::initAC (void) {
00431   setVoltageSources (0);
00432   allocMatrixMNA ();
00433 }
00434 
00435 void mslange::calcAC (nr_double_t frequency) {
00436   // fetch line properties
00437   nr_double_t l = getPropertyDouble ("L");
00438 
00439   // compute propagation constants for even and odd mode
00440   calcPropagation (frequency);
00441   nr_complex_t ge = nr_complex_t (ae, be);
00442   nr_complex_t go = nr_complex_t (ao, bo);
00443 
00444   // compute abbreviations
00445   nr_complex_t De, Do, y1, y2, y3, y4;
00446   De = 0.5 / (ze * qucs::sinh (ge * l));
00447   Do = 0.5 / (zo * qucs::sinh (go * l));
00448   y2 = -De - Do;
00449   y3 = -De + Do;
00450   De *= cosh (ge * l);
00451   Do *= cosh (go * l);
00452   y1 = De + Do;
00453   y4 = De - Do;
00454 
00455   // store Y-parameters
00456   setY (NODE_1, NODE_1, y1); setY (NODE_2, NODE_2, y1);
00457   setY (NODE_3, NODE_3, y1); setY (NODE_4, NODE_4, y1);
00458   setY (NODE_1, NODE_2, y2); setY (NODE_2, NODE_1, y2);
00459   setY (NODE_3, NODE_4, y2); setY (NODE_4, NODE_3, y2);
00460   setY (NODE_1, NODE_3, y3); setY (NODE_2, NODE_4, y3);
00461   setY (NODE_3, NODE_1, y3); setY (NODE_4, NODE_2, y3);
00462   setY (NODE_1, NODE_4, y4); setY (NODE_2, NODE_3, y4);
00463   setY (NODE_3, NODE_2, y4); setY (NODE_4, NODE_1, y4);
00464 }
00465 
00466 void mslange::calcNoiseAC (nr_double_t) {
00467   // calculate noise using Bosma's theorem
00468   nr_double_t T = getPropertyDouble ("Temp");
00469   setMatrixN (4 * celsius2kelvin (T) / T0 * real (getMatrixY ()));
00470 }
00471 
00472 // properties
00473 PROP_REQ [] = {
00474   { "W", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
00475   { "L", PROP_REAL, { 10e-3, PROP_NO_STR }, PROP_POS_RANGE },
00476   { "S", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
00477   { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
00478   { "Model", PROP_STR, { PROP_NO_VAL, "Kirschning" },
00479     PROP_RNG_STR2 ("Kirschning", "Hammerstad") },
00480   { "DispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" },
00481     PROP_RNG_STR2 ("Kirschning", "Getsinger") },
00482   PROP_NO_PROP };
00483 PROP_OPT [] = {
00484   { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
00485   PROP_NO_PROP };
00486 struct define_t mslange::cirdef =
00487   { "MLANGE", 4, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };