Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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$
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 mstee::mstee () : circuit (3) {
39  lineA = lineB = line2 = NULL;
40  type = CIR_MSTEE;
41 }
42 
43 void mstee::initSP (void) {
44  allocMatrixS ();
45  initLines ();
46  lineA->initSP ();
47  lineB->initSP ();
48  line2->initSP ();
49 }
50 
51 void mstee::initNoiseSP (void) {
52  allocMatrixN ();
53  lineA->initNoiseSP ();
54  lineB->initNoiseSP ();
55  line2->initNoiseSP ();
56 }
57 
58 void mstee::initLines (void) {
59  lineA = splitMicrostrip (this, lineA, getNet (), "LineA", "NodeA", NODE_1);
60  lineA->setProperty ("W", getPropertyDouble ("W1"));
61  lineA->setProperty ("Temp", getPropertyDouble ("Temp"));
62  lineA->setProperty ("Model", getPropertyString ("MSModel"));
63  lineA->setProperty ("DispModel", getPropertyString ("MSDispModel"));
65 
66  lineB = splitMicrostrip (this, lineB, getNet (), "LineB", "NodeB", NODE_2);
67  lineB->setProperty ("W", getPropertyDouble ("W2"));
68  lineB->setProperty ("Temp", getPropertyDouble ("Temp"));
69  lineB->setProperty ("Model", getPropertyString ("MSModel"));
70  lineB->setProperty ("DispModel", getPropertyString ("MSDispModel"));
72 
73  line2 = splitMicrostrip (this, line2, getNet (), "Line2", "Node2", NODE_3);
74  line2->setProperty ("W", getPropertyDouble ("W3"));
75  line2->setProperty ("Temp", getPropertyDouble ("Temp"));
76  line2->setProperty ("Model", getPropertyString ("MSModel"));
77  line2->setProperty ("DispModel", getPropertyString ("MSDispModel"));
79 }
80 
81 void mstee::calcSP (nr_double_t frequency) {
82  calcPropagation (frequency);
83 
84  lineA->setProperty ("L", La);
85  lineB->setProperty ("L", Lb);
86  line2->setProperty ("L", L2);
87  lineA->calcSP (frequency);
88  lineB->calcSP (frequency);
89  line2->calcSP (frequency);
90 
91  // calculate S-parameters
92  nr_complex_t n1 = Ta2 * nr_complex_t (1 + 1 / Tb2, Bt * z0);
93  nr_complex_t n2 = Tb2 * nr_complex_t (1 + 1 / Ta2, Bt * z0);
94  nr_complex_t n3 = nr_complex_t (1 / Ta2 + 1 / Tb2, Bt * z0);
95  setS (NODE_1, NODE_1, (1.0 - n1) / (1.0 + n1));
96  setS (NODE_2, NODE_2, (1.0 - n2) / (1.0 + n2));
97  setS (NODE_3, NODE_3, (1.0 - n3) / (1.0 + n3));
98  setS (NODE_1, NODE_3, 2.0 * std::sqrt (Ta2) / (1.0 + n1));
99  setS (NODE_3, NODE_1, 2.0 * std::sqrt (Ta2) / (1.0 + n1));
100  setS (NODE_2, NODE_3, 2.0 * std::sqrt (Tb2) / (1.0 + n2));
101  setS (NODE_3, NODE_2, 2.0 * std::sqrt (Tb2) / (1.0 + n2));
102  setS (NODE_1, NODE_2, 2.0 / (std::sqrt (Ta2 * Tb2) * nr_complex_t (1, Bt * z0) +
103  std::sqrt (Ta2 / Tb2) + std::sqrt (Tb2 / Ta2)));
104  setS (NODE_2, NODE_1, 2.0 / (std::sqrt (Ta2 * Tb2) * nr_complex_t (1, Bt * z0) +
105  std::sqrt (Ta2 / Tb2) + std::sqrt (Tb2 / Ta2)));
106 }
107 
108 void mstee::calcPropagation (nr_double_t f) {
109 
110  char * SModel = getPropertyString ("MSModel");
111  char * DModel = getPropertyString ("MSDispModel");
113  nr_double_t er = subst->getPropertyDouble ("er");
114  nr_double_t h = subst->getPropertyDouble ("h");
115  nr_double_t t = subst->getPropertyDouble ("t");
116  nr_double_t Wa = getPropertyDouble ("W1");
117  nr_double_t Wb = getPropertyDouble ("W2");
118  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  msline::analyseQuasiStatic (Wa, h, t, er, SModel, ZlEff, ErEff, WEff);
125  msline::analyseDispersion (Wa, h, er, ZlEff, ErEff, f, DModel,
126  Zla, Era);
127  msline::analyseQuasiStatic (Wb, h, t, er, SModel, ZlEff, ErEff, WEff);
128  msline::analyseDispersion (Wb, h, er, ZlEff, ErEff, f, DModel,
129  Zlb, Erb);
130  msline::analyseQuasiStatic (W2, h, t, er, SModel, ZlEff, ErEff, WEff);
131  msline::analyseDispersion (W2, h, er, ZlEff, ErEff, f, DModel,
132  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  Da = Z0 / Zla * h / std::sqrt (Era);
139  Db = Z0 / Zlb * h / std::sqrt (Erb);
140  D2 = Z0 / Zl2 * h / std::sqrt (Er2);
141 
142  // first higher order mode cut-off frequencies
143  fpa = 0.4e6 * Zla / h;
144  fpb = 0.4e6 * Zlb / h;
145 
146  // effective wavelengths of quasi-TEM mode
147  lda = C0 / std::sqrt (Era) / f;
148  ldb = C0 / std::sqrt (Erb) / f;
149 
150  // main arm displacements
151  da = 0.055 * D2 * Zla / Zl2 * (1 - 2 * Zla / Zl2 * sqr (f / fpa));
152  db = 0.055 * D2 * Zlb / Zl2 * (1 - 2 * Zlb / Zl2 * sqr (f / fpb));
153 
154  // length of lines in the main arms
155  La = 0.5 * W2 - da;
156  Lb = 0.5 * W2 - db;
157 
158  // displacement and length of line in the side arm
159  r = std::sqrt (Zla * Zlb) / Zl2;
160  q = sqr (f) / fpa / fpb;
161  d2 = std::sqrt (Da * Db) * (0.5 - r * (0.05 + 0.7 * std::exp (-1.6 * r) +
162  0.25 * r * q - 0.17 * std::log (r)));
163  L2 = 0.5 * MAX (Wa, Wb) - d2;
164 
165  // turn ratio of transformers in main arms
166  Ta2 = 1 - M_PI * sqr (f / fpa) *
167  (sqr (Zla / Zl2) / 12 + sqr (0.5 - d2 / Da));
168  Tb2 = 1 - M_PI * sqr (f / fpb) *
169  (sqr (Zlb / Zl2) / 12 + sqr (0.5 - d2 / Db));
170  Ta2 = MAX (Ta2, NR_TINY);
171  Tb2 = MAX (Tb2, NR_TINY);
172 
173  // shunt susceptance
174  Bt = 5.5 * std::sqrt (Da * Db / lda / ldb) * (er + 2) / er /
175  Zl2 / std::sqrt (Ta2 * Tb2) * std::sqrt (da * db) / D2 *
176  (1 + 0.9 * std::log (r) + 4.5 * r * q - 4.4 * std::exp (-1.3 * r) -
177  20 * sqr (Zl2 / Z0));
178 }
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 circuit * splitMicrostrip (circuit * base, circuit * line, net * subnet,
191  const char * c, const char * n, int internal) {
192  if (line == NULL) {
193  line = new msline ();
194  char * name = circuit::createInternal (c, base->getName ());
195  char * node = circuit::createInternal (n, base->getName ());
196  line->setName (name);
197  line->setNode (0, base->getNode(internal)->getName ());
198  line->setNode (1, node, 1);
199  subnet->insertCircuit (line);
200  free (name);
201  free (node);
202  }
203  base->setNode (internal, line->getNode(1)->getName (), 1);
204  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 void disableMicrostrip (circuit * base, circuit * line, net * subnet,
211  int internal) {
212  if (line != NULL) {
213  subnet->removeCircuit (line, 0);
214  base->setNode (internal, line->getNode(1)->getName (), 0);
215  }
216 }
217 
218 void mstee::initDC (void) {
219  setVoltageSources (2);
221  allocMatrixMNA ();
224  if (deviceEnabled (lineA)) {
225  disableMicrostrip (this, lineA, getNet (), NODE_1);
226  }
227  if (deviceEnabled (lineB)) {
228  disableMicrostrip (this, lineB, getNet (), NODE_2);
229  }
230  if (deviceEnabled (line2)) {
231  disableMicrostrip (this, line2, getNet (), NODE_3);
232  }
233 }
234 
235 void mstee::initAC (void) {
236  setVoltageSources (3);
238  allocMatrixMNA ();
239  setB (NODE_1, VSRC_1, +1); setB (NODE_2, VSRC_2, +1);
240  setB (NODE_3, VSRC_3, +1);
241  setC (VSRC_1, NODE_1, -1); setC (VSRC_2, NODE_2, -1);
242  setC (VSRC_3, NODE_3, -1);
243  initLines ();
244  lineA->initAC ();
245  lineB->initAC ();
246  line2->initAC ();
247 }
248 
249 void mstee::initNoiseAC (void) {
251  lineA->initNoiseAC ();
252  lineB->initNoiseAC ();
253  line2->initNoiseAC ();
254 }
255 
256 void mstee::calcAC (nr_double_t frequency) {
257  calcPropagation (frequency);
258 
259  lineA->setProperty ("L", La);
260  lineB->setProperty ("L", Lb);
261  line2->setProperty ("L", L2);
262  lineA->calcAC (frequency);
263  lineB->calcAC (frequency);
264  line2->calcAC (frequency);
265 
266  // calculate Z-parameters
267  setD (VSRC_1, VSRC_1, nr_complex_t (0, -1 / Ta2 / Bt));
268  setD (VSRC_1, VSRC_2, nr_complex_t (0, -1 / std::sqrt (Ta2 * Tb2) / Bt));
269  setD (VSRC_1, VSRC_3, nr_complex_t (0, -1 / std::sqrt (Ta2) / Bt));
270  setD (VSRC_2, VSRC_1, nr_complex_t (0, -1 / std::sqrt (Ta2 * Tb2) / Bt));
271  setD (VSRC_2, VSRC_2, nr_complex_t (0, -1 / Tb2 / Bt));
272  setD (VSRC_2, VSRC_3, nr_complex_t (0, -1 / std::sqrt (Tb2) / Bt));
273  setD (VSRC_3, VSRC_1, nr_complex_t (0, -1 / std::sqrt (Ta2) / Bt));
274  setD (VSRC_3, VSRC_2, nr_complex_t (0, -1 / std::sqrt (Tb2) / Bt));
275  setD (VSRC_3, VSRC_3, nr_complex_t (0, -1 / Bt));
276 }
277 
278 void mstee::initTR (void) {
279  initDC ();
280 }
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 =
void initNoiseAC(void)
Definition: mstee.cpp:249
void setProperty(const char *, char *)
Definition: object.cpp:104
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
#define PROP_POS_RANGE
Definition: netdefs.h:129
#define NODE_2
Definition: circuit.h:35
void initLines(void)
Definition: mstee.cpp:58
substrate * subst
Definition: circuit.h:350
#define PROP_DEF
Definition: netdefs.h:189
name
Definition: parse_mdl.y:352
void allocMatrixN(int sources=0)
Definition: circuit.cpp:260
nr_double_t getPropertyDouble(const char *)
Definition: object.cpp:176
void setD(int, int, nr_complex_t)
Definition: circuit.cpp:373
int deviceEnabled(circuit *c)
Definition: device.cpp:112
#define PROP_REAL
Definition: netdefs.h:174
substrate * getSubstrate(void)
Definition: circuit.cpp:332
void setInternalVoltageSource(bool i)
Definition: circuit.h:184
t
Definition: parse_vcd.y:290
nr_double_t La
Definition: mstee.h:55
#define PROP_NO_PROP
Definition: netdefs.h:122
void setVoltageSources(int)
Definition: circuit.cpp:607
PROP_REQ[]
Definition: mstee.cpp:283
#define K
Absolute 0 in centigrade.
Definition: constants.h:59
#define PROP_NO_RANGE
Definition: netdefs.h:126
void calcAC(nr_double_t)
Definition: mstee.cpp:256
#define PROP_NO_STR
Definition: netdefs.h:125
void setB(int, int, nr_complex_t)
Definition: circuit.cpp:349
void allocMatrixS(void)
Definition: circuit.cpp:251
void initNoiseSP(void)
Definition: mstee.cpp:51
#define PROP_RNG_MOD
Definition: netdefs.h:169
n
Definition: parse_citi.y:147
nr_double_t Ta2
Definition: mstee.h:55
#define PROP_LINEAR
Definition: netdefs.h:120
static const nr_double_t z0
Definition: circuit.h:320
h
Definition: parse_vcd.y:214
void initDC(void)
Definition: mstee.cpp:218
r
Definition: parse_mdl.y:515
circuit * splitMicrostrip(circuit *base, circuit *line, net *subnet, const char *c, const char *n, int internal)
Definition: mstee.cpp:190
void initAC(void)
Definition: mstee.cpp:235
#define PROP_RNG_DIS
Definition: netdefs.h:166
#define VSRC_1
Definition: circuit.h:40
n2
Definition: parse_zvr.y:187
int getVoltageSources(void)
Definition: circuit.cpp:602
nr_complex_t sqr(const nr_complex_t z)
Square of complex number.
Definition: complex.cpp:673
virtual void initNoiseAC(void)
Definition: circuit.h:118
virtual void initAC(void)
Definition: circuit.h:120
nr_complex_t sqrt(const nr_complex_t z)
Compute principal value of square root.
Definition: complex.cpp:271
nr_double_t Lb
Definition: mstee.h:55
#define PROP_COMPONENT
Definition: netdefs.h:116
free($1)
virtual void initSP(void)
placehoder for S-Parameter initialisation function
Definition: circuit.h:111
net * getNet(void)
Definition: circuit.h:173
#define VSRC_3
Definition: circuit.h:42
nr_double_t Bt
Definition: mstee.h:55
nr_double_t L2
Definition: mstee.h:55
#define NODE_3
Definition: circuit.h:36
Definition: mstee.cpp:294
#define M_PI
Archimedes' constant ( )
Definition: consts.h:47
PROP_OPT[]
Definition: mstee.cpp:291
nr_double_t Tb2
Definition: mstee.h:55
virtual void calcAC(nr_double_t)
Definition: circuit.h:121
friend qucs::circuit * splitMicrostrip(qucs::circuit *, qucs::circuit *, qucs::net *, const char *, const char *, int)
#define PROP_MIN_VAL(k)
Definition: netdefs.h:133
friend void disableMicrostrip(qucs::circuit *, qucs::circuit *, qucs::net *, int)
n1
Definition: parse_zvr.y:179
void allocMatrixMNA(void)
Definition: circuit.cpp:267
void initSP(void)
placehoder for S-Parameter initialisation function
Definition: mstee.cpp:43
virtual void calcSP(nr_double_t)
Definition: circuit.h:112
virtual void initNoiseSP(void)
Definition: circuit.h:116
#define PROP_STR
Definition: netdefs.h:175
#define NODE_1
Definition: circuit.h:34
#define C0
speed of light in vacuum ( )
Definition: constants.h:47
void voltageSource(int, int, int, nr_double_t value=0.0)
Definition: circuit.cpp:748
PROP_NO_SUBSTRATE
Definition: mstee.cpp:295
void disableMicrostrip(circuit *base, circuit *line, net *subnet, int internal)
Definition: mstee.cpp:210
static void analyseQuasiStatic(nr_double_t, nr_double_t, nr_double_t, nr_double_t, char *, nr_double_t &, nr_double_t &, nr_double_t &)
Definition: msline.cpp:115
nr_complex_t exp(const nr_complex_t z)
Compute complex exponential.
Definition: complex.cpp:205
qucs::circuit * lineB
Definition: mstee.h:57
void setS(int, int, nr_complex_t)
Definition: circuit.cpp:587
#define PROP_NO_VAL
Definition: netdefs.h:124
void setC(int, int, nr_complex_t)
Definition: circuit.cpp:361
static void analyseDispersion(nr_double_t, nr_double_t, nr_double_t, nr_double_t, nr_double_t, nr_double_t, char *, nr_double_t &, nr_double_t &)
Definition: msline.cpp:229
void calcPropagation(nr_double_t)
Definition: mstee.cpp:108
#define VSRC_2
Definition: circuit.h:41
qucs::circuit * lineA
Definition: mstee.h:56
char * getPropertyString(const char *)
Definition: object.cpp:159
void initTR(void)
Definition: mstee.cpp:278
void calcSP(nr_double_t)
Definition: mstee.cpp:81
nr_complex_t log(const nr_complex_t z)
Compute principal value of natural logarithm of z.
Definition: complex.cpp:215
#define Z0
Wave impedance in vacuum ( )
Definition: constants.h:53
qucs::circuit * line2
Definition: mstee.h:58
void setSubstrate(substrate *)
Definition: circuit.cpp:337
line
#define MAX(x, y)
Maximum of x and y.
Definition: constants.h:127