Qucs-core
0.0.19
|
00001 /* 00002 * thyristor.cpp - thyristor class implementation 00003 * 00004 * Copyright (C) 2008 Stefan Jahn <stefan@lkcc.org> 00005 * Copyright (C) 2008 Michael Margraf <Michael.Margraf@alumni.TU-Berlin.DE> 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 "device.h" 00032 #include "devstates.h" 00033 #include "thyristor.h" 00034 00035 #define NODE_A1 0 /* anode 1 */ 00036 #define NODE_A2 1 /* anode 2 (cathode) */ 00037 #define NODE_GA 2 /* gate */ 00038 #define NODE_IN 3 /* internal node */ 00039 00040 using namespace qucs; 00041 using namespace qucs::device; 00042 00043 // Constructor for the thyristor. 00044 thyristor::thyristor () : circuit (4) { 00045 type = CIR_THYRISTOR; 00046 } 00047 00048 // Callback for initializing the DC analysis. 00049 void thyristor::initDC (void) { 00050 Ud_last = 0.0; 00051 // allocate MNA matrices 00052 allocMatrixMNA (); 00053 // create internal node 00054 setInternalNode (NODE_IN, "int"); 00055 } 00056 00057 // Callback for DC analysis. 00058 void thyristor::calcDC (void) { 00059 calcTheModel (false); 00060 } 00061 00062 void thyristor::calcTheModel (bool last) { 00063 // get device properties 00064 nr_double_t Ubo = getPropertyDouble ("Vbo"); 00065 nr_double_t Ibo = getPropertyDouble ("Igt"); 00066 nr_double_t Is = getPropertyDouble ("Is"); 00067 nr_double_t N = getPropertyDouble ("N"); 00068 nr_double_t Gg = 1.0 / getPropertyDouble ("Rg"); 00069 nr_double_t T = getPropertyDouble ("Temp"); 00070 gi = 1.0 / getPropertyDouble ("Ri"); 00071 00072 nr_double_t Ut, Ud_bo, Ieq, Vd; 00073 00074 Ut = N * celsius2kelvin (T) * kBoverQ; 00075 Ud_bo = std::log (Ibo / Is + 1.0); 00076 00077 Vd = Ud = real (getV (NODE_IN) - getV (NODE_A2)); 00078 Id = Is; 00079 Ud /= Ut; 00080 00081 bool isOn; 00082 if (last) 00083 isOn = (Ud_last / Ut) > Ud_bo; 00084 else 00085 isOn = Ud > Ud_bo; 00086 00087 if (Ud >= 80.0) { 00088 Id *= std::exp (80.0) * (1.0 + Ud - 80.0) - 1.0; 00089 Ud = 80.0; 00090 } 00091 else 00092 Id *= std::exp (Ud) - 1.0; 00093 00094 gd = Is / Ut * std::exp (Ud); 00095 Ieq = Id - Vd * gd; 00096 00097 // fill in I-Vector 00098 setI (NODE_A2, +Ieq); 00099 setI (NODE_IN, -Ieq); 00100 setI (NODE_A1, +0.0); 00101 setI (NODE_GA, +0.0); 00102 00103 if (!isOn) { 00104 Ut = Ubo / std::log (Ibo / Is); 00105 Vd = Ud = real (getV (NODE_A1) - getV (NODE_IN)); 00106 Id = Is; 00107 Ud /= Ut; 00108 00109 if (Ud >= 80.0) { 00110 Id *= std::exp (80.0) * (1.0 + Ud - 80.0) - 1.0; 00111 Ud = 80.0; 00112 } 00113 else 00114 Id *= std::exp (Ud) - 1.0; 00115 00116 gi = Is / Ut * std::exp (Ud); 00117 Ieq = Id - Vd * gi; 00118 addI (NODE_A1, -Ieq); 00119 addI (NODE_IN, +Ieq); 00120 } 00121 00122 // fill in G-Matrix 00123 setY (NODE_A2, NODE_A2, +gd); setY (NODE_IN, NODE_IN, +gd); 00124 setY (NODE_A2, NODE_IN, -gd); setY (NODE_IN, NODE_A2, -gd); 00125 setY (NODE_A1, NODE_A1, +gi); addY (NODE_IN, NODE_IN, +gi); 00126 setY (NODE_A1, NODE_IN, -gi); setY (NODE_IN, NODE_A1, -gi); 00127 setY (NODE_GA, NODE_GA, +Gg); addY (NODE_IN, NODE_IN, +Gg); 00128 setY (NODE_GA, NODE_IN, -Gg); setY (NODE_IN, NODE_GA, -Gg); 00129 } 00130 00131 // Saves operating points (voltages). 00132 void thyristor::saveOperatingPoints (void) { 00133 nr_double_t Vd = real (getV (NODE_IN) - getV (NODE_A2)); 00134 nr_double_t Vi = real (getV (NODE_A1) - getV (NODE_IN)); 00135 setOperatingPoint ("Vd", Vd); 00136 setOperatingPoint ("Vi", Vi); 00137 } 00138 00139 // Loads operating points (voltages). 00140 void thyristor::loadOperatingPoints (void) { 00141 Ud = getOperatingPoint ("Vd"); 00142 Ui = getOperatingPoint ("Vi"); 00143 } 00144 00145 // Calculates and saves operating points. 00146 void thyristor::calcOperatingPoints (void) { 00147 nr_double_t Cj0 = getPropertyDouble ("Cj0"); 00148 // calculate capacitances and charges 00149 nr_double_t Ci; 00150 Ci = Cj0; 00151 Qi = Cj0 * Ui; 00152 // save operating points 00153 setOperatingPoint ("gi", gi); 00154 setOperatingPoint ("gd", gd); 00155 setOperatingPoint ("Id", Id); 00156 setOperatingPoint ("Ci", Ci); 00157 } 00158 00159 // Callback for initializing the AC analysis. 00160 void thyristor::initAC (void) { 00161 initDC (); 00162 } 00163 00164 // Build admittance matrix for AC and SP analysis. 00165 matrix thyristor::calcMatrixY (nr_double_t frequency) { 00166 nr_double_t gd = getOperatingPoint ("gd"); 00167 nr_double_t gi = getOperatingPoint ("gi"); 00168 nr_double_t gg = 1.0 / getPropertyDouble ("Rg"); 00169 nr_double_t Ci = getOperatingPoint ("Ci"); 00170 nr_complex_t yi = nr_complex_t (gi, Ci * 2.0 * pi * frequency); 00171 matrix y (4); 00172 y.set (NODE_A2, NODE_A2, +gd); 00173 y.set (NODE_IN, NODE_IN, +gd +yi +gg); 00174 y.set (NODE_A2, NODE_IN, -gd); 00175 y.set (NODE_IN, NODE_A2, -gd); 00176 y.set (NODE_A1, NODE_A1, +yi); 00177 y.set (NODE_A1, NODE_IN, -yi); 00178 y.set (NODE_IN, NODE_A1, -yi); 00179 y.set (NODE_GA, NODE_GA, +gg); 00180 y.set (NODE_GA, NODE_IN, -gg); 00181 y.set (NODE_IN, NODE_GA, -gg); 00182 return y; 00183 } 00184 00185 // Callback for the AC analysis. 00186 void thyristor::calcAC (nr_double_t frequency) { 00187 setMatrixY (calcMatrixY (frequency)); 00188 } 00189 00190 // Callback for S-parameter analysis. 00191 void thyristor::calcSP (nr_double_t frequency) { 00192 setMatrixS (ytos (calcMatrixY (frequency))); 00193 } 00194 00195 #define qState 0 // charge state 00196 #define cState 1 // current state 00197 00198 // Callback for initializing the TR analysis. 00199 void thyristor::initTR (void) { 00200 setStates (2); 00201 initDC (); 00202 time_prev = -1.0; 00203 } 00204 00205 // Callback for the TR analysis. 00206 void thyristor::calcTR (nr_double_t time) { 00207 if (time_prev < time) { 00208 time_prev = time; 00209 Ud_last = fabs (real (getV (NODE_IN) - getV (NODE_A2))); 00210 } 00211 calcTheModel (true); 00212 00213 saveOperatingPoints (); 00214 loadOperatingPoints (); 00215 calcOperatingPoints (); 00216 00217 nr_double_t Ci = getOperatingPoint ("Ci"); 00218 transientCapacitance (qState, NODE_A1, NODE_IN, Ci, Ui, Qi); 00219 } 00220 00221 // properties 00222 PROP_REQ [] = { 00223 { "Igt", PROP_REAL, { 50e-6, PROP_NO_STR }, PROP_POS_RANGEX }, 00224 { "Vbo", PROP_REAL, { 30, PROP_NO_STR }, PROP_POS_RANGEX }, 00225 PROP_NO_PROP }; 00226 PROP_OPT [] = { 00227 { "Cj0", PROP_REAL, { 10e-12, PROP_NO_STR }, PROP_POS_RANGE }, 00228 { "Is", PROP_REAL, { 1e-10, PROP_NO_STR }, PROP_POS_RANGE }, 00229 { "N", PROP_REAL, { 2.0, PROP_NO_STR }, PROP_RNGII (0.1, 100) }, 00230 { "Ri", PROP_REAL, { 10.0, PROP_NO_STR }, PROP_POS_RANGEX }, 00231 { "Rg", PROP_REAL, { 5.0, PROP_NO_STR }, PROP_POS_RANGEX }, 00232 { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) }, 00233 PROP_NO_PROP }; 00234 struct define_t thyristor::cirdef = 00235 { "SCR", 3, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_NONLINEAR, PROP_DEF };