LCOV - code coverage report
Current view: top level - src/components/microstrip - mstee.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 110 174 63.2 %
Date: 2015-01-05 16:01:02 Functions: 6 14 42.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 55 148 37.2 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * mstee.cpp - microstrip t-junction class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 2004, 2005, 2006 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 "device.h"
      32                 :            : #include "msline.h"
      33                 :            : #include "mstee.h"
      34                 :            : 
      35                 :            : using namespace qucs;
      36                 :            : using namespace qucs::device;
      37                 :            : 
      38                 :          1 : mstee::mstee () : circuit (3) {
      39                 :          1 :   lineA = lineB = line2 = NULL;
      40                 :          1 :   type = CIR_MSTEE;
      41                 :          1 : }
      42                 :            : 
      43                 :          1 : void mstee::initSP (void) {
      44                 :          1 :   allocMatrixS ();
      45                 :          1 :   initLines ();
      46                 :          1 :   lineA->initSP ();
      47                 :          1 :   lineB->initSP ();
      48                 :          1 :   line2->initSP ();
      49                 :          1 : }
      50                 :            : 
      51                 :          0 : void mstee::initNoiseSP (void) {
      52                 :          0 :   allocMatrixN ();
      53                 :          0 :   lineA->initNoiseSP ();
      54                 :          0 :   lineB->initNoiseSP ();
      55                 :          0 :   line2->initNoiseSP ();
      56                 :          0 : }
      57                 :            : 
      58                 :          1 : void mstee::initLines (void) {
      59                 :          1 :   lineA = splitMicrostrip (this, lineA, getNet (), "LineA", "NodeA", NODE_1);
      60                 :          1 :   lineA->setProperty ("W", getPropertyDouble ("W1"));
      61                 :          1 :   lineA->setProperty ("Temp", getPropertyDouble ("Temp"));
      62                 :          1 :   lineA->setProperty ("Model", getPropertyString ("MSModel"));
      63                 :          1 :   lineA->setProperty ("DispModel", getPropertyString ("MSDispModel"));
      64                 :          1 :   lineA->setSubstrate (getSubstrate ());
      65                 :            : 
      66                 :          1 :   lineB = splitMicrostrip (this, lineB, getNet (), "LineB", "NodeB", NODE_2);
      67                 :          1 :   lineB->setProperty ("W", getPropertyDouble ("W2"));
      68                 :          1 :   lineB->setProperty ("Temp", getPropertyDouble ("Temp"));
      69                 :          1 :   lineB->setProperty ("Model", getPropertyString ("MSModel"));
      70                 :          1 :   lineB->setProperty ("DispModel", getPropertyString ("MSDispModel"));
      71                 :          1 :   lineB->setSubstrate (getSubstrate ());
      72                 :            : 
      73                 :          1 :   line2 = splitMicrostrip (this, line2, getNet (), "Line2", "Node2", NODE_3);
      74                 :          1 :   line2->setProperty ("W", getPropertyDouble ("W3"));
      75                 :          1 :   line2->setProperty ("Temp", getPropertyDouble ("Temp"));
      76                 :          1 :   line2->setProperty ("Model", getPropertyString ("MSModel"));
      77                 :          1 :   line2->setProperty ("DispModel", getPropertyString ("MSDispModel"));
      78                 :          1 :   line2->setSubstrate (getSubstrate ());
      79                 :          1 : }
      80                 :            : 
      81                 :         39 : void mstee::calcSP (nr_double_t frequency) {
      82         [ +  - ]:         39 :   calcPropagation (frequency);
      83                 :            : 
      84         [ +  - ]:         39 :   lineA->setProperty ("L", La);
      85         [ +  - ]:         39 :   lineB->setProperty ("L", Lb);
      86         [ +  - ]:         39 :   line2->setProperty ("L", L2);
      87         [ +  - ]:         39 :   lineA->calcSP (frequency);
      88         [ +  - ]:         39 :   lineB->calcSP (frequency);
      89         [ +  - ]:         39 :   line2->calcSP (frequency);
      90                 :            : 
      91                 :            :   // calculate S-parameters
      92                 :         39 :   nr_complex_t n1 = Ta2 * nr_complex_t (1 + 1 / Tb2, Bt * z0);
      93                 :         39 :   nr_complex_t n2 = Tb2 * nr_complex_t (1 + 1 / Ta2, Bt * z0);
      94                 :         39 :   nr_complex_t n3 = nr_complex_t (1 / Ta2 + 1 / Tb2, Bt * z0);
      95 [ +  - ][ +  - ]:         39 :   setS (NODE_1, NODE_1, (1.0 - n1) / (1.0 + n1));
      96 [ +  - ][ +  - ]:         39 :   setS (NODE_2, NODE_2, (1.0 - n2) / (1.0 + n2));
      97 [ +  - ][ +  - ]:         39 :   setS (NODE_3, NODE_3, (1.0 - n3) / (1.0 + n3));
      98 [ +  - ][ +  - ]:         39 :   setS (NODE_1, NODE_3, 2.0 * std::sqrt (Ta2) / (1.0 + n1));
      99 [ +  - ][ +  - ]:         39 :   setS (NODE_3, NODE_1, 2.0 * std::sqrt (Ta2) / (1.0 + n1));
     100 [ +  - ][ +  - ]:         39 :   setS (NODE_2, NODE_3, 2.0 * std::sqrt (Tb2) / (1.0 + n2));
     101 [ +  - ][ +  - ]:         39 :   setS (NODE_3, NODE_2, 2.0 * std::sqrt (Tb2) / (1.0 + n2));
     102                 :         39 :   setS (NODE_1, NODE_2, 2.0 / (std::sqrt (Ta2 * Tb2) * nr_complex_t (1, Bt * z0) +
     103 [ +  - ][ +  - ]:         39 :                                std::sqrt (Ta2 / Tb2) + std::sqrt (Tb2 / Ta2)));
     104                 :         39 :   setS (NODE_2, NODE_1, 2.0 / (std::sqrt (Ta2 * Tb2) * nr_complex_t (1, Bt * z0) +
     105 [ +  - ][ +  - ]:         39 :                                std::sqrt (Ta2 / Tb2) + std::sqrt (Tb2 / Ta2)));
     106                 :         39 : }
     107                 :            : 
     108                 :         39 : void mstee::calcPropagation (nr_double_t f) {
     109                 :            : 
     110         [ +  - ]:         39 :   const char * SModel = getPropertyString ("MSModel");
     111         [ +  - ]:         39 :   const char * DModel = getPropertyString ("MSDispModel");
     112         [ +  - ]:         39 :   substrate * subst = getSubstrate ();
     113         [ +  - ]:         39 :   nr_double_t er = subst->getPropertyDouble ("er");
     114         [ +  - ]:         39 :   nr_double_t h  = subst->getPropertyDouble ("h");
     115         [ +  - ]:         39 :   nr_double_t t  = subst->getPropertyDouble ("t");
     116         [ +  - ]:         39 :   nr_double_t Wa = getPropertyDouble ("W1");
     117         [ +  - ]:         39 :   nr_double_t Wb = getPropertyDouble ("W2");
     118         [ +  - ]:         39 :   nr_double_t W2 = getPropertyDouble ("W3");
     119                 :            : 
     120                 :            :   nr_double_t Zla, Zlb, Zl2, Era, Erb, Er2;
     121                 :            : 
     122                 :            :   // computation of impedances and effective dielectric constants
     123                 :            :   nr_double_t ZlEff, ErEff, WEff;
     124         [ +  - ]:         39 :   msline::analyseQuasiStatic (Wa, h, t, er, SModel, ZlEff, ErEff, WEff);
     125                 :            :   msline::analyseDispersion  (Wa, h, er, ZlEff, ErEff, f, DModel,
     126         [ +  - ]:         39 :                               Zla, Era);
     127         [ +  - ]:         39 :   msline::analyseQuasiStatic (Wb, h, t, er, SModel, ZlEff, ErEff, WEff);
     128                 :            :   msline::analyseDispersion  (Wb, h, er, ZlEff, ErEff, f, DModel,
     129         [ +  - ]:         39 :                               Zlb, Erb);
     130         [ +  - ]:         39 :   msline::analyseQuasiStatic (W2, h, t, er, SModel, ZlEff, ErEff, WEff);
     131                 :            :   msline::analyseDispersion  (W2, h, er, ZlEff, ErEff, f, DModel,
     132         [ +  - ]:         39 :                               Zl2, Er2);
     133                 :            : 
     134                 :            :   // local variables
     135                 :            :   nr_double_t Da, Db, D2, fpa, fpb, lda, ldb, da, db, d2, r, q;
     136                 :            : 
     137                 :            :   // equivalent parallel plate line widths
     138                 :         39 :   Da = Z0 / Zla * h / std::sqrt (Era);
     139                 :         39 :   Db = Z0 / Zlb * h / std::sqrt (Erb);
     140                 :         39 :   D2 = Z0 / Zl2 * h / std::sqrt (Er2);
     141                 :            : 
     142                 :            :   // first higher order mode cut-off frequencies
     143                 :         39 :   fpa = 0.4e6 * Zla / h;
     144                 :         39 :   fpb = 0.4e6 * Zlb / h;
     145                 :            : 
     146                 :            :   // effective wavelengths of quasi-TEM mode
     147                 :         39 :   lda = C0 / std::sqrt (Era) / f;
     148                 :         39 :   ldb = C0 / std::sqrt (Erb) / f;
     149                 :            : 
     150                 :            :   // main arm displacements
     151         [ +  - ]:         39 :   da = 0.055 * D2 * Zla / Zl2 * (1 - 2 * Zla / Zl2 * sqr (f / fpa));
     152         [ +  - ]:         39 :   db = 0.055 * D2 * Zlb / Zl2 * (1 - 2 * Zlb / Zl2 * sqr (f / fpb));
     153                 :            : 
     154                 :            :   // length of lines in the main arms
     155                 :         39 :   La = 0.5 * W2 - da;
     156                 :         39 :   Lb = 0.5 * W2 - db;
     157                 :            : 
     158                 :            :   // displacement and length of line in the side arm
     159                 :         39 :   r = std::sqrt (Zla * Zlb) / Zl2;
     160         [ +  - ]:         39 :   q = sqr (f) / fpa / fpb;
     161                 :         39 :   d2 = std::sqrt (Da * Db) * (0.5 - r * (0.05 + 0.7 * std::exp (-1.6 * r) +
     162                 :         39 :                                     0.25 * r * q - 0.17 * std::log (r)));
     163         [ -  + ]:         39 :   L2 = 0.5 * MAX (Wa, Wb) - d2;
     164                 :            : 
     165                 :            :   // turn ratio of transformers in main arms
     166         [ +  - ]:         39 :   Ta2 = 1 - M_PI * sqr (f / fpa) *
     167 [ +  - ][ +  - ]:         39 :         (sqr (Zla / Zl2) / 12 + sqr (0.5 - d2 / Da));
     168         [ +  - ]:         39 :   Tb2 = 1 - M_PI * sqr (f / fpb) *
     169 [ +  - ][ +  - ]:         39 :         (sqr (Zlb / Zl2) / 12 + sqr (0.5 - d2 / Db));
     170         [ +  - ]:         39 :   Ta2 = MAX (Ta2, NR_TINY);
     171         [ +  - ]:         39 :   Tb2 = MAX (Tb2, NR_TINY);
     172                 :            : 
     173                 :            :   // shunt susceptance
     174                 :         39 :   Bt = 5.5 * std::sqrt (Da * Db / lda / ldb) * (er + 2) / er /
     175                 :         78 :     Zl2 / std::sqrt (Ta2 * Tb2) * std::sqrt (da * db) / D2 *
     176                 :         78 :     (1 + 0.9 * std::log (r) + 4.5 * r * q - 4.4 * std::exp (-1.3 * r) -
     177         [ +  - ]:         39 :      20 * sqr (Zl2 / Z0));
     178                 :         39 : }
     179                 :            : 
     180                 :            : /* This function can be used to create an extra microstrip circuit.
     181                 :            :    If the 'line' argument is NULL then the new circuit is created, the
     182                 :            :    nodes get re-arranged and it is inserted into the given
     183                 :            :    netlist. The given arguments can be explained as follows.
     184                 :            :    base:     calling circuit (this)
     185                 :            :    line:     additional microstrip line circuit (can be NULL)
     186                 :            :    subnet:   the netlist object
     187                 :            :    c:        name of the additional circuit
     188                 :            :    n:        name of the inserted (internal) node
     189                 :            :    internal: number of new internal node (the original external node) */
     190                 :          3 : circuit * splitMicrostrip (circuit * base, circuit * line, net * subnet,
     191                 :            :                            const char * c, const char * n, int internal) {
     192         [ +  - ]:          3 :   if (line == NULL) {
     193         [ +  - ]:          3 :     line = new msline ();
     194                 :          3 :     char * name = circuit::createInternal (c, base->getName ());
     195                 :          3 :     char * node = circuit::createInternal (n, base->getName ());
     196                 :          3 :     line->setName (name);
     197                 :          3 :     line->setNode (0, base->getNode(internal)->getName ());
     198                 :          3 :     line->setNode (1, node, 1);
     199                 :          3 :     subnet->insertCircuit (line);
     200                 :          3 :     free (name);
     201                 :          3 :     free (node);
     202                 :            :   }
     203                 :          3 :   base->setNode (internal, line->getNode(1)->getName (), 1);
     204                 :          3 :   return line;
     205                 :            : }
     206                 :            : 
     207                 :            : /* This function is the counterpart of the above routine.  It removes
     208                 :            :    the microstrip circuit from the netlist and re-assigns the original
     209                 :            :    node. */
     210                 :          0 : void disableMicrostrip (circuit * base, circuit * line, net * subnet,
     211                 :            :                         int internal) {
     212         [ #  # ]:          0 :   if (line != NULL) {
     213                 :          0 :     subnet->removeCircuit (line, 0);
     214                 :          0 :     base->setNode (internal, line->getNode(1)->getName (), 0);
     215                 :            :   }
     216                 :          0 : }
     217                 :            : 
     218                 :          0 : void mstee::initDC (void) {
     219                 :          0 :   setVoltageSources (2);
     220                 :          0 :   setInternalVoltageSource (1);
     221                 :          0 :   allocMatrixMNA ();
     222                 :          0 :   voltageSource (VSRC_1, NODE_1, NODE_2);
     223                 :          0 :   voltageSource (VSRC_2, NODE_1, NODE_3);
     224         [ #  # ]:          0 :   if (deviceEnabled (lineA)) {
     225                 :          0 :     disableMicrostrip (this, lineA, getNet (), NODE_1);
     226                 :            :   }
     227         [ #  # ]:          0 :   if (deviceEnabled (lineB)) {
     228                 :          0 :     disableMicrostrip (this, lineB, getNet (), NODE_2);
     229                 :            :   }
     230         [ #  # ]:          0 :   if (deviceEnabled (line2)) {
     231                 :          0 :     disableMicrostrip (this, line2, getNet (), NODE_3);
     232                 :            :   }
     233                 :          0 : }
     234                 :            : 
     235                 :          0 : void mstee::initAC (void) {
     236                 :          0 :   setVoltageSources (3);
     237                 :          0 :   setInternalVoltageSource (1);
     238                 :          0 :   allocMatrixMNA ();
     239 [ #  # ][ #  # ]:          0 :   setB (NODE_1, VSRC_1, +1); setB (NODE_2, VSRC_2, +1);
     240         [ #  # ]:          0 :   setB (NODE_3, VSRC_3, +1);
     241 [ #  # ][ #  # ]:          0 :   setC (VSRC_1, NODE_1, -1); setC (VSRC_2, NODE_2, -1);
     242         [ #  # ]:          0 :   setC (VSRC_3, NODE_3, -1);
     243                 :          0 :   initLines ();
     244                 :          0 :   lineA->initAC ();
     245                 :          0 :   lineB->initAC ();
     246                 :          0 :   line2->initAC ();
     247                 :          0 : }
     248                 :            : 
     249                 :          0 : void mstee::initNoiseAC (void) {
     250                 :          0 :   allocMatrixN (getVoltageSources ());
     251                 :          0 :   lineA->initNoiseAC ();
     252                 :          0 :   lineB->initNoiseAC ();
     253                 :          0 :   line2->initNoiseAC ();
     254                 :          0 : }
     255                 :            : 
     256                 :          0 : void mstee::calcAC (nr_double_t frequency) {
     257                 :          0 :   calcPropagation (frequency);
     258                 :            : 
     259                 :          0 :   lineA->setProperty ("L", La);
     260                 :          0 :   lineB->setProperty ("L", Lb);
     261                 :          0 :   line2->setProperty ("L", L2);
     262                 :          0 :   lineA->calcAC (frequency);
     263                 :          0 :   lineB->calcAC (frequency);
     264                 :          0 :   line2->calcAC (frequency);
     265                 :            : 
     266                 :            :   // calculate Z-parameters
     267         [ #  # ]:          0 :   setD (VSRC_1, VSRC_1, nr_complex_t (0, -1 / Ta2 / Bt));
     268         [ #  # ]:          0 :   setD (VSRC_1, VSRC_2, nr_complex_t (0, -1 / std::sqrt (Ta2 * Tb2) / Bt));
     269         [ #  # ]:          0 :   setD (VSRC_1, VSRC_3, nr_complex_t (0, -1 / std::sqrt (Ta2) / Bt));
     270         [ #  # ]:          0 :   setD (VSRC_2, VSRC_1, nr_complex_t (0, -1 / std::sqrt (Ta2 * Tb2) / Bt));
     271         [ #  # ]:          0 :   setD (VSRC_2, VSRC_2, nr_complex_t (0, -1 / Tb2 / Bt));
     272         [ #  # ]:          0 :   setD (VSRC_2, VSRC_3, nr_complex_t (0, -1 / std::sqrt (Tb2) / Bt));
     273         [ #  # ]:          0 :   setD (VSRC_3, VSRC_1, nr_complex_t (0, -1 / std::sqrt (Ta2) / Bt));
     274         [ #  # ]:          0 :   setD (VSRC_3, VSRC_2, nr_complex_t (0, -1 / std::sqrt (Tb2) / Bt));
     275         [ #  # ]:          0 :   setD (VSRC_3, VSRC_3, nr_complex_t (0, -1 / Bt));
     276                 :          0 : }
     277                 :            : 
     278                 :          0 : void mstee::initTR (void) {
     279                 :          0 :   initDC ();
     280                 :          0 : }
     281                 :            : 
     282                 :            : // properties
     283                 :            : PROP_REQ [] = {
     284                 :            :   { "W1", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
     285                 :            :   { "W2", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
     286                 :            :   { "W3", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE },
     287                 :            :   { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
     288                 :            :   { "MSDispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" }, PROP_RNG_DIS },
     289                 :            :   { "MSModel", PROP_STR, { PROP_NO_VAL, "Hammerstad" }, PROP_RNG_MOD },
     290                 :            :   PROP_NO_PROP };
     291                 :            : PROP_OPT [] = {
     292                 :            :   { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
     293                 :            :   PROP_NO_PROP };
     294                 :            : struct define_t mstee::cirdef =
     295                 :            :   { "MTEE", 3, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };

Generated by: LCOV version 1.11