Qucs-core  0.0.19
bondwire.cpp
Go to the documentation of this file.
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 };