LCOV - code coverage report
Current view: top level - src/components/microstrip - mscoupled.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 180 283 63.6 %
Date: 2015-01-05 16:01:02 Functions: 5 12 41.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 216 678 31.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * mscoupled.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$
      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 "mscoupled.h"
      33                 :            : 
      34                 :            : using namespace qucs;
      35                 :            : 
      36                 :          6 : mscoupled::mscoupled () : circuit (4) {
      37                 :          6 :   type = CIR_MSCOUPLED;
      38                 :          6 : }
      39                 :            : 
      40                 :        851 : void mscoupled::calcPropagation (nr_double_t frequency) {
      41                 :            : 
      42                 :            :   // fetch line properties
      43         [ +  - ]:        851 :   nr_double_t W = getPropertyDouble ("W");
      44         [ +  - ]:        851 :   nr_double_t s = getPropertyDouble ("S");
      45         [ +  - ]:        851 :   const char * SModel = getPropertyString ("Model");
      46         [ +  - ]:        851 :   const char * DModel = getPropertyString ("DispModel");
      47                 :            : 
      48                 :            :   // fetch substrate properties
      49         [ +  - ]:        851 :   substrate * subst = getSubstrate ();
      50         [ +  - ]:        851 :   nr_double_t er    = subst->getPropertyDouble ("er");
      51         [ +  - ]:        851 :   nr_double_t h     = subst->getPropertyDouble ("h");
      52         [ +  - ]:        851 :   nr_double_t t     = subst->getPropertyDouble ("t");
      53         [ +  - ]:        851 :   nr_double_t tand  = subst->getPropertyDouble ("tand");
      54         [ +  - ]:        851 :   nr_double_t rho   = subst->getPropertyDouble ("rho");
      55         [ +  - ]:        851 :   nr_double_t D     = subst->getPropertyDouble ("D");
      56                 :            : 
      57                 :            :   // quasi-static analysis
      58                 :            :   nr_double_t Zle, ErEffe, Zlo, ErEffo;
      59         [ +  - ]:        851 :   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         [ +  - ]:        851 :                      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         [ +  - ]:        851 :                        frequency, "Hammerstad", ace, ade);
      70                 :            :   msline::analyseLoss (W, t, er, rho, D, tand, Zlo, Zle, ErEffo,
      71         [ +  - ]:        851 :                        frequency, "Hammerstad", aco, ado);
      72                 :            : 
      73                 :            :   // compute propagation constants for even and odd mode
      74                 :        851 :   nr_double_t k0 = 2 * M_PI * frequency / C0;
      75                 :        851 :   ae = ace + ade;
      76                 :        851 :   ao = aco + ado;
      77         [ +  - ]:        851 :   be = qucs::sqrt (ErEffeFreq) * k0;
      78         [ +  - ]:        851 :   bo = qucs::sqrt (ErEffoFreq) * k0;
      79                 :        851 :   ze = ZleFreq;
      80                 :        851 :   zo = ZloFreq;
      81                 :        851 :   ee = ErEffeFreq;
      82                 :        851 :   eo = ErEffoFreq;
      83                 :        851 : }
      84                 :            : 
      85                 :          0 : void mscoupled::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                 :        851 : void mscoupled::calcSP (nr_double_t frequency) {
      93                 :            :   // fetch line properties
      94         [ +  - ]:        851 :   nr_double_t l = getPropertyDouble ("L");
      95                 :            : 
      96                 :            :   // compute propagation constants for even and odd mode
      97         [ +  - ]:        851 :   calcPropagation (frequency);
      98                 :        851 :   nr_complex_t ge = nr_complex_t (ae, be);
      99                 :        851 :   nr_complex_t go = nr_complex_t (ao, bo);
     100                 :            : 
     101                 :            :   // compute abbreviations
     102                 :        851 :   nr_complex_t Ee, Eo, De, Do, Xe, Xo, Ye, Yo;
     103 [ +  - ][ +  - ]:        851 :   Ee = (sqr (ze) + sqr (z0)) * qucs::sinh (ge * l);
                 [ +  - ]
     104 [ +  - ][ +  - ]:        851 :   Eo = (sqr (zo) + sqr (z0)) * qucs::sinh (go * l);
                 [ +  - ]
     105 [ +  - ][ +  - ]:        851 :   De = 2 * ze * z0 * cosh (ge * l) + Ee;
     106 [ +  - ][ +  - ]:        851 :   Do = 2 * zo * z0 * cosh (go * l) + Eo;
     107 [ +  - ][ +  - ]:        851 :   Xe = (sqr (ze) - sqr (z0)) * qucs::sinh (ge * l) / 2.0 / De;
         [ +  - ][ +  - ]
     108 [ +  - ][ +  - ]:        851 :   Xo = (sqr (zo) - sqr (z0)) * qucs::sinh (go * l) / 2.0 / Do;
         [ +  - ][ +  - ]
     109         [ +  - ]:        851 :   Ye = ze * z0 / De;
     110         [ +  - ]:        851 :   Yo = zo * z0 / Do;
     111                 :            : 
     112                 :            :   // reflexion coefficients
     113 [ +  - ][ +  - ]:        851 :   setS (NODE_1, NODE_1, Xe + Xo); setS (NODE_2, NODE_2, Xe + Xo);
         [ +  - ][ +  - ]
     114 [ +  - ][ +  - ]:        851 :   setS (NODE_3, NODE_3, Xe + Xo); setS (NODE_4, NODE_4, Xe + Xo);
         [ +  - ][ +  - ]
     115                 :            :   // through paths
     116 [ +  - ][ +  - ]:        851 :   setS (NODE_1, NODE_2, Ye + Yo); setS (NODE_2, NODE_1, Ye + Yo);
         [ +  - ][ +  - ]
     117 [ +  - ][ +  - ]:        851 :   setS (NODE_3, NODE_4, Ye + Yo); setS (NODE_4, NODE_3, Ye + Yo);
         [ +  - ][ +  - ]
     118                 :            :   // coupled paths
     119 [ +  - ][ +  - ]:        851 :   setS (NODE_1, NODE_4, Xe - Xo); setS (NODE_4, NODE_1, Xe - Xo);
         [ +  - ][ +  - ]
     120 [ +  - ][ +  - ]:        851 :   setS (NODE_2, NODE_3, Xe - Xo); setS (NODE_3, NODE_2, Xe - Xo);
         [ +  - ][ +  - ]
     121                 :            :   // isolated paths
     122 [ +  - ][ +  - ]:        851 :   setS (NODE_1, NODE_3, Ye - Yo); setS (NODE_3, NODE_1, Ye - Yo);
         [ +  - ][ +  - ]
     123 [ +  - ][ +  - ]:        851 :   setS (NODE_2, NODE_4, Ye - Yo); setS (NODE_4, NODE_2, Ye - Yo);
         [ +  - ][ +  - ]
     124                 :        851 : }
     125                 :            : 
     126                 :          0 : void mscoupled::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                 :        851 : void mscoupled::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                 :        851 :   ErEffe = ErEffo = er;
     145                 :        851 :   Zlo = 42.2; Zle = 55.7;
     146                 :            : 
     147                 :            :   // normalized width and gap
     148                 :        851 :   nr_double_t u = W / h;
     149                 :        851 :   nr_double_t g = s / h;
     150                 :            : 
     151                 :            :   // HAMMERSTAD and JENSEN
     152         [ -  + ]:        851 :   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         [ +  - ]:        851 :   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                 :        851 :     nr_double_t ue = u;
     211                 :        851 :     nr_double_t uo = u;
     212 [ +  - ][ +  + ]:        851 :     if (t != 0 && s > 10 * (2 * t)) {
     213                 :        750 :       nr_double_t dW = 0;
     214                 :            :       // SCHNEIDER, referred by JANSEN
     215 [ +  - ][ +  - ]:        750 :       if (u >= M_1_PI / 2 && M_1_PI / 2 > 2 * t / h)
     216         [ +  - ]:        750 :         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                 :        750 :       nr_double_t dt = 2 * t * h / s / er;
     221         [ +  - ]:        750 :       nr_double_t We = W + dW * (1 - 0.5 * qucs::exp (-0.69 * dW / dt));
     222                 :        750 :       nr_double_t Wo = We + dt;
     223                 :        750 :       ue = We / h;
     224                 :        750 :       uo = Wo / h;
     225                 :            :     }
     226                 :            : 
     227                 :            :     // even relative dielectric constant
     228 [ +  - ][ +  - ]:        851 :     v = ue * (20 + sqr (g)) / (10 + sqr (g)) + g * qucs::exp (-g);
                 [ +  - ]
     229         [ +  - ]:        851 :     msline::Hammerstad_ab (v, er, ae, be);
     230         [ +  - ]:        851 :     msline::Hammerstad_er (v, er, ae, be, ErEffe);
     231                 :            : 
     232                 :            :     // odd relative dielectric constant
     233         [ +  - ]:        851 :     msline::Hammerstad_ab (uo, er, a, b);
     234         [ +  - ]:        851 :     msline::Hammerstad_er (uo, er, a, b, ErEff);
     235         [ +  - ]:        851 :     d = 0.593 + 0.694 * qucs::exp (-0.562 * uo);
     236                 :        851 :     bo = 0.747 * er / (0.15 + er);
     237         [ +  - ]:        851 :     co = bo - (bo - 0.207) * qucs::exp (-0.414 * uo);
     238         [ +  - ]:        851 :     ao = 0.7287 * (ErEff - (er + 1) / 2) * (1 - qucs::exp (-0.179 * uo));
     239 [ +  - ][ +  - ]:        851 :     ErEffo = ((er + 1) / 2 + ao - ErEff) * qucs::exp (-co * qucs::pow (g, d)) + ErEff;
     240                 :            : 
     241                 :            :     // characteristic impedance of single line
     242         [ +  - ]:        851 :     msline::Hammerstad_zl (u, Zl1);
     243         [ +  - ]:        851 :     Zl1 /= qucs::sqrt (ErEff);
     244                 :            : 
     245                 :            :     // even characteristic impedance
     246         [ +  - ]:        851 :     q1 = 0.8695 * qucs::pow (ue, 0.194);
     247         [ +  - ]:        851 :     q2 = 1 + 0.7519 * g + 0.189 * qucs::pow (g, 2.31);
     248 [ +  - ][ +  - ]:        851 :     q3 = 0.1975 + qucs::pow (16.6 + qucs::pow (8.4 / g, 6.), -0.387) +
     249 [ +  - ][ +  - ]:        851 :       qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 3.4, 10.))) / 241;
                 [ +  - ]
     250                 :            :     q4 = q1 / q2 * 2 /
     251 [ +  - ][ +  - ]:        851 :       (qucs::exp (-g) * qucs::pow (ue, q3) + (2 - qucs::exp (-g)) * qucs::pow (ue, -q3));
         [ +  - ][ +  - ]
     252 [ +  - ][ +  - ]:        851 :     Zle = qucs::sqrt (ErEff / ErEffe) * Zl1 / (1 - Zl1 * qucs::sqrt (ErEff) * q4 / Z0);
     253                 :            : 
     254                 :            :     // odd characteristic impedance
     255 [ +  - ][ +  - ]:        851 :     q5 = 1.794 + 1.14 * qucs::log (1 + 0.638 / (g + 0.517 * qucs::pow (g, 2.43)));
     256 [ +  - ][ +  - ]:        851 :     q6 = 0.2305 + qucs::log (qucs::pow (g, 10.) / (1 + qucs::pow (g / 5.8, 10.))) / 281.3 +
                 [ +  - ]
     257 [ +  - ][ +  - ]:        851 :       qucs::log (1 + 0.598 * qucs::pow (g, 1.154)) / 5.1;
     258         [ +  - ]:        851 :     q7 = (10 + 190 * sqr (g)) / (1 + 82.3 * cubic (g));
     259 [ +  - ][ +  - ]:        851 :     q8 = qucs::exp (-6.5 - 0.95 * qucs::log (g) - qucs::pow (g / 0.15, 5.));
                 [ +  - ]
     260         [ +  - ]:        851 :     q9 = qucs::log (q7) * (q8 + 1 / 16.5);
     261 [ +  - ][ +  - ]:        851 :     q10 = (q2 * q4 - q5 * qucs::exp (qucs::log (uo) * q6 * qucs::pow (uo, -q9))) / q2;
                 [ +  - ]
     262 [ +  - ][ +  - ]:        851 :     Zlo = qucs::sqrt (ErEff / ErEffo) * Zl1 / (1 - Zl1 * qucs::sqrt (ErEff) * q10 / Z0);
     263                 :            :   }
     264                 :        851 : }
     265                 :            : 
     266                 :            : /* The function computes the dispersion effects on the dielectric
     267                 :            :    constants and characteristic impedances for the even and odd mode
     268                 :            :    of parallel coupled microstrip lines. */
     269                 :        851 : void mscoupled::analyseDispersion (nr_double_t W, nr_double_t h, nr_double_t s,
     270                 :            :                                    nr_double_t er, nr_double_t Zle,
     271                 :            :                                    nr_double_t Zlo, nr_double_t ErEffe,
     272                 :            :                                    nr_double_t ErEffo, nr_double_t frequency,
     273                 :            :                                    const char * const DModel, nr_double_t& ZleFreq,
     274                 :            :                                    nr_double_t& ZloFreq,
     275                 :            :                                    nr_double_t& ErEffeFreq,
     276                 :            :                                    nr_double_t& ErEffoFreq) {
     277                 :            : 
     278                 :            :   // initialize default return values
     279                 :        851 :   ZleFreq = Zle;
     280                 :        851 :   ErEffeFreq = ErEffe;
     281                 :        851 :   ZloFreq = Zlo;
     282                 :        851 :   ErEffoFreq = ErEffo;
     283                 :            : 
     284                 :            :   // normalized width and gap
     285                 :        851 :   nr_double_t u = W / h;
     286                 :        851 :   nr_double_t g = s / h;
     287                 :            : 
     288                 :            :   // GETSINGER
     289         [ -  + ]:        851 :   if (!strcmp (DModel, "Getsinger")) {
     290                 :            :     // even mode dispersion
     291                 :            :     msline::Getsinger_disp (h, er, ErEffe, Zle / 2,
     292                 :          0 :                             frequency, ErEffeFreq, ZleFreq);
     293                 :          0 :     ZleFreq *= 2;
     294                 :            :     // odd mode dispersion
     295                 :            :     msline::Getsinger_disp (h, er, ErEffo, Zlo * 2,
     296                 :          0 :                             frequency, ErEffoFreq, ZloFreq);
     297                 :          0 :     ZloFreq /= 2;
     298                 :            :   }
     299                 :            :   // KIRSCHNING and JANSEN
     300         [ +  - ]:        851 :   else if (!strcmp (DModel, "Kirschning")) {
     301                 :            :     nr_double_t p1, p2, p3, p4, p5, p6, p7, Fe;
     302                 :        851 :     nr_double_t fn = frequency * h * 1e-6;
     303                 :            : 
     304                 :            :     // even relative dielectric constant dispersion
     305         [ +  - ]:        851 :     p1 = 0.27488 * (0.6315 + 0.525 / qucs::pow (1 + 0.0157 * fn, 20.)) * u -
     306         [ +  - ]:        851 :       0.065683 * qucs::exp (-8.7513 * u);
     307         [ +  - ]:        851 :     p2 = 0.33622 * (1 - qucs::exp (-0.03442 * er));
     308 [ +  - ][ +  - ]:        851 :     p3 = 0.0363 * qucs::exp (-4.6 * u) * (1 - qucs::exp (- qucs::pow (fn / 38.7, 4.97)));
                 [ +  - ]
     309 [ +  - ][ +  - ]:        851 :     p4 = 1 + 2.751 * (1 - qucs::exp (- qucs::pow (er / 15.916, 8.)));
     310         [ +  - ]:        851 :     p5 = 0.334 * qucs::exp (-3.3 * cubic (er / 15)) + 0.746;
     311 [ +  - ][ +  - ]:        851 :     p6 = p5 * qucs::exp (- qucs::pow (fn / 18, 0.368));
     312         [ +  - ]:        851 :     p7 = 1 + 4.069 * p6 * qucs::pow (g, 0.479) *
     313 [ +  - ][ +  - ]:        851 :       qucs::exp (-1.347 * qucs::pow (g, 0.595) - 0.17 * qucs::pow (g, 2.5));
                 [ +  - ]
     314         [ +  - ]:        851 :     Fe = p1 * p2 * qucs::pow ((p3 * p4 + 0.1844 * p7) * fn, 1.5763);
     315                 :        851 :     ErEffeFreq = er - (er - ErEffe) / (1 + Fe);
     316                 :            : 
     317                 :            :     // odd relative dielectric constant dispersion
     318                 :            :     nr_double_t p8, p9, p10, p11, p12, p13, p14, p15, Fo;
     319                 :        851 :     p8 = 0.7168 * (1 + 1.076 / (1 + 0.0576 * (er - 1)));
     320 [ +  - ][ +  - ]:        851 :     p9 = p8 - 0.7913 * (1 - qucs::exp (- qucs::pow (fn / 20, 1.424))) *
     321 [ +  - ][ +  - ]:        851 :       qucs::atan (2.481 * qucs::pow (er / 8, 0.946));
     322         [ +  - ]:        851 :     p10 = 0.242 * qucs::pow (er - 1, 0.55);
     323         [ +  - ]:        851 :     p11 = 0.6366 * (qucs::exp (-0.3401 * fn) - 1) *
     324 [ +  - ][ +  - ]:        851 :       qucs::atan (1.263 * qucs::pow (u / 3, 1.629));
     325         [ +  - ]:        851 :     p12 = p9 + (1 - p9) / (1 + 1.183 * qucs::pow (u, 1.376));
     326                 :        851 :     p13 = 1.695 * p10 / (0.414 + 1.605 * p10);
     327 [ +  - ][ +  - ]:        851 :     p14 = 0.8928 + 0.1072 * (1 - qucs::exp (-0.42 * qucs::pow (fn / 20, 3.215)));
     328                 :            :     p15 = fabs (1 - 0.8928 * (1 + p11) *
     329 [ +  - ][ +  - ]:        851 :                 qucs::exp (-p13 * qucs::pow (g, 1.092)) * p12 / p14);
     330         [ +  - ]:        851 :     Fo = p1 * p2 * qucs::pow ((p3 * p4 + 0.1844) * fn * p15, 1.5763);
     331                 :        851 :     ErEffoFreq = er - (er - ErEffo) / (1 + Fo);
     332                 :            : 
     333                 :            :     // dispersion of even characteristic impedance
     334                 :            :     nr_double_t t, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21;
     335                 :        851 :     q11 = 0.893 * (1 - 0.3 / (1 + 0.7 * (er - 1)));
     336         [ +  - ]:        851 :     t = qucs::pow (fn / 20, 4.91);
     337 [ +  - ][ +  - ]:        851 :     q12 = 2.121 * t / (1 + q11 * t) * qucs::exp (-2.87 * g) * qucs::pow (g, 0.902);
     338         [ +  - ]:        851 :     q13 = 1 + 0.038 * qucs::pow (er / 8, 5.1);
     339         [ +  - ]:        851 :     t = quadr (er / 15);
     340                 :        851 :     q14 = 1 + 1.203 * t / (1 + t);
     341 [ +  - ][ +  - ]:        851 :     q15 = 1.887 * qucs::exp (-1.5 * qucs::pow (g, 0.84)) * qucs::pow (g, q14) /
                 [ +  - ]
     342         [ +  - ]:        851 :       (1 + 0.41 * qucs::pow (fn / 15, 3.) *
     343 [ +  - ][ +  - ]:        851 :        qucs::pow (u, 2 / q13) / (0.125 + qucs::pow (u, 1.626 / q13)));
     344         [ +  - ]:        851 :     q16 = q15 * (1 + 9 / (1 + 0.403 * sqr (er - 1)));
     345 [ +  - ][ +  - ]:        851 :     q17 = 0.394 * (1 - qucs::exp (-1.47 * qucs::pow (u / 7, 0.672))) *
     346 [ +  - ][ +  - ]:        851 :       (1 - qucs::exp (-4.25 * qucs::pow (fn / 20, 1.87)));
     347 [ +  - ][ +  - ]:        851 :     q18 = 0.61 * (1 - qucs::exp (-2.31 * qucs::pow (u / 8, 1.593))) /
     348         [ +  - ]:        851 :       (1 + 6.544 * qucs::pow (g, 4.17));
     349 [ +  - ][ +  - ]:        851 :     q19 = 0.21 * quadr (g) / (1 + 0.18 * qucs::pow (g, 4.9)) / (1 + 0.1 * sqr (u)) /
                 [ +  - ]
     350         [ +  - ]:        851 :       (1 + qucs::pow (fn / 24, 3.));
     351         [ +  - ]:        851 :     q20 = q19 * (0.09 + 1 / (1 + 0.1 * qucs::pow (er - 1, 2.7)));
     352         [ +  - ]:        851 :     t = qucs::pow (u, 2.5);
     353 [ +  - ][ +  - ]:        851 :     q21 = fabs (1 - 42.54 * qucs::pow (g, 0.133) * qucs::exp (-0.812 * g) * t /
     354                 :       1702 :                 (1 + 0.033 * t));
     355                 :            : 
     356                 :            :     nr_double_t re, qe, pe, de, Ce, q0, ZlFreq, ErEffFreq;
     357         [ +  - ]:        851 :     msline::Kirschning_er (u, fn, er, ErEffe, ErEffFreq);
     358         [ +  - ]:        851 :     msline::Kirschning_zl (u, fn, er, ErEffe, ErEffFreq, Zle, q0, ZlFreq);
     359         [ +  - ]:        851 :     re = qucs::pow (fn / 28.843, 12.);
     360         [ +  - ]:        851 :     qe = 0.016 + qucs::pow (0.0514 * er * q21, 4.524);
     361 [ +  - ][ +  - ]:        851 :     pe = 4.766 * qucs::exp (-3.228 * qucs::pow (u, 0.641));
     362         [ +  - ]:        851 :     t = qucs::pow (er - 1, 6.);
     363                 :            :     de = 5.086 * qe * re / (0.3838 + 0.386 * qe) *
     364 [ +  - ][ +  - ]:        851 :       qucs::exp (-22.2 * qucs::pow (u, 1.92)) / (1 + 1.2992 * re) * t / (1 + 10 * t);
     365         [ +  - ]:        851 :     Ce = 1 + 1.275 * (1 - qucs::exp (-0.004625 * pe * qucs::pow (er, 1.674) *
     366 [ +  - ][ +  - ]:        851 :          qucs::pow (fn / 18.365, 2.745))) - q12 + q16 - q17 + q18 + q20;
     367         [ +  - ]:        851 :     ZleFreq = Zle * qucs::pow ((0.9408 * qucs::pow (ErEffFreq, Ce) - 0.9603) /
     368 [ +  - ][ +  - ]:        851 :                          ((0.9408 - de) * qucs::pow (ErEffe, Ce) - 0.9603), q0);
     369                 :            : 
     370                 :            :     // dispersion of odd characteristic impedance
     371                 :            :     nr_double_t q22, q23, q24, q25, q26, q27, q28, q29;
     372         [ +  - ]:        851 :     msline::Kirschning_er (u, fn, er, ErEffo, ErEffFreq);
     373         [ +  - ]:        851 :     msline::Kirschning_zl (u, fn, er, ErEffo, ErEffFreq, Zlo, q0, ZlFreq);
     374         [ +  - ]:        851 :     q29 = 15.16 / (1 + 0.196 * sqr (er - 1));
     375         [ +  - ]:        851 :     t = sqr (er - 1);
     376 [ +  - ][ +  - ]:        851 :     q25 = 0.3 * sqr (fn) / (10 + sqr (fn)) * (1 + 2.333 * t / (5 + t));
     377         [ +  - ]:        851 :     t = qucs::pow ((er - 1) / 13, 12.);
     378                 :        851 :     q26 = 30 - 22.2 * t / (1 + 3 * t) - q29;
     379         [ +  - ]:        851 :     t = qucs::pow (er - 1, 1.5);
     380         [ +  - ]:        851 :     q27 = 0.4 * qucs::pow (g, 0.84) * (1 + 2.5 * t / (5 + t));
     381         [ +  - ]:        851 :     t = qucs::pow (er - 1, 3.);
     382                 :        851 :     q28 = 0.149 * t / (94.5 + 0.038 * t);
     383 [ +  - ][ +  - ]:        851 :     q22 = 0.925 * qucs::pow (fn / q26, 1.536) / (1 + 0.3 * qucs::pow (fn / 30, 1.536));
     384         [ +  - ]:        851 :     q23 = 1 + 0.005 * fn * q27 / (1 + 0.812 * qucs::pow (fn / 15, 1.9)) /
     385         [ +  - ]:        851 :       (1 + 0.025 * sqr (u));
     386         [ +  - ]:        851 :     t = qucs::pow (u, 0.894);
     387                 :            :     q24 = 2.506 * q28 * t / (3.575 + t) *
     388         [ +  - ]:        851 :       qucs::pow ((1 + 1.3 * u) * fn / 99.25, 4.29);
     389         [ +  - ]:        851 :     ZloFreq = ZlFreq + (Zlo * qucs::pow (ErEffoFreq / ErEffo, q22) - ZlFreq * q23) /
     390         [ +  - ]:        851 :       (1 + q24 + qucs::pow (0.46 * g, 2.2) * q25);
     391                 :            : 
     392                 :            :   }
     393                 :        851 : }
     394                 :            : 
     395                 :          0 : void mscoupled::initDC (void) {
     396                 :          0 :   nr_double_t l     = getPropertyDouble ("L");
     397                 :          0 :   nr_double_t W     = getPropertyDouble ("W");
     398                 :          0 :   substrate * subst = getSubstrate ();
     399                 :          0 :   nr_double_t t     = subst->getPropertyDouble ("t");
     400                 :          0 :   nr_double_t rho   = subst->getPropertyDouble ("rho");
     401                 :            : 
     402 [ #  # ][ #  # ]:          0 :   if (t != 0.0 && rho != 0.0) {
     403                 :            :     // tiny resistances
     404                 :          0 :     nr_double_t g = t * W / rho / l;
     405                 :          0 :     setVoltageSources (0);
     406                 :          0 :     allocMatrixMNA ();
     407 [ #  # ][ #  # ]:          0 :     setY (NODE_1, NODE_1, +g); setY (NODE_2, NODE_2, +g);
     408 [ #  # ][ #  # ]:          0 :     setY (NODE_1, NODE_2, -g); setY (NODE_2, NODE_1, -g);
     409 [ #  # ][ #  # ]:          0 :     setY (NODE_3, NODE_3, +g); setY (NODE_4, NODE_4, +g);
     410 [ #  # ][ #  # ]:          0 :     setY (NODE_3, NODE_4, -g); setY (NODE_4, NODE_3, -g);
     411                 :            :   }
     412                 :            :   else {
     413                 :            :     // DC shorts (voltage sources V = 0 volts)
     414                 :          0 :     setVoltageSources (2);
     415                 :          0 :     setInternalVoltageSource (1);
     416                 :          0 :     allocMatrixMNA ();
     417                 :          0 :     clearY ();
     418                 :          0 :     voltageSource (VSRC_1, NODE_1, NODE_2);
     419                 :          0 :     voltageSource (VSRC_2, NODE_3, NODE_4);
     420 [ #  # ][ #  # ]:          0 :     setD (VSRC_1, VSRC_2, 0.0); setD (VSRC_2, VSRC_1, 0.0);
     421                 :            :   }
     422                 :          0 : }
     423                 :            : 
     424                 :          0 : void mscoupled::initAC (void) {
     425                 :          0 :   setVoltageSources (0);
     426                 :          0 :   allocMatrixMNA ();
     427                 :          0 : }
     428                 :            : 
     429                 :          0 : void mscoupled::calcAC (nr_double_t frequency) {
     430                 :            :   // fetch line properties
     431         [ #  # ]:          0 :   nr_double_t l = getPropertyDouble ("L");
     432                 :            : 
     433                 :            :   // compute propagation constants for even and odd mode
     434         [ #  # ]:          0 :   calcPropagation (frequency);
     435                 :          0 :   nr_complex_t ge = nr_complex_t (ae, be);
     436                 :          0 :   nr_complex_t go = nr_complex_t (ao, bo);
     437                 :            : 
     438                 :            :   // compute abbreviations
     439                 :          0 :   nr_complex_t De, Do, y1, y2, y3, y4;
     440 [ #  # ][ #  # ]:          0 :   De = 0.5 / (ze * qucs::sinh (ge * l));
     441 [ #  # ][ #  # ]:          0 :   Do = 0.5 / (zo * qucs::sinh (go * l));
     442         [ #  # ]:          0 :   y2 = -De - Do;
     443         [ #  # ]:          0 :   y3 = -De + Do;
     444         [ #  # ]:          0 :   De *= cosh (ge * l);
     445         [ #  # ]:          0 :   Do *= cosh (go * l);
     446         [ #  # ]:          0 :   y1 = De + Do;
     447         [ #  # ]:          0 :   y4 = De - Do;
     448                 :            : 
     449                 :            :   // store Y-parameters
     450 [ #  # ][ #  # ]:          0 :   setY (NODE_1, NODE_1, y1); setY (NODE_2, NODE_2, y1);
     451 [ #  # ][ #  # ]:          0 :   setY (NODE_3, NODE_3, y1); setY (NODE_4, NODE_4, y1);
     452 [ #  # ][ #  # ]:          0 :   setY (NODE_1, NODE_2, y2); setY (NODE_2, NODE_1, y2);
     453 [ #  # ][ #  # ]:          0 :   setY (NODE_3, NODE_4, y2); setY (NODE_4, NODE_3, y2);
     454 [ #  # ][ #  # ]:          0 :   setY (NODE_1, NODE_3, y3); setY (NODE_2, NODE_4, y3);
     455 [ #  # ][ #  # ]:          0 :   setY (NODE_3, NODE_1, y3); setY (NODE_4, NODE_2, y3);
     456 [ #  # ][ #  # ]:          0 :   setY (NODE_1, NODE_4, y4); setY (NODE_2, NODE_3, y4);
     457 [ #  # ][ #  # ]:          0 :   setY (NODE_3, NODE_2, y4); setY (NODE_4, NODE_1, y4);
     458                 :          0 : }
     459                 :            : 
     460                 :          0 : void mscoupled::calcNoiseAC (nr_double_t) {
     461                 :            :   // calculate noise using Bosma's theorem
     462                 :          0 :   nr_double_t T = getPropertyDouble ("Temp");
     463 [ #  # ][ #  # ]:          0 :   setMatrixN (4 * kelvin (T) / T0 * real (getMatrixY ()));
         [ #  # ][ #  # ]
                 [ #  # ]
     464                 :          0 : }
     465                 :            : 
     466                 :            : // properties
     467                 :            : PROP_REQ [] = {
     468                 :            :   { "W", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
     469                 :            :   { "L", PROP_REAL, { 10e-3, PROP_NO_STR }, PROP_POS_RANGE },
     470                 :            :   { "S", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
     471                 :            :   { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
     472                 :            :   { "Model", PROP_STR, { PROP_NO_VAL, "Kirschning" },
     473                 :            :     PROP_RNG_STR2 ("Kirschning", "Hammerstad") },
     474                 :            :   { "DispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" },
     475                 :            :     PROP_RNG_STR2 ("Kirschning", "Getsinger") },
     476                 :            :   PROP_NO_PROP };
     477                 :            : PROP_OPT [] = {
     478                 :            :   { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
     479                 :            :   PROP_NO_PROP };
     480                 :            : struct define_t mscoupled::cirdef =
     481                 :            :   { "MCOUPLED", 4, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };

Generated by: LCOV version 1.11