Qucs-core
0.0.19
|
00001 /* 00002 * bondwire.cpp - bondwire class implementation 00003 * 00004 * Copyright (C) 2006 Bastien Roucaries <roucaries.bastien@gmail.com> 00005 * Copyright (C) 2007, 2008 Stefan Jahn <stefan@lkcc.org> 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 00049 #if HAVE_CONFIG_H 00050 # include <config.h> 00051 #endif 00052 00053 #include "component.h" 00054 #include "substrate.h" 00055 #include "bondwire.h" 00056 00057 using namespace qucs; 00058 00059 bondwire::bondwire () : circuit (2) { 00060 type = CIR_BONDWIRE; 00061 } 00062 00063 00065 #define TABLE(x) { #x, x } 00066 00067 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 00068 00070 enum bondwiremodel { 00071 FREESPACE, 00072 MIRROR, 00073 DESCHARLES 00074 }; 00075 00077 struct modeltable_t { 00078 const char * name; 00079 int model; 00080 }; 00081 00083 static const modeltable_t modeltable[] = { 00084 TABLE(FREESPACE), 00085 TABLE(MIRROR), 00086 }; 00087 00088 00094 void bondwire::getProperties (void) { 00095 unsigned int i; 00096 00097 R = 0; 00098 l = getPropertyDouble ("L"); 00099 d = getPropertyDouble ("D"); 00100 h = getPropertyDouble ("H"); 00101 rho = getPropertyDouble ("rho"); 00102 mur = getPropertyDouble ("mur"); 00103 00104 /* model used */ 00105 const char * Model = getPropertyString ("Model"); 00106 if (Model == NULL) { 00107 model = FREESPACE; 00108 logprint (LOG_STATUS, "Model is not specified force FREESPACE\n"); 00109 } else { 00110 model = (enum bondwiremodel) -1; 00111 for (i = 0 ; i < ARRAY_SIZE (modeltable); i++) { 00112 if (!strcasecmp (modeltable[i].name, Model)) 00113 model = modeltable[i].model; 00114 } 00115 00116 if (model == -1) 00117 /* XXXX: how to abort ? */ 00118 logprint (LOG_ERROR, "Model %s not defined\n", Model); 00119 } 00120 00121 /* For noise */ 00122 temp = getPropertyDouble ("Temp"); 00123 00124 /* how to get properties of the substrate, e.g. Er, H */ 00125 substrate * subst = getSubstrate (); 00126 nr_double_t er = subst->getPropertyDouble ("er"); 00127 nr_double_t h = subst->getPropertyDouble ("h"); 00128 nr_double_t t = subst->getPropertyDouble ("t"); 00129 00130 /* Not yet used */ 00131 (void) er; 00132 (void) h; 00133 (void) t; 00134 } 00135 00143 static nr_double_t skindepth (const nr_double_t f, 00144 const nr_double_t rho, const nr_double_t mur) { 00145 return std::sqrt (rho / (pi * f * MU0 * mur)); 00146 } 00147 00159 nr_double_t bondwire::resistance (const nr_double_t f) const { 00160 nr_double_t delta, rout, rin; 00161 rout = d / 2; 00162 if (f > 0.0) { 00163 delta = skindepth (f, rho, mur); 00164 rin = rout - delta; 00165 if (rin < 0.0) 00166 rin = 0.0; 00167 } 00168 else 00169 rin = 0.0; 00170 00171 return (rho * one_over_pi * l) / (rout * rout - rin * rin); 00172 } 00173 00174 00198 static nr_double_t correctionfactor (const nr_double_t f, 00199 const nr_double_t d, 00200 const nr_double_t rho, 00201 const nr_double_t mur) { 00202 /* skin depth */ 00203 nr_double_t delta; 00204 00205 if (f > 0.0 && rho > 0.0) { 00206 delta = skindepth (f, rho, mur); 00207 if (delta / d < 1e-2) 00208 return delta / d; 00209 else 00210 return (mur / 4) * std::tanh ((4 * delta) / d); 00211 } 00212 return mur / 4; 00213 } 00214 00254 nr_double_t bondwire::Lfreespace (const nr_double_t f) const { 00255 nr_double_t _2ld = (2.0 * l) / d; 00256 nr_double_t d2l = d / (2.0 * l); 00257 nr_double_t tmp; 00258 00259 tmp = std::log (_2ld + std::sqrt (1 + _2ld * _2ld)); 00260 tmp += d2l - std::sqrt (1 + d2l * d2l); 00261 tmp += correctionfactor (f, d, rho, mur); 00262 00263 return MU0 * (one_over_pi / 2) * l * tmp; 00264 } 00265 00266 00297 nr_double_t bondwire::Lmirror (void) const { 00298 nr_double_t tmp; 00299 00300 /* compute \$\ln \frac{l+\sqrt{l^2+d^2/4}}{l+\sqrt{l^2+4h^2}}\$ */ 00301 tmp = std::log ((l + std::sqrt (l * l + d * d / 4)) / (l + std::sqrt (l * l + 4 * h * h))); 00302 tmp += std::log (4 * h / d); 00303 tmp += std::sqrt (1 + 4 * h * h / (l * l)); 00304 tmp -= std::sqrt (1 + d * d / (4 * l * l)); 00305 tmp -= 2 * h / l; 00306 tmp += d / (2 * l); 00307 00308 return MU0 * (one_over_pi / 2) * l * tmp; 00309 } 00310 00311 00314 matrix bondwire::calcMatrixY (const nr_double_t f) { 00315 nr_double_t Lw; 00316 L = 0; 00317 00318 switch (model) { 00319 case MIRROR: 00320 L = Lmirror (); 00321 R = resistance (f); 00322 break; 00323 case FREESPACE: 00324 L = Lfreespace (f); 00325 R = resistance (f); 00326 break; 00327 default: 00328 break; 00329 } 00330 00331 Lw = L * 2 * pi * f; 00332 00333 /* build Y-parameter matrix */ 00334 nr_complex_t yL = 1.0 / nr_complex_t (R, Lw); 00335 00336 matrix Y (2); 00337 Y.set (NODE_1, NODE_1, +yL); 00338 Y.set (NODE_1, NODE_2, -yL); 00339 Y.set (NODE_2, NODE_1, -yL); 00340 Y.set (NODE_2, NODE_2, +yL); 00341 return Y; 00342 } 00343 00345 void bondwire::initSP (void) { 00346 allocMatrixS (); 00347 getProperties (); 00348 } 00349 00353 void bondwire::calcSP (const nr_double_t frequency) { 00354 setMatrixS (ytos (calcMatrixY (frequency))); 00355 } 00356 00358 void bondwire::saveCharacteristics (nr_double_t) { 00359 setCharacteristic ("L", L); 00360 setCharacteristic ("R", R); 00361 } 00362 00366 void bondwire::initDC (void) { 00367 nr_double_t g; 00368 00369 getProperties (); 00370 00371 /* for non-zero resistances usual MNA entries */ 00372 if (rho != 0.0) { 00373 g = 1.0 / resistance (0); 00374 setVoltageSources (0); 00375 allocMatrixMNA (); 00376 setY (NODE_1, NODE_1, +g); setY (NODE_2, NODE_2, +g); 00377 setY (NODE_1, NODE_2, -g); setY (NODE_2, NODE_1, -g); 00378 } 00379 /* for zero resistances create a zero voltage source */ 00380 else { 00381 setVoltageSources (1); 00382 setInternalVoltageSource (1); 00383 allocMatrixMNA (); 00384 clearY (); 00385 voltageSource (VSRC_1, NODE_1, NODE_2); 00386 } 00387 } 00388 00390 void bondwire::initAC (void) { 00391 getProperties (); 00392 setVoltageSources (0); 00393 allocMatrixMNA (); 00394 } 00395 00399 void bondwire::calcAC (const nr_double_t frequency) { 00400 setMatrixY (calcMatrixY (frequency)); 00401 } 00402 00403 void bondwire::calcNoiseSP (nr_double_t) { 00404 // calculate noise correlation matrix 00405 nr_double_t T = getPropertyDouble ("Temp"); 00406 nr_double_t f = celsius2kelvin (T) * 4.0 * R * z0 / norm (4.0 * z0 + R) / T0; 00407 setN (NODE_1, NODE_1, +f); setN (NODE_2, NODE_2, +f); 00408 setN (NODE_1, NODE_2, -f); setN (NODE_2, NODE_1, -f); 00409 } 00410 00411 void bondwire::calcNoiseAC (nr_double_t) { 00412 // calculate noise current correlation matrix 00413 nr_double_t y = 1 / R; 00414 nr_double_t T = getPropertyDouble ("Temp"); 00415 nr_double_t f = celsius2kelvin (T) / T0 * 4.0 * y; 00416 setN (NODE_1, NODE_1, +f); setN (NODE_2, NODE_2, +f); 00417 setN (NODE_1, NODE_2, -f); setN (NODE_2, NODE_1, -f); 00418 } 00419 00420 // properties 00421 PROP_REQ [] = { 00422 { "D", PROP_REAL, { 25e-6, PROP_NO_STR }, PROP_POS_RANGE }, 00423 { "L", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00424 { "H", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE }, 00425 { "mur", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 100) }, 00426 { "rho", PROP_REAL, { 0.022e-6, PROP_NO_STR }, PROP_POS_RANGE }, 00427 { "Model", PROP_STR, { PROP_NO_VAL, "FREESPACE" }, 00428 PROP_RNG_STR3 ("FREESPACE", "MIRROR", "DESCHARLES") }, 00429 { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE }, 00430 PROP_NO_PROP }; 00431 PROP_OPT [] = { 00432 { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) }, 00433 PROP_NO_PROP }; 00434 struct define_t bondwire::cirdef = 00435 { "BOND", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };