Qucs-core
0.0.19
|
00001 /* 00002 * cpwstep.cpp - coplanar waveguide step class implementation 00003 * 00004 * Copyright (C) 2005, 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 "cpwline.h" 00032 #include "cpwstep.h" 00033 00034 using namespace qucs; 00035 00036 cpwstep::cpwstep () : circuit (2) { 00037 type = CIR_CPWSTEP; 00038 } 00039 00040 // Returns the coplanar step capacitances per unit length. 00041 void cpwstep::calcCends (nr_double_t frequency, 00042 nr_double_t& C1, nr_double_t& C2) { 00043 00044 // get properties of substrate and coplanar step 00045 nr_double_t W1 = getPropertyDouble ("W1"); 00046 nr_double_t W2 = getPropertyDouble ("W2"); 00047 nr_double_t s = getPropertyDouble ("S"); 00048 nr_double_t s1 = (s - W1) / 2; 00049 nr_double_t s2 = (s - W2) / 2; 00050 substrate * subst = getSubstrate (); 00051 nr_double_t er = subst->getPropertyDouble ("er"); 00052 nr_double_t h = subst->getPropertyDouble ("h"); 00053 nr_double_t t = subst->getPropertyDouble ("t"); 00054 int backMetal = !strcmp (getPropertyString ("Backside"), "Metal"); 00055 00056 nr_double_t ZlEff, ErEff, ZlEffFreq, ErEffFreq; 00057 cpwline::analyseQuasiStatic (W1, s1, h, t, er, backMetal, ZlEff, ErEff); 00058 cpwline::analyseDispersion (W1, s1, h, er, ZlEff, ErEff, frequency, 00059 ZlEffFreq, ErEffFreq); 00060 C1 = ErEffFreq / C0 / ZlEffFreq; 00061 cpwline::analyseQuasiStatic (W2, s2, h, t, er, backMetal, ZlEff, ErEff); 00062 cpwline::analyseDispersion (W2, s2, h, er, ZlEff, ErEff, frequency, 00063 ZlEffFreq, ErEffFreq); 00064 C2 = ErEffFreq / C0 / ZlEffFreq; 00065 } 00066 00067 void cpwstep::initSP (void) { 00068 allocMatrixS (); 00069 checkProperties (); 00070 } 00071 00072 void cpwstep::calcSP (nr_double_t frequency) { 00073 nr_complex_t z = 2.0 / calcY (frequency) / z0; 00074 nr_complex_t s11 = -1.0 / (z + 1.0); 00075 nr_complex_t s21 = +z / (z + 1.0); 00076 setS (NODE_1, NODE_1, s11); 00077 setS (NODE_2, NODE_2, s11); 00078 setS (NODE_1, NODE_2, s21); 00079 setS (NODE_2, NODE_1, s21); 00080 } 00081 00082 void cpwstep::checkProperties (void) { 00083 nr_double_t W1 = getPropertyDouble ("W1"); 00084 nr_double_t W2 = getPropertyDouble ("W2"); 00085 nr_double_t s = getPropertyDouble ("S"); 00086 if (W1 == W2) { 00087 logprint (LOG_ERROR, "ERROR: Strip widths of step discontinuity do not " 00088 "differ\n"); 00089 } 00090 if (W1 >= s || W2 >= s) { 00091 logprint (LOG_ERROR, "ERROR: Strip widths of step discontinuity larger " 00092 "than groundplane gap\n"); 00093 } 00094 substrate * subst = getSubstrate (); 00095 nr_double_t er = subst->getPropertyDouble ("er"); 00096 if (er < 2 || er > 14) { 00097 logprint (LOG_ERROR, "WARNING: Model for coplanar step valid for " 00098 "2 < er < 14 (er = %g)\n", er); 00099 } 00100 } 00101 00102 nr_complex_t cpwstep::calcY (nr_double_t frequency) { 00103 nr_double_t W1 = getPropertyDouble ("W1"); 00104 nr_double_t W2 = getPropertyDouble ("W2"); 00105 nr_double_t s = getPropertyDouble ("S"); 00106 nr_double_t s1 = (s - W1) / 2; 00107 nr_double_t s2 = (s - W2) / 2; 00108 nr_double_t a, c, c1, c2, x1, x2; 00109 nr_double_t o = 2 * pi * frequency; 00110 calcCends (frequency, c1, c2); 00111 x1 = c1 * s1; 00112 x2 = c2 * s2; 00113 a = s1 > s2 ? s2 / s1 : s1 / s2; 00114 c = one_over_pi * ((a * a + 1) / a * std::log ((1 + a) / (1 - a)) - 00115 2 * std::log (4 * a / (1 - a * a))); 00116 c = c * (x1 + x2) / 2; 00117 return nr_complex_t (0, c * o); 00118 } 00119 00120 void cpwstep::initDC (void) { 00121 setVoltageSources (1); 00122 setInternalVoltageSource (true); 00123 allocMatrixMNA (); 00124 voltageSource (VSRC_1, NODE_1, NODE_2); 00125 } 00126 00127 void cpwstep::initAC (void) { 00128 setVoltageSources (2); 00129 setInternalVoltageSource (true); 00130 allocMatrixMNA (); 00131 setB (NODE_1, VSRC_1, +1.0); setB (NODE_1, VSRC_2, +0.0); 00132 setB (NODE_2, VSRC_1, +0.0); setB (NODE_2, VSRC_2, +1.0); 00133 setC (VSRC_1, NODE_1, -1.0); setC (VSRC_1, NODE_2, +0.0); 00134 setC (VSRC_2, NODE_1, +0.0); setC (VSRC_2, NODE_2, -1.0); 00135 setE (VSRC_1, +0.0); setE (VSRC_2, +0.0); 00136 checkProperties (); 00137 } 00138 00139 void cpwstep::calcAC (nr_double_t frequency) { 00140 nr_complex_t z = 1.0 / calcY (frequency); 00141 setD (VSRC_1, VSRC_1, z); setD (VSRC_2, VSRC_2, z); 00142 setD (VSRC_1, VSRC_2, z); setD (VSRC_2, VSRC_1, z); 00143 } 00144 00145 // properties 00146 PROP_REQ [] = { 00147 { "W1", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00148 { "W2", PROP_REAL, { 2e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00149 { "S", PROP_REAL, { 4e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00150 { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE }, 00151 PROP_NO_PROP }; 00152 PROP_OPT [] = { 00153 { "Backside", PROP_STR, { PROP_NO_VAL, "Metal" }, 00154 PROP_RNG_STR2 ("Metal", "Air") }, 00155 PROP_NO_PROP }; 00156 struct define_t cpwstep::cirdef = 00157 { "CSTEP", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };