Qucs-core
0.0.19
|
00001 /* 00002 * rectline.cpp - rectangular waveguide class implementation 00003 * 00004 * Copyright (C) 2008 Bastien ROUCARIES <roucaries.bastien@gmail.com> 00005 * Copyright (C) 2008 Andrea Zonca <andrea.zonca@gmail.com> 00006 * 00007 * This is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2, or (at your option) 00010 * any later version. 00011 * 00012 * This software is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this package; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00020 * Boston, MA 02110-1301, USA. 00021 * 00022 * $Id$ 00023 * 00024 */ 00025 00026 #if HAVE_CONFIG_H 00027 # include <config.h> 00028 #endif 00029 00030 #include "component.h" 00031 #include "rectline.h" 00032 00055 using namespace qucs; 00056 00057 rectline::rectline () : circuit (2) { 00058 alpha = beta = fc_low = fc_high = 0.0; 00059 zl = 0.0; 00060 type = CIR_RECTANGULAR; 00061 } 00062 00063 void rectline::calcResistivity (const char * const Mat, nr_double_t T) { 00064 if (!strcmp (Mat, "Copper")) { 00065 if (T < 7) { 00066 rho = 2e-11; 00067 } 00068 else if (T < 15) { 00069 rho = 6.66667e-17 * qucs::pow (T, 5.0) - 3.88549e-15 * qucs::pow (T, 4.0) + 00070 9.82267e-14 * qucs::pow (T, 3.0) - 1.29684e-12 * qucs::pow (T, 2.0) + 00071 8.68341e-12 * T - 2.72120e-12; 00072 } 00073 else if (T < 45) { 00074 rho = 6.60731e-15 * qucs::pow (T, 3.0) - 1.14812e-13 * qucs::pow (T, 2.0) - 00075 1.11681e-12 * T + 4.23709e-11; 00076 } 00077 else if (T < 100) { 00078 rho = -6.53059e-15 * qucs::pow (T, 3.0) + 1.73783e-12 * qucs::pow (T, 2.0) - 00079 8.73888e-11 * T + 1.37016e-9; 00080 } 00081 else if (T < 350) { 00082 rho = 1.00018e-17 * qucs::pow (T, 3.0) - 8.72408e-15 * qucs::pow (T, 2.0) + 00083 7.06020e-11 * T - 3.51125e-9; 00084 } 00085 else { 00086 rho = 0.000000020628; 00087 } 00088 // in ADS iT_K is forced T_Ko Cu_300K: 00089 //rho = 1.7e-8; 00090 } 00091 else if (!strcmp (Mat, "StainlessSteel")) { 00092 rho = 7.4121e-17 * qucs::pow (T, 4.0) - 5.3504e-14 * qucs::pow (T, 3.0) + 00093 1.2902e-11 * qucs::pow (T, 2.0) - 2.9186e-10 * T +4.9320e-7; 00094 } 00095 else if (!strcmp (Mat, "Gold")) { 00096 if (T < 20) { 00097 rho = 0.00000000024; 00098 } 00099 else if (T < 65) { 00100 rho = 2e-12 * qucs::pow (T, 2.0) - 8e-11 * T + 1e-9; 00101 } 00102 else if (T < 80) { 00103 rho = 5e-13 * qucs::pow (T, 3.0) - 1e-10 * qucs::pow (T, 2.0) + 9e-9 * T - 2e-7; 00104 } 00105 else if (T < 300) { 00106 rho = 8e-11 * T - 1e-10; 00107 } 00108 else { 00109 rho = 2.4e-8; 00110 } 00111 } 00112 } 00113 00153 void rectline::calcPropagation (nr_double_t frequency) { 00154 nr_double_t er = getPropertyDouble ("er"); 00155 nr_double_t mur = getPropertyDouble ("mur"); 00156 nr_double_t tand = getPropertyDouble ("tand"); 00157 nr_double_t a = getPropertyDouble ("a"); 00158 nr_double_t b = getPropertyDouble ("b"); 00159 00160 /* wave number */ 00161 nr_double_t k0; 00162 nr_double_t kc; 00163 /* dielectric loss */ 00164 nr_double_t ad, ac, rs; 00165 00166 // check cutoff frequency 00167 if (frequency >= fc_high) { 00168 logprint (LOG_ERROR, "WARNING: Operating frequency (%g) outside TE10 " 00169 "band (%g <= TE10 <= %g) or outside non propagative mode " 00170 "<= %g\n", frequency, fc_low, fc_high, fc_low); 00171 } 00172 // calculate wave number 00173 k0 = (2.0 * pi * frequency * std::sqrt (er * mur)) / C0; 00174 kc = pi / a; 00175 00176 // calculate losses only for propagative mode 00177 if (frequency >= fc_low) { 00178 // calculate beta 00179 beta = std::sqrt (sqr (k0) - sqr (kc)); 00180 00181 // dielectric 00182 ad = (sqr(k0) * tand) / (2.0 * beta); 00183 // resistive 00184 rs = std::sqrt (pi * frequency * mur * MU0 * rho); 00185 ac = rs * (2.0 * b * sqr (pi) + cubic (a) * sqr (k0)) / 00186 (cubic (a) * b * beta * k0 * Z0); 00187 alpha = (ad + ac); 00188 00189 // wave impedance 00190 zl = (k0 * Z0) / beta; 00191 00192 } else { 00193 /* according to [2] eq 3.207 */ 00194 beta = 0; 00195 alpha = -std::sqrt (- (sqr (k0) - sqr (kc))); 00196 // wave impedance 00197 zl = (k0 * Z0) / nr_complex_t (0, -alpha) ; 00198 } 00199 } 00200 00202 void rectline::calcNoiseSP (nr_double_t) { 00203 nr_double_t l = getPropertyDouble ("L"); 00204 if (l < 0) return; 00205 // calculate noise using Bosma's theorem 00206 nr_double_t T = getPropertyDouble ("Temp"); 00207 matrix s = getMatrixS (); 00208 matrix e = eye (getSize ()); 00209 setMatrixN (celsius2kelvin (T) / T0 * (e - s * transpose (conj (s)))); 00210 } 00211 00215 void rectline::initCheck (void) { 00216 nr_double_t a = getPropertyDouble ("a"); 00217 nr_double_t b = getPropertyDouble ("b"); 00218 nr_double_t epsr = getPropertyDouble ("er"); 00219 nr_double_t mur = getPropertyDouble ("mur"); 00220 // check validity 00221 if (a < b) { 00222 logprint (LOG_ERROR, "ERROR: a < b should be a >= b.\n"); 00223 } 00224 nr_double_t c = std::sqrt (epsr * mur); 00225 fc_low = C0 / (2.0 * a * c); 00226 /* min of second TE mode and first TM mode */ 00227 fc_high = std::min (C0 / (a * c), C0 / (2.0 * b * c)); 00228 // calculation of resistivity 00229 rho = getPropertyDouble ("rho"); 00230 nr_double_t T = getPropertyDouble ("Temp"); 00231 calcResistivity (getPropertyString ("Material"), celsius2kelvin (T)); 00232 } 00233 00234 void rectline::saveCharacteristics (nr_complex_t) { 00235 setCharacteristic ("Zl", real (zl)); 00236 } 00237 00239 void rectline::initSP (void) { 00240 // allocate S-parameter matrix 00241 allocMatrixS (); 00242 initCheck (); 00243 } 00244 00246 void rectline::calcSP (nr_double_t frequency) { 00247 nr_double_t l = getPropertyDouble ("L"); 00248 00249 // calculate propagation constants 00250 calcPropagation (frequency); 00251 00252 // calculate S-parameters 00253 nr_complex_t z = zl / z0; 00254 nr_complex_t y = 1.0 / z; 00255 nr_complex_t g = nr_complex_t (alpha, beta); 00256 nr_complex_t n = 2.0 * cosh (g * l) + (z + y) * sinh (g * l); 00257 nr_complex_t s11 = (z - y) * sinh (g * l) / n; 00258 nr_complex_t s21 = 2.0 / n; 00259 setS (NODE_1, NODE_1, s11); setS (NODE_2, NODE_2, s11); 00260 setS (NODE_1, NODE_2, s21); setS (NODE_2, NODE_1, s21); 00261 } 00262 00263 /* ! Compute DC 00264 \note below cut off it is an open circuit 00265 */ 00266 void rectline::initDC (void) { 00267 allocMatrixMNA (); 00268 // open circuit 00269 clearY (); 00270 } 00271 00273 void rectline::initAC (void) { 00274 setVoltageSources (0); 00275 allocMatrixMNA (); 00276 initCheck (); 00277 } 00278 00280 void rectline::calcAC (nr_double_t frequency) { 00281 nr_double_t l = getPropertyDouble ("L"); 00282 00283 // calculate propagation constants 00284 calcPropagation (frequency); 00285 00286 // calculate Y-parameters 00287 nr_complex_t g = nr_complex_t (alpha, beta); 00288 nr_complex_t y11 = coth (g * l) / zl; 00289 nr_complex_t y21 = -cosech (g * l) / zl; 00290 setY (NODE_1, NODE_1, y11); setY (NODE_2, NODE_2, y11); 00291 setY (NODE_1, NODE_2, y21); setY (NODE_2, NODE_1, y21); 00292 } 00293 00295 void rectline::calcNoiseAC (nr_double_t) { 00296 nr_double_t l = getPropertyDouble ("L"); 00297 if (l < 0) return; 00298 // calculate noise using Bosma's theorem 00299 nr_double_t T = getPropertyDouble ("Temp"); 00300 setMatrixN (4.0 * celsius2kelvin (T) / T0 * real (getMatrixY ())); 00301 } 00302 00303 // properties 00304 PROP_REQ [] = { 00305 { "a", PROP_REAL, { 2.86e-2, PROP_NO_STR }, PROP_POS_RANGEX }, 00306 { "b", PROP_REAL, { 1.016e-2, PROP_NO_STR }, PROP_POS_RANGEX }, 00307 { "L", PROP_REAL, { 1500e-3, PROP_NO_STR }, PROP_NO_RANGE }, 00308 { "er", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 100) }, 00309 { "mur", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 100) }, 00310 { "tand", PROP_REAL, { 4e-4, PROP_NO_STR }, PROP_POS_RANGE }, 00311 { "rho", PROP_REAL, { 0.022e-6, PROP_NO_STR }, PROP_POS_RANGE }, 00312 PROP_NO_PROP }; 00313 PROP_OPT [] = { 00314 { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) }, 00315 { "Material", PROP_STR, { PROP_NO_VAL, "unspecified" }, 00316 PROP_RNG_STR4 ("unspecified", "Copper", "StainlessSteel", "Gold") }, 00317 PROP_NO_PROP }; 00318 struct define_t rectline::cirdef = 00319 { "RECTLINE", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };