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