Qucs-core
0.0.19
|
00001 /* 00002 * mscross.cpp - microstrip cross-junction class implementation 00003 * 00004 * Copyright (C) 2004, 2007, 2008 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 "component.h" 00030 #include "substrate.h" 00031 #include "msline.h" 00032 #include "mscross.h" 00033 00034 using namespace qucs; 00035 00036 mscross::mscross () : circuit (6) { 00037 type = CIR_MSCROSS; 00038 } 00039 00040 void mscross::initModel (void) { 00041 setNode (NODE_5, createInternal (getName (), "i13")); 00042 setNode (NODE_6, createInternal (getName (), "i24")); 00043 } 00044 00045 void mscross::initSP (void) { 00046 initModel (); 00047 allocMatrixS (); 00048 } 00049 00050 void mscross::calcSP (nr_double_t frequency) { 00051 setMatrixS (ytos (calcMatrixY (frequency))); 00052 } 00053 00054 void mscross::initDC (void) { 00055 initModel (); 00056 setVoltageSources (5); 00057 allocMatrixMNA (); 00058 voltageSource (VSRC_1, NODE_1, NODE_5); 00059 voltageSource (VSRC_2, NODE_3, NODE_5); 00060 voltageSource (VSRC_3, NODE_2, NODE_6); 00061 voltageSource (VSRC_4, NODE_4, NODE_6); 00062 voltageSource (VSRC_5, NODE_5, NODE_6); 00063 } 00064 00065 void mscross::initAC (void) { 00066 initModel (); 00067 setVoltageSources (0); 00068 allocMatrixMNA (); 00069 } 00070 00071 void mscross::calcAC (nr_double_t frequency) { 00072 setMatrixY (calcMatrixY (frequency)); 00073 } 00074 00075 nr_double_t mscross::capCorrection (nr_double_t W, nr_double_t f) { 00076 substrate * subst = getSubstrate (); 00077 nr_double_t er = subst->getPropertyDouble ("er"); 00078 nr_double_t h = subst->getPropertyDouble ("h"); 00079 nr_double_t t = subst->getPropertyDouble ("t"); 00080 const char * SModel = getPropertyString ("MSModel"); 00081 const char * DModel = getPropertyString ("MSDispModel"); 00082 nr_double_t Zl1, Er1, Zl2, Er2; 00083 nr_double_t ZlEff, ErEff, WEff; 00084 msline::analyseQuasiStatic (W, h, t, 9.9, SModel, ZlEff, ErEff, WEff); 00085 msline::analyseDispersion (W, h, 9.9, ZlEff, ErEff, f, DModel, 00086 Zl1, Er1); 00087 msline::analyseQuasiStatic (W, h, t, er, SModel, ZlEff, ErEff, WEff); 00088 msline::analyseDispersion (W, h, er, ZlEff, ErEff, f, DModel, 00089 Zl2, Er2); 00090 return Zl1 / Zl2 * qucs::sqrt (Er2 / Er1); 00091 } 00092 00093 nr_double_t mscross::calcCap (nr_double_t W1, nr_double_t h, nr_double_t W2) { 00094 nr_double_t W1h = W1 / h; 00095 nr_double_t W2h = W2 / h; 00096 nr_double_t X = qucs::log10 (W1h) * (86.6 * W2h - 30.9 * qucs::sqrt (W2h) + 367) + 00097 cubic (W2h) + 74 * W2h + 130; 00098 return 1e-12 * W1 * (0.25 * X * qucs::pow (W1h, -1.0 / 3.0) - 60 + 00099 1 / W2h / 2 - 0.375 * W1h * (1 - W2h)); 00100 } 00101 00102 nr_double_t mscross::calcInd (nr_double_t W1, nr_double_t h, nr_double_t W2) { 00103 nr_double_t W1h = W1 / h; 00104 nr_double_t W2h = W2 / h; 00105 nr_double_t Y = 165.6 * W2h + 31.2 * qucs::sqrt (W2h) - 11.8 * sqr (W2h); 00106 return 1e-9 * h * (Y * W1h - 32 * W2h + 3) * qucs::pow (W1h, -1.5); 00107 } 00108 00109 matrix mscross::calcMatrixY (nr_double_t f) { 00110 nr_double_t W1 = getPropertyDouble ("W1"); 00111 nr_double_t W2 = getPropertyDouble ("W2"); 00112 nr_double_t W3 = getPropertyDouble ("W3"); 00113 nr_double_t W4 = getPropertyDouble ("W4"); 00114 substrate * subst = getSubstrate (); 00115 nr_double_t h = subst->getPropertyDouble ("h"); 00116 nr_double_t W1h = (W1 + W3) / 2 / h; 00117 nr_double_t W2h = (W2 + W4) / 2 / h; 00118 nr_double_t C1, C2, C3, C4, L1, L2, L3, L4, L5; 00119 00120 // apply asymmetric modifications of original model 00121 C1 = calcCap (W1, h, (W2 + W4) / 2); 00122 C2 = calcCap (W2, h, (W1 + W3) / 2); 00123 C3 = calcCap (W3, h, (W4 + W2) / 2); 00124 C4 = calcCap (W4, h, (W3 + W1) / 2); 00125 00126 L1 = calcInd (W1, h, (W2 + W4) / 2); 00127 L2 = calcInd (W2, h, (W1 + W3) / 2); 00128 L3 = calcInd (W3, h, (W4 + W2) / 2); 00129 L4 = calcInd (W4, h, (W3 + W1) / 2); 00130 00131 L5 = 1e-9 * h * (5 * W2h * qucs::cos (pi / 2 * (1.5 - W1h)) - 00132 (1 + 7 / W1h ) / W2h - 337.5); 00133 00134 // center inductance correction 00135 L5 = L5 * 0.8; 00136 00137 // capacitance corrections 00138 C1 = C1 * capCorrection (W1, f); 00139 C2 = C2 * capCorrection (W2, f); 00140 C3 = C3 * capCorrection (W3, f); 00141 C4 = C4 * capCorrection (W4, f); 00142 00143 // compute admittance matrix 00144 nr_double_t o = 2 * pi * f; 00145 nr_complex_t yc1 = nr_complex_t (0, o * C1); 00146 nr_complex_t yc2 = nr_complex_t (0, o * C2); 00147 nr_complex_t yc3 = nr_complex_t (0, o * C3); 00148 nr_complex_t yc4 = nr_complex_t (0, o * C4); 00149 nr_complex_t yl1 = 1.0 / nr_complex_t (0, o * L1); 00150 nr_complex_t yl2 = 1.0 / nr_complex_t (0, o * L2); 00151 nr_complex_t yl3 = 1.0 / nr_complex_t (0, o * L3); 00152 nr_complex_t yl4 = 1.0 / nr_complex_t (0, o * L4); 00153 nr_complex_t yl5 = 1.0 / nr_complex_t (0, o * L5); 00154 matrix Y (6); 00155 Y.set (NODE_1, NODE_1, yl1 + yc1); 00156 Y.set (NODE_2, NODE_2, yl2 + yc2); 00157 Y.set (NODE_3, NODE_3, yl3 + yc3); 00158 Y.set (NODE_4, NODE_4, yl4 + yc4); 00159 Y.set (NODE_1, NODE_5, -yl1); Y.set (NODE_5, NODE_1, -yl1); 00160 Y.set (NODE_3, NODE_5, -yl3); Y.set (NODE_5, NODE_3, -yl3); 00161 Y.set (NODE_2, NODE_6, -yl2); Y.set (NODE_6, NODE_2, -yl2); 00162 Y.set (NODE_4, NODE_6, -yl4); Y.set (NODE_6, NODE_4, -yl4); 00163 Y.set (NODE_5, NODE_6, -yl5); Y.set (NODE_6, NODE_5, -yl5); 00164 Y.set (NODE_5, NODE_5, yl1 + yl3 + yl5); 00165 Y.set (NODE_6, NODE_6, yl2 + yl4 + yl5); 00166 return Y; 00167 } 00168 00169 void mscross::initTR (void) { 00170 initDC (); 00171 } 00172 00173 // properties 00174 PROP_REQ [] = { 00175 { "W1", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00176 { "W2", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00177 { "W3", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00178 { "W4", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00179 { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE }, 00180 { "MSDispModel", PROP_STR, { PROP_NO_VAL, "Kirschning" }, PROP_RNG_DIS }, 00181 { "MSModel", PROP_STR, { PROP_NO_VAL, "Hammerstad" }, PROP_RNG_MOD }, 00182 PROP_NO_PROP }; 00183 PROP_OPT [] = { 00184 PROP_NO_PROP }; 00185 struct define_t mscross::cirdef = 00186 { "MCROSS", 4, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };