LCOV - code coverage report
Current view: top level - src/components/microstrip - msline.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 130 247 52.6 %
Date: 2015-01-05 16:01:02 Functions: 11 19 57.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 54 340 15.9 %

           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 };

Generated by: LCOV version 1.11