My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tunneldiode.cpp
Go to the documentation of this file.
1 /*
2  * tunneldiode.cpp - resonance tunnel diode class implementation
3  *
4  * Copyright (C) 2011 Michael Margraf <michael.margraf@alumni.tu-berlin.de>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: tunneldiode.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include "component.h"
30 #include "device.h"
31 #include "devstates.h"
32 #include "tunneldiode.h"
33 
34 #define NODE_A1 0 /* cathode node */
35 #define NODE_A2 1 /* anode node */
36 
37 using namespace device;
38 
39 // Constructor for the diode.
40 tunneldiode::tunneldiode () : circuit (2) {
41  type = CIR_TUNNELDIODE;
42 }
43 
44 // Callback for initializing the DC analysis.
45 void tunneldiode::initDC (void) {
46  // allocate MNA matrices
47  allocMatrixMNA ();
48 }
49 
50 // Calculate one branch of the tunnel current.
51 void tunneldiode::calcId (nr_double_t U, nr_double_t& I, nr_double_t& G) {
52  nr_double_t eta = getPropertyDouble ("eta");
53  nr_double_t Wr = getPropertyDouble ("Wr");
54  nr_double_t dv = getPropertyDouble ("dv");
55  nr_double_t de = getPropertyDouble ("de");
56  nr_double_t dW = getPropertyDouble ("dW");
57 
58  U = Wr - Q*U/dv;
59  de *= kB * kelvin (getPropertyDouble ("Temp"));
60 
61  nr_double_t a = M_PI_2 + atan ( U / dW );
62 
63  nr_double_t e = (eta - U) / de;
64  nr_double_t b = e;
65  if (e < 15.0) // avoid numerical overflow
66  b = log (1.0 + exp ( e ));
67 
68  // current
69  I = b * a;
70 
71  // derivative
72  G = Q / dv / de / (1.0 + exp(-e)) * a - b * Q / dv / dW / (1.0 + sqr (U/dW));
73 }
74 
75 // Callback for DC analysis.
76 void tunneldiode::calcDC (void) {
77  // get device properties
78  nr_double_t Ip = getPropertyDouble ("Ip");
79  nr_double_t A = getPropertyDouble ("Area");
80  nr_double_t Tmax = getPropertyDouble ("Tmax");
81  nr_double_t de = getPropertyDouble ("de");
82  nr_double_t eta = getPropertyDouble ("eta");
83  nr_double_t Iv = getPropertyDouble ("Iv");
84  nr_double_t Vv = getPropertyDouble ("Vv");
85  nr_double_t nv = getPropertyDouble ("nv");
86  nr_double_t T = kB * kelvin (getPropertyDouble ("Temp"));
87 
88  // diode voltage
89  Ud = real (getV (NODE_A1) - getV (NODE_A2));
90 
91  // bi-directional tunnel current
92  nr_double_t Ipos, Ineg, Gpos, Gneg;
93  gd = Id = A * Ip * Tmax * de * T / eta / M_PI_2;
94  calcId ( Ud, Ipos, Gpos);
95  calcId (-Ud, Ineg, Gneg);
96  Id *= Ipos - Ineg;
97  gd *= Gpos + Gneg;
98 
99  // thermal-ionic current
100  nv *= T / Q;
101  nr_double_t c = A * Iv / sinh (Vv / nv);
102  Id += c * sinh (Ud / nv);
103  gd += c * cosh (Ud / nv) / nv;
104 
105  nr_double_t Ieq = Id - Ud * gd;
106 
107  // fill in I-Vector
108  setI (NODE_A2, +Ieq);
109  setI (NODE_A1, -Ieq);
110 
111  // fill in G-Matrix
112  setY (NODE_A1, NODE_A1, +gd); setY (NODE_A2, NODE_A2, +gd);
113  setY (NODE_A1, NODE_A2, -gd); setY (NODE_A2, NODE_A1, -gd);
114 }
115 
116 // Saves operating points (voltages).
118  nr_double_t Vd = real (getV (NODE_A1) - getV (NODE_A2));
119  setOperatingPoint ("Vd", Vd);
120 }
121 
122 // Loads operating points (voltages).
124  Ud = getOperatingPoint ("Vd");
125 }
126 
127 // Calculates and saves operating points.
129  nr_double_t A = getPropertyDouble ("Area");
130  nr_double_t Cj0 = getPropertyDouble ("Cj0");
131  nr_double_t M = getScaledProperty ("M");
132  nr_double_t Vj = getScaledProperty ("Vj");
133  nr_double_t te = getScaledProperty ("te");
134 
135  // calculate capacitances and charges
136  nr_double_t Cd;
137 
138  // depletion capacitance
139  nr_double_t c = 1.0 + fabs(Ud) / Vj;
140  Cd = A * Cj0 / pow (c, M);
141  Qd = A * Cj0 * Vj / (1.0-M) * (1.0 - pow (c, 1.0 - M));
142 
143  // quantum well (diffusion) capacitance (negative because of NDR region)
144  Cd -= te * gd;
145  Qd -= te * Id;
146 
147  // save operating points
148  setOperatingPoint ("gd", gd);
149  setOperatingPoint ("Id", Id);
150  setOperatingPoint ("Cd", Cd);
151 }
152 
153 // Callback for initializing the AC analysis.
154 void tunneldiode::initAC (void) {
155  initDC ();
156 }
157 
158 // Build admittance matrix for AC and SP analysis.
159 matrix tunneldiode::calcMatrixY (nr_double_t frequency) {
160  nr_double_t gd = getOperatingPoint ("gd");
161  nr_double_t Cd = getOperatingPoint ("Cd");
162  nr_complex_t yd = rect (gd, Cd * 2.0 * M_PI * frequency);
163  matrix y (2);
164  y.set (NODE_A1, NODE_A1, +yd);
165  y.set (NODE_A2, NODE_A2, +yd);
166  y.set (NODE_A1, NODE_A2, -yd);
167  y.set (NODE_A2, NODE_A1, -yd);
168  return y;
169 }
170 
171 // Callback for the AC analysis.
172 void tunneldiode::calcAC (nr_double_t frequency) {
173  setMatrixY (calcMatrixY (frequency));
174 }
175 
176 // Callback for S-parameter analysis.
177 void tunneldiode::calcSP (nr_double_t frequency) {
178  setMatrixS (ytos (calcMatrixY (frequency)));
179 }
180 
181 #define qState 0 // charge state
182 #define cState 1 // current state
183 
184 // Callback for initializing the TR analysis.
185 void tunneldiode::initTR (void) {
186  setStates (2);
187  initDC ();
188 }
189 
190 // Callback for the TR analysis.
191 void tunneldiode::calcTR (nr_double_t) {
192  calcDC ();
193 
197 
198  nr_double_t Cd = getOperatingPoint ("Cd");
199  transientCapacitance (qState, NODE_A1, NODE_A2, Cd, Ud, Qd);
200 }
201 
202 // properties
203 PROP_REQ [] = {
204  { "Ip", PROP_REAL, { 4.0e-3, PROP_NO_STR }, PROP_POS_RANGE },
205  { "Iv", PROP_REAL, { 0.6e-3, PROP_NO_STR }, PROP_POS_RANGE },
206  { "Vv", PROP_REAL, { 0.8, PROP_NO_STR }, PROP_POS_RANGE },
207 
208  { "Cj0", PROP_REAL, { 80e-15, PROP_NO_STR }, PROP_POS_RANGE },
209  { "M", PROP_REAL, { 0.5, PROP_NO_STR }, PROP_RNGII (0, 2) },
210  { "Vj", PROP_REAL, { 0.5, PROP_NO_STR }, PROP_RNGXI (0, 10) },
211  PROP_NO_PROP };
212 PROP_OPT [] = {
213  { "Wr", PROP_REAL, { 2.7e-20, PROP_NO_STR }, PROP_POS_RANGE },
214  { "eta", PROP_REAL, { 1e-20, PROP_NO_STR }, PROP_POS_RANGE },
215  { "dW", PROP_REAL, { 4.5e-21, PROP_NO_STR }, PROP_POS_RANGE },
216  { "Tmax", PROP_REAL, { 0.95, PROP_NO_STR }, PROP_POS_RANGE },
217  { "de", PROP_REAL, { 0.9, PROP_NO_STR }, PROP_POS_RANGE },
218  { "dv", PROP_REAL, { 2.0, PROP_NO_STR }, PROP_POS_RANGE },
219  { "nv", PROP_REAL, { 16, PROP_NO_STR }, PROP_POS_RANGE },
220  { "te", PROP_REAL, { 0.6e-12, PROP_NO_STR }, PROP_POS_RANGE },
221  { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
222  { "Area", PROP_REAL, { 1, PROP_NO_STR }, PROP_POS_RANGEX },
223  PROP_NO_PROP };
224 struct define_t tunneldiode::cirdef =