Branch data Line data Source code
1 : : /*
2 : : * mscross.cpp - microstrip cross-junction class implementation
3 : : *
4 : : * Copyright (C) 2004, 2007, 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 : : #include "mscross.h"
33 : :
34 : : using namespace qucs;
35 : :
36 : 0 : mscross::mscross () : circuit (6) {
37 : 0 : type = CIR_MSCROSS;
38 : 0 : }
39 : :
40 : 0 : void mscross::initModel (void) {
41 : 0 : setNode (NODE_5, createInternal (getName (), "i13"));
42 : 0 : setNode (NODE_6, createInternal (getName (), "i24"));
43 : 0 : }
44 : :
45 : 0 : void mscross::initSP (void) {
46 : 0 : initModel ();
47 : 0 : allocMatrixS ();
48 : 0 : }
49 : :
50 : 0 : void mscross::calcSP (nr_double_t frequency) {
51 [ # # ][ # # ]: 0 : setMatrixS (ytos (calcMatrixY (frequency)));
[ # # ][ # # ]
[ # # ]
52 : 0 : }
53 : :
54 : 0 : void mscross::initDC (void) {
55 : 0 : initModel ();
56 : 0 : setVoltageSources (5);
57 : 0 : allocMatrixMNA ();
58 : 0 : voltageSource (VSRC_1, NODE_1, NODE_5);
59 : 0 : voltageSource (VSRC_2, NODE_3, NODE_5);
60 : 0 : voltageSource (VSRC_3, NODE_2, NODE_6);
61 : 0 : voltageSource (VSRC_4, NODE_4, NODE_6);
62 : 0 : voltageSource (VSRC_5, NODE_5, NODE_6);
63 : 0 : }
64 : :
65 : 0 : void mscross::initAC (void) {
66 : 0 : initModel ();
67 : 0 : setVoltageSources (0);
68 : 0 : allocMatrixMNA ();
69 : 0 : }
70 : :
71 : 0 : void mscross::calcAC (nr_double_t frequency) {
72 [ # # ]: 0 : setMatrixY (calcMatrixY (frequency));
73 : 0 : }
74 : :
75 : 0 : nr_double_t mscross::capCorrection (nr_double_t W, nr_double_t f) {
76 [ # # ]: 0 : substrate * subst = getSubstrate ();
77 [ # # ]: 0 : nr_double_t er = subst->getPropertyDouble ("er");
78 [ # # ]: 0 : nr_double_t h = subst->getPropertyDouble ("h");
79 [ # # ]: 0 : nr_double_t t = subst->getPropertyDouble ("t");
80 [ # # ]: 0 : const char * SModel = getPropertyString ("MSModel");
81 [ # # ]: 0 : const char * DModel = getPropertyString ("MSDispModel");
82 : : nr_double_t Zl1, Er1, Zl2, Er2;
83 : : nr_double_t ZlEff, ErEff, WEff;
84 [ # # ]: 0 : msline::analyseQuasiStatic (W, h, t, 9.9, SModel, ZlEff, ErEff, WEff);
85 : : msline::analyseDispersion (W, h, 9.9, ZlEff, ErEff, f, DModel,
86 [ # # ]: 0 : Zl1, Er1);
87 [ # # ]: 0 : msline::analyseQuasiStatic (W, h, t, er, SModel, ZlEff, ErEff, WEff);
88 : : msline::analyseDispersion (W, h, er, ZlEff, ErEff, f, DModel,
89 [ # # ]: 0 : Zl2, Er2);
90 [ # # ]: 0 : return Zl1 / Zl2 * qucs::sqrt (Er2 / Er1);
91 : : }
92 : :
93 : 0 : nr_double_t mscross::calcCap (nr_double_t W1, nr_double_t h, nr_double_t W2) {
94 : 0 : nr_double_t W1h = W1 / h;
95 : 0 : nr_double_t W2h = W2 / h;
96 : 0 : nr_double_t X = qucs::log10 (W1h) * (86.6 * W2h - 30.9 * qucs::sqrt (W2h) + 367) +
97 : 0 : cubic (W2h) + 74 * W2h + 130;
98 : 0 : return 1e-12 * W1 * (0.25 * X * qucs::pow (W1h, -1.0 / 3.0) - 60 +
99 : 0 : 1 / W2h / 2 - 0.375 * W1h * (1 - W2h));
100 : : }
101 : :
102 : 0 : nr_double_t mscross::calcInd (nr_double_t W1, nr_double_t h, nr_double_t W2) {
103 : 0 : nr_double_t W1h = W1 / h;
104 : 0 : nr_double_t W2h = W2 / h;
105 : 0 : nr_double_t Y = 165.6 * W2h + 31.2 * qucs::sqrt (W2h) - 11.8 * sqr (W2h);
106 : 0 : return 1e-9 * h * (Y * W1h - 32 * W2h + 3) * qucs::pow (W1h, -1.5);
107 : : }
108 : :
109 : 0 : matrix mscross::calcMatrixY (nr_double_t f) {
110 [ # # ]: 0 : nr_double_t W1 = getPropertyDouble ("W1");
111 [ # # ]: 0 : nr_double_t W2 = getPropertyDouble ("W2");
112 [ # # ]: 0 : nr_double_t W3 = getPropertyDouble ("W3");
113 [ # # ]: 0 : nr_double_t W4 = getPropertyDouble ("W4");
114 [ # # ]: 0 : substrate * subst = getSubstrate ();
115 [ # # ]: 0 : nr_double_t h = subst->getPropertyDouble ("h");
116 : 0 : nr_double_t W1h = (W1 + W3) / 2 / h;
117 : 0 : nr_double_t W2h = (W2 + W4) / 2 / h;
118 : : nr_double_t C1, C2, C3, C4, L1, L2, L3, L4, L5;
119 : :
120 : : // apply asymmetric modifications of original model
121 [ # # ]: 0 : C1 = calcCap (W1, h, (W2 + W4) / 2);
122 [ # # ]: 0 : C2 = calcCap (W2, h, (W1 + W3) / 2);
123 [ # # ]: 0 : C3 = calcCap (W3, h, (W4 + W2) / 2);
124 [ # # ]: 0 : C4 = calcCap (W4, h, (W3 + W1) / 2);
125 : :
126 [ # # ]: 0 : L1 = calcInd (W1, h, (W2 + W4) / 2);
127 [ # # ]: 0 : L2 = calcInd (W2, h, (W1 + W3) / 2);
128 [ # # ]: 0 : L3 = calcInd (W3, h, (W4 + W2) / 2);
129 [ # # ]: 0 : L4 = calcInd (W4, h, (W3 + W1) / 2);
130 : :
131 [ # # ]: 0 : L5 = 1e-9 * h * (5 * W2h * qucs::cos (M_PI / 2 * (1.5 - W1h)) -
132 : 0 : (1 + 7 / W1h ) / W2h - 337.5);
133 : :
134 : : // center inductance correction
135 : 0 : L5 = L5 * 0.8;
136 : :
137 : : // capacitance corrections
138 [ # # ]: 0 : C1 = C1 * capCorrection (W1, f);
139 [ # # ]: 0 : C2 = C2 * capCorrection (W2, f);
140 [ # # ]: 0 : C3 = C3 * capCorrection (W3, f);
141 [ # # ]: 0 : C4 = C4 * capCorrection (W4, f);
142 : :
143 : : // compute admittance matrix
144 : 0 : nr_double_t o = 2 * M_PI * f;
145 : 0 : nr_complex_t yc1 = nr_complex_t (0, o * C1);
146 : 0 : nr_complex_t yc2 = nr_complex_t (0, o * C2);
147 : 0 : nr_complex_t yc3 = nr_complex_t (0, o * C3);
148 : 0 : nr_complex_t yc4 = nr_complex_t (0, o * C4);
149 [ # # ]: 0 : nr_complex_t yl1 = 1.0 / nr_complex_t (0, o * L1);
150 [ # # ]: 0 : nr_complex_t yl2 = 1.0 / nr_complex_t (0, o * L2);
151 [ # # ]: 0 : nr_complex_t yl3 = 1.0 / nr_complex_t (0, o * L3);
152 [ # # ]: 0 : nr_complex_t yl4 = 1.0 / nr_complex_t (0, o * L4);
153 [ # # ]: 0 : nr_complex_t yl5 = 1.0 / nr_complex_t (0, o * L5);
154 [ # # ]: 0 : matrix Y (6);
155 [ # # ][ # # ]: 0 : Y.set (NODE_1, NODE_1, yl1 + yc1);
156 [ # # ][ # # ]: 0 : Y.set (NODE_2, NODE_2, yl2 + yc2);
157 [ # # ][ # # ]: 0 : Y.set (NODE_3, NODE_3, yl3 + yc3);
158 [ # # ][ # # ]: 0 : Y.set (NODE_4, NODE_4, yl4 + yc4);
159 [ # # ][ # # ]: 0 : Y.set (NODE_1, NODE_5, -yl1); Y.set (NODE_5, NODE_1, -yl1);
160 [ # # ][ # # ]: 0 : Y.set (NODE_3, NODE_5, -yl3); Y.set (NODE_5, NODE_3, -yl3);
161 [ # # ][ # # ]: 0 : Y.set (NODE_2, NODE_6, -yl2); Y.set (NODE_6, NODE_2, -yl2);
162 [ # # ][ # # ]: 0 : Y.set (NODE_4, NODE_6, -yl4); Y.set (NODE_6, NODE_4, -yl4);
163 [ # # ][ # # ]: 0 : Y.set (NODE_5, NODE_6, -yl5); Y.set (NODE_6, NODE_5, -yl5);
164 [ # # ][ # # ]: 0 : Y.set (NODE_5, NODE_5, yl1 + yl3 + yl5);
[ # # ]
165 [ # # ][ # # ]: 0 : Y.set (NODE_6, NODE_6, yl2 + yl4 + yl5);
[ # # ]
166 : 0 : return Y;
167 : : }
168 : :
169 : 0 : void mscross::initTR (void) {
170 : 0 : initDC ();
171 : 0 : }
172 : :
173 : : // properties
174 : : PROP_REQ [] = {
175 : : { "W1", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
176 : : { "W2", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE },
177 : : { "W3", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
178 : : { "W4", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE },
179 : : { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
180 : : { "MSDispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" }, PROP_RNG_DIS },
181 : : { "MSModel", PROP_STR, { PROP_NO_VAL, "Hammerstad" }, PROP_RNG_MOD },
182 : : PROP_NO_PROP };
183 : : PROP_OPT [] = {
184 : : PROP_NO_PROP };
185 : : struct define_t mscross::cirdef =
186 : : { "MCROSS", 4, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
|