Qucs-core  0.0.19
mstee.cpp
Go to the documentation of this file.
00001 /*
00002  * mstee.cpp - microstrip t-junction class implementation
00003  *
00004  * Copyright (C) 2004, 2005, 2006 Stefan Jahn <stefan@lkcc.org>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  * $Id$
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <algorithm>
00030 
00031 #include "component.h"
00032 #include "substrate.h"
00033 #include "device.h"
00034 #include "msline.h"
00035 #include "mstee.h"
00036 
00037 using namespace qucs;
00038 using namespace qucs::device;
00039 
00040 mstee::mstee () : circuit (3) {
00041   lineA = lineB = line2 = NULL;
00042   type = CIR_MSTEE;
00043 }
00044 
00045 void mstee::initSP (void) {
00046   allocMatrixS ();
00047   initLines ();
00048   lineA->initSP ();
00049   lineB->initSP ();
00050   line2->initSP ();
00051 }
00052 
00053 void mstee::initNoiseSP (void) {
00054   allocMatrixN ();
00055   lineA->initNoiseSP ();
00056   lineB->initNoiseSP ();
00057   line2->initNoiseSP ();
00058 }
00059 
00060 void mstee::initLines (void) {
00061   lineA = splitMicrostrip (this, lineA, getNet (), "LineA", "NodeA", NODE_1);
00062   lineA->setProperty ("W", getPropertyDouble ("W1"));
00063   lineA->setProperty ("Temp", getPropertyDouble ("Temp"));
00064   lineA->setProperty ("Model", getPropertyString ("MSModel"));
00065   lineA->setProperty ("DispModel", getPropertyString ("MSDispModel"));
00066   lineA->setSubstrate (getSubstrate ());
00067 
00068   lineB = splitMicrostrip (this, lineB, getNet (), "LineB", "NodeB", NODE_2);
00069   lineB->setProperty ("W", getPropertyDouble ("W2"));
00070   lineB->setProperty ("Temp", getPropertyDouble ("Temp"));
00071   lineB->setProperty ("Model", getPropertyString ("MSModel"));
00072   lineB->setProperty ("DispModel", getPropertyString ("MSDispModel"));
00073   lineB->setSubstrate (getSubstrate ());
00074 
00075   line2 = splitMicrostrip (this, line2, getNet (), "Line2", "Node2", NODE_3);
00076   line2->setProperty ("W", getPropertyDouble ("W3"));
00077   line2->setProperty ("Temp", getPropertyDouble ("Temp"));
00078   line2->setProperty ("Model", getPropertyString ("MSModel"));
00079   line2->setProperty ("DispModel", getPropertyString ("MSDispModel"));
00080   line2->setSubstrate (getSubstrate ());
00081 }
00082 
00083 void mstee::calcSP (nr_double_t frequency) {
00084   calcPropagation (frequency);
00085 
00086   lineA->setProperty ("L", La);
00087   lineB->setProperty ("L", Lb);
00088   line2->setProperty ("L", L2);
00089   lineA->calcSP (frequency);
00090   lineB->calcSP (frequency);
00091   line2->calcSP (frequency);
00092 
00093   // calculate S-parameters
00094   nr_complex_t n1 = Ta2 * nr_complex_t (1 + 1 / Tb2, Bt * z0);
00095   nr_complex_t n2 = Tb2 * nr_complex_t (1 + 1 / Ta2, Bt * z0);
00096   nr_complex_t n3 = nr_complex_t (1 / Ta2 + 1 / Tb2, Bt * z0);
00097   setS (NODE_1, NODE_1, (1.0 - n1) / (1.0 + n1));
00098   setS (NODE_2, NODE_2, (1.0 - n2) / (1.0 + n2));
00099   setS (NODE_3, NODE_3, (1.0 - n3) / (1.0 + n3));
00100   setS (NODE_1, NODE_3, 2.0 * std::sqrt (Ta2) / (1.0 + n1));
00101   setS (NODE_3, NODE_1, 2.0 * std::sqrt (Ta2) / (1.0 + n1));
00102   setS (NODE_2, NODE_3, 2.0 * std::sqrt (Tb2) / (1.0 + n2));
00103   setS (NODE_3, NODE_2, 2.0 * std::sqrt (Tb2) / (1.0 + n2));
00104   setS (NODE_1, NODE_2, 2.0 / (std::sqrt (Ta2 * Tb2) * nr_complex_t (1, Bt * z0) +
00105                                std::sqrt (Ta2 / Tb2) + std::sqrt (Tb2 / Ta2)));
00106   setS (NODE_2, NODE_1, 2.0 / (std::sqrt (Ta2 * Tb2) * nr_complex_t (1, Bt * z0) +
00107                                std::sqrt (Ta2 / Tb2) + std::sqrt (Tb2 / Ta2)));
00108 }
00109 
00110 void mstee::calcPropagation (nr_double_t f) {
00111 
00112   const char * SModel = getPropertyString ("MSModel");
00113   const char * DModel = getPropertyString ("MSDispModel");
00114   substrate * subst = getSubstrate ();
00115   nr_double_t er = subst->getPropertyDouble ("er");
00116   nr_double_t h  = subst->getPropertyDouble ("h");
00117   nr_double_t t  = subst->getPropertyDouble ("t");
00118   nr_double_t Wa = getPropertyDouble ("W1");
00119   nr_double_t Wb = getPropertyDouble ("W2");
00120   nr_double_t W2 = getPropertyDouble ("W3");
00121 
00122   nr_double_t Zla, Zlb, Zl2, Era, Erb, Er2;
00123 
00124   // computation of impedances and effective dielectric constants
00125   nr_double_t ZlEff, ErEff, WEff;
00126   msline::analyseQuasiStatic (Wa, h, t, er, SModel, ZlEff, ErEff, WEff);
00127   msline::analyseDispersion  (Wa, h, er, ZlEff, ErEff, f, DModel,
00128                               Zla, Era);
00129   msline::analyseQuasiStatic (Wb, h, t, er, SModel, ZlEff, ErEff, WEff);
00130   msline::analyseDispersion  (Wb, h, er, ZlEff, ErEff, f, DModel,
00131                               Zlb, Erb);
00132   msline::analyseQuasiStatic (W2, h, t, er, SModel, ZlEff, ErEff, WEff);
00133   msline::analyseDispersion  (W2, h, er, ZlEff, ErEff, f, DModel,
00134                               Zl2, Er2);
00135 
00136   // local variables
00137   nr_double_t Da, Db, D2, fpa, fpb, lda, ldb, da, db, d2, r, q;
00138 
00139   // equivalent parallel plate line widths
00140   Da = Z0 / Zla * h / std::sqrt (Era);
00141   Db = Z0 / Zlb * h / std::sqrt (Erb);
00142   D2 = Z0 / Zl2 * h / std::sqrt (Er2);
00143 
00144   // first higher order mode cut-off frequencies
00145   fpa = 0.4e6 * Zla / h;
00146   fpb = 0.4e6 * Zlb / h;
00147 
00148   // effective wavelengths of quasi-TEM mode
00149   lda = C0 / std::sqrt (Era) / f;
00150   ldb = C0 / std::sqrt (Erb) / f;
00151 
00152   // main arm displacements
00153   da = 0.055 * D2 * Zla / Zl2 * (1 - 2 * Zla / Zl2 * sqr (f / fpa));
00154   db = 0.055 * D2 * Zlb / Zl2 * (1 - 2 * Zlb / Zl2 * sqr (f / fpb));
00155 
00156   // length of lines in the main arms
00157   La = 0.5 * W2 - da;
00158   Lb = 0.5 * W2 - db;
00159 
00160   // displacement and length of line in the side arm
00161   r = std::sqrt (Zla * Zlb) / Zl2;
00162   q = sqr (f) / fpa / fpb;
00163   d2 = std::sqrt (Da * Db) * (0.5 - r * (0.05 + 0.7 * std::exp (-1.6 * r) +
00164                                     0.25 * r * q - 0.17 * std::log (r)));
00165   L2 = 0.5 * std::max (Wa, Wb) - d2;
00166 
00167   // turn ratio of transformers in main arms
00168   Ta2 = 1 - pi * sqr (f / fpa) *
00169         (sqr (Zla / Zl2) / 12 + sqr (0.5 - d2 / Da));
00170   Tb2 = 1 - pi * sqr (f / fpb) *
00171         (sqr (Zlb / Zl2) / 12 + sqr (0.5 - d2 / Db));
00172   Ta2 = std::max (Ta2, NR_TINY);
00173   Tb2 = std::max (Tb2, NR_TINY);
00174 
00175   // shunt susceptance
00176   Bt = 5.5 * std::sqrt (Da * Db / lda / ldb) * (er + 2) / er /
00177     Zl2 / std::sqrt (Ta2 * Tb2) * std::sqrt (da * db) / D2 *
00178     (1 + 0.9 * std::log (r) + 4.5 * r * q - 4.4 * std::exp (-1.3 * r) -
00179      20 * sqr (Zl2 / Z0));
00180 }
00181 
00182 /* This function can be used to create an extra microstrip circuit.
00183    If the 'line' argument is NULL then the new circuit is created, the
00184    nodes get re-arranged and it is inserted into the given
00185    netlist. The given arguments can be explained as follows.
00186    base:     calling circuit (this)
00187    line:     additional microstrip line circuit (can be NULL)
00188    subnet:   the netlist object
00189    c:        name of the additional circuit
00190    n:        name of the inserted (internal) node
00191    internal: number of new internal node (the original external node) */
00192 circuit * splitMicrostrip (circuit * base, circuit * line, net * subnet,
00193                            const char * c, const char * n, int internal) {
00194   if (line == NULL) {
00195     line = new msline ();
00196     const std::string &name = circuit::createInternal (c, base->getName ());
00197     const std::string &node = circuit::createInternal (n, base->getName ());
00198     line->setName (name);
00199     line->setNode (0, base->getNode(internal)->getName ());
00200     line->setNode (1, node, 1);
00201     subnet->insertCircuit (line);
00202   }
00203   base->setNode (internal, line->getNode(1)->getName (), 1);
00204   return line;
00205 }
00206 
00207 /* This function is the counterpart of the above routine.  It removes
00208    the microstrip circuit from the netlist and re-assigns the original
00209    node. */
00210 void disableMicrostrip (circuit * base, circuit * line, net * subnet,
00211                         int internal) {
00212   if (line != NULL) {
00213     subnet->removeCircuit (line, 0);
00214     base->setNode (internal, line->getNode(1)->getName (), 0);
00215   }
00216 }
00217 
00218 void mstee::initDC (void) {
00219   setVoltageSources (2);
00220   setInternalVoltageSource (1);
00221   allocMatrixMNA ();
00222   voltageSource (VSRC_1, NODE_1, NODE_2);
00223   voltageSource (VSRC_2, NODE_1, NODE_3);
00224   if (deviceEnabled (lineA)) {
00225     disableMicrostrip (this, lineA, getNet (), NODE_1);
00226   }
00227   if (deviceEnabled (lineB)) {
00228     disableMicrostrip (this, lineB, getNet (), NODE_2);
00229   }
00230   if (deviceEnabled (line2)) {
00231     disableMicrostrip (this, line2, getNet (), NODE_3);
00232   }
00233 }
00234 
00235 void mstee::initAC (void) {
00236   setVoltageSources (3);
00237   setInternalVoltageSource (1);
00238   allocMatrixMNA ();
00239   setB (NODE_1, VSRC_1, +1); setB (NODE_2, VSRC_2, +1);
00240   setB (NODE_3, VSRC_3, +1);
00241   setC (VSRC_1, NODE_1, -1); setC (VSRC_2, NODE_2, -1);
00242   setC (VSRC_3, NODE_3, -1);
00243   initLines ();
00244   lineA->initAC ();
00245   lineB->initAC ();
00246   line2->initAC ();
00247 }
00248 
00249 void mstee::initNoiseAC (void) {
00250   allocMatrixN (getVoltageSources ());
00251   lineA->initNoiseAC ();
00252   lineB->initNoiseAC ();
00253   line2->initNoiseAC ();
00254 }
00255 
00256 void mstee::calcAC (nr_double_t frequency) {
00257   calcPropagation (frequency);
00258 
00259   lineA->setProperty ("L", La);
00260   lineB->setProperty ("L", Lb);
00261   line2->setProperty ("L", L2);
00262   lineA->calcAC (frequency);
00263   lineB->calcAC (frequency);
00264   line2->calcAC (frequency);
00265 
00266   // calculate Z-parameters
00267   setD (VSRC_1, VSRC_1, nr_complex_t (0, -1 / Ta2 / Bt));
00268   setD (VSRC_1, VSRC_2, nr_complex_t (0, -1 / std::sqrt (Ta2 * Tb2) / Bt));
00269   setD (VSRC_1, VSRC_3, nr_complex_t (0, -1 / std::sqrt (Ta2) / Bt));
00270   setD (VSRC_2, VSRC_1, nr_complex_t (0, -1 / std::sqrt (Ta2 * Tb2) / Bt));
00271   setD (VSRC_2, VSRC_2, nr_complex_t (0, -1 / Tb2 / Bt));
00272   setD (VSRC_2, VSRC_3, nr_complex_t (0, -1 / std::sqrt (Tb2) / Bt));
00273   setD (VSRC_3, VSRC_1, nr_complex_t (0, -1 / std::sqrt (Ta2) / Bt));
00274   setD (VSRC_3, VSRC_2, nr_complex_t (0, -1 / std::sqrt (Tb2) / Bt));
00275   setD (VSRC_3, VSRC_3, nr_complex_t (0, -1 / Bt));
00276 }
00277 
00278 void mstee::initTR (void) {
00279   initDC ();
00280 }
00281 
00282 // properties
00283 PROP_REQ [] = {
00284   { "W1", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
00285   { "W2", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
00286   { "W3", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE },
00287   { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
00288   { "MSDispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" },     PROP_RNG_DIS },
00289   { "MSModel", PROP_STR, { PROP_NO_VAL, "Hammerstad" }, PROP_RNG_MOD },
00290   PROP_NO_PROP };
00291 PROP_OPT [] = {
00292   { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
00293   PROP_NO_PROP };
00294 struct define_t mstee::cirdef =
00295   { "MTEE", 3, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };