Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
diac.cpp
Go to the documentation of this file.
1 /*
2  * diac.cpp - diac class implementation
3  *
4  * Copyright (C) 2008 Stefan Jahn <stefan@lkcc.org>
5  * Copyright (C) 2008 Michael Margraf <Michael.Margraf@alumni.TU-Berlin.DE>
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this package; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * $Id$
23  *
24  */
25 
26 #if HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include "component.h"
31 #include "device.h"
32 #include "devstates.h"
33 #include "diac.h"
34 
35 #define NODE_A1 0 /* anode 1 */
36 #define NODE_A2 1 /* anode 2 (cathode) */
37 #define NODE_IN 2 /* internal node */
38 
39 using namespace qucs;
40 using namespace qucs::device;
41 
42 // Constructor for the diac.
43 diac::diac () : circuit (3) {
44  type = CIR_DIAC;
45 }
46 
47 // Callback for initializing the DC analysis.
48 void diac::initDC (void) {
49  Ud_last = 0.0;
50  // allocate MNA matrices
51  allocMatrixMNA ();
52  // create internal node
53  setInternalNode (NODE_IN, "int");
54 }
55 
56 // Callback for DC analysis.
57 void diac::calcDC (void) {
58  calcTheModel (false);
59 }
60 
61 void diac::calcTheModel (bool last) {
62  // get device properties
63  nr_double_t Ubo = getPropertyDouble ("Vbo");
64  nr_double_t Ibo = getPropertyDouble ("Ibo");
65  nr_double_t Is = getPropertyDouble ("Is");
66  nr_double_t N = getPropertyDouble ("N");
67  nr_double_t gi = 1.0 / getPropertyDouble ("Ri");
68  nr_double_t T = getPropertyDouble ("Temp");
69 
70  bool isOn;
71  if (last)
72  Ud = fabs (Ud_last);
73  else
74  Ud = fabs (real (getV (NODE_A1) - getV (NODE_IN)));
75  isOn = Ud > (Ibo / gi);
76 
77  nr_double_t Ut, Ieq, Vd;
78 
79  if (isOn)
80  Ut = N * kelvin (T) * kBoverQ;
81  else
82  Ut = Ubo / std::log (Ibo / Is);
83 
84  Vd = Ud = real (getV (NODE_IN) - getV (NODE_A2));
85  Ud = fabs (Ud) / Ut;
86  Id = sign (Vd) * Is;
87 
88  if (Ud >= 80.0) {
89  Id *= std::exp (80.0) * (1.0 + Ud - 80.0) - 1.0;
90  Ud = 80.0;
91  }
92  else
93  Id *= std::exp (Ud) - 1.0;
94 
95  gd = Is / Ut * std::exp (Ud);
96  Ieq = Id - Vd * gd;
97 
98  // fill in I-Vector
99  setI (NODE_A2, +Ieq);
100  setI (NODE_IN, -Ieq);
101  setI (NODE_A1, +0.0);
102 
103  // fill in G-Matrix
104  setY (NODE_A2, NODE_A2, +gd); setY (NODE_IN, NODE_IN, +gd);
105  setY (NODE_A2, NODE_IN, -gd); setY (NODE_IN, NODE_A2, -gd);
106  setY (NODE_A1, NODE_A1, +gi); addY (NODE_IN, NODE_IN, +gi);
107  setY (NODE_A1, NODE_IN, -gi); setY (NODE_IN, NODE_A1, -gi);
108 }
109 
110 // Saves operating points (voltages).
112  nr_double_t Vd = real (getV (NODE_IN) - getV (NODE_A2));
113  nr_double_t Vi = real (getV (NODE_A1) - getV (NODE_IN));
114  setOperatingPoint ("Vd", Vd);
115  setOperatingPoint ("Vi", Vi);
116 }
117 
118 // Loads operating points (voltages).
120  Ud = getOperatingPoint ("Vd");
121  Ui = getOperatingPoint ("Vi");
122 }
123 
124 // Calculates and saves operating points.
126  nr_double_t Cj0 = getPropertyDouble ("Cj0");
127  // calculate capacitances and charges
128  nr_double_t Ci;
129  Ci = Cj0;
130  Qi = Cj0 * Ud;
131  // save operating points
132  setOperatingPoint ("gi", gi);
133  setOperatingPoint ("gd", gd);
134  setOperatingPoint ("Id", Id);
135  setOperatingPoint ("Ci", Ci);
136 }
137 
138 // Callback for initializing the AC analysis.
139 void diac::initAC (void) {
140  initDC ();
141 }
142 
143 // Build admittance matrix for AC and SP analysis.
144 matrix diac::calcMatrixY (nr_double_t frequency) {
145  nr_double_t gd = getOperatingPoint ("gd");
146  nr_double_t gi = getOperatingPoint ("gi");
147  nr_double_t Ci = getOperatingPoint ("Ci");
148  nr_complex_t yd = nr_complex_t (gd, Ci * 2.0 * M_PI * frequency);
149  matrix y (3);
150  y.set (NODE_A2, NODE_A2, +yd);
151  y.set (NODE_IN, NODE_IN, +yd +gi);
152  y.set (NODE_A2, NODE_IN, -yd);
153  y.set (NODE_IN, NODE_A2, -yd);
154  y.set (NODE_A1, NODE_A1, +gi);
155  y.set (NODE_A1, NODE_IN, -gi);
156  y.set (NODE_IN, NODE_A1, -gi);
157  return y;
158 }
159 
160 // Callback for the AC analysis.
161 void diac::calcAC (nr_double_t frequency) {
162  setMatrixY (calcMatrixY (frequency));
163 }
164 
165 // Callback for S-parameter analysis.
166 void diac::calcSP (nr_double_t frequency) {
167  setMatrixS (ytos (calcMatrixY (frequency)));
168 }
169 
170 #define qState 0 // charge state
171 #define cState 1 // current state
172 
173 // Callback for initializing the TR analysis.
174 void diac::initTR (void) {
175  setStates (2);
176  initDC ();
177  time_prev = -1.0;
178 }
179 
180 // Callback for the TR analysis.
181 void diac::calcTR (nr_double_t time) {
182  if (time_prev < time) {
183  time_prev = time;
184  Ud_last = real (getV (NODE_A1) - getV (NODE_IN));
185  }
186  calcTheModel (true);
187 
191 
192  nr_double_t Ci = getOperatingPoint ("Ci");
194 }
195 
196 // properties
197 PROP_REQ [] = {
198  { "Ibo", PROP_REAL, { 50e-6, PROP_NO_STR }, PROP_POS_RANGEX },
199  { "Vbo", PROP_REAL, { 30, PROP_NO_STR }, PROP_POS_RANGEX },
200  PROP_NO_PROP };
201 PROP_OPT [] = {
202  { "Cj0", PROP_REAL, { 10e-12, PROP_NO_STR }, PROP_POS_RANGE },
203  { "Is", PROP_REAL, { 1e-10, PROP_NO_STR }, PROP_POS_RANGE },
204  { "N", PROP_REAL, { 2.0, PROP_NO_STR }, PROP_RNGII (0.1, 100) },
205  { "Ri", PROP_REAL, { 10.0, PROP_NO_STR }, PROP_POS_RANGEX },
206  { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
207  PROP_NO_PROP };
208 struct define_t diac::cirdef =
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
nr_double_t getOperatingPoint(const char *)
Definition: circuit.cpp:525
#define PROP_POS_RANGE
Definition: netdefs.h:129
matrix ytos(matrix y, qucs::vector z0)
Admittance matrix to scattering parameters.
Definition: matrix.cpp:1133
matrix real(matrix a)
Real part matrix.
Definition: matrix.cpp:568
nr_double_t Ud_last
Definition: diac.h:46
nr_double_t Qi
Definition: diac.h:46
#define PROP_RNGII(f, t)
Definition: netdefs.h:138
#define N(n)
Definition: equation.cpp:58
nr_double_t Ud
Definition: diac.h:46
#define kelvin(x)
Definition: constants.h:108
#define PROP_DEF
Definition: netdefs.h:189
nr_double_t getPropertyDouble(const char *)
Definition: object.cpp:176
#define PROP_REAL
Definition: netdefs.h:174
void setStates(int n)
Definition: states.h:52
Definition: diac.cpp:208
nr_double_t Id
Definition: diac.h:46
#define PROP_NO_PROP
Definition: netdefs.h:122
#define qState
Definition: diac.cpp:170
#define K
Absolute 0 in centigrade.
Definition: constants.h:59
#define PROP_NO_STR
Definition: netdefs.h:125
PROP_REQ[]
Definition: diac.cpp:197
void calcDC(void)
Definition: diac.cpp:57
nr_complex_t sign(const nr_complex_t z)
complex sign function
Definition: complex.cpp:435
void addY(int, int, nr_complex_t)
Definition: circuit.cpp:458
PROP_NONLINEAR
Definition: diac.cpp:209
void transientCapacitance(int, int, int, nr_double_t, nr_double_t, nr_double_t)
Definition: circuit.cpp:759
#define NODE_IN
Definition: diac.cpp:37
nr_double_t time_prev
Definition: diac.h:46
#define kBoverQ
Boltzmann constant over Elementary charge ( )
Definition: constants.h:68
#define PROP_COMPONENT
Definition: netdefs.h:116
void calcAC(nr_double_t)
Definition: diac.cpp:161
void initAC(void)
Definition: diac.cpp:139
#define NODE_A1
Definition: diac.cpp:35
void setMatrixY(matrix)
Definition: circuit.cpp:685
void saveOperatingPoints(void)
Definition: diac.cpp:111
void calcTheModel(bool)
Definition: diac.cpp:61
void initTR(void)
Definition: diac.cpp:174
#define M_PI
Archimedes' constant ( )
Definition: consts.h:47
void calcSP(nr_double_t)
Definition: diac.cpp:166
void loadOperatingPoints(void)
Definition: diac.cpp:119
void setI(int, nr_complex_t)
Definition: circuit.cpp:397
void setMatrixS(matrix)
Definition: circuit.cpp:643
type
Definition: parse_vcd.y:164
void setY(int, int, nr_complex_t)
Definition: circuit.cpp:452
#define PROP_MIN_VAL(k)
Definition: netdefs.h:133
void setInternalNode(int, const char *)
Definition: circuit.cpp:635
nr_double_t Ui
Definition: diac.h:46
void calcTR(nr_double_t)
Definition: diac.cpp:181
void allocMatrixMNA(void)
Definition: circuit.cpp:267
#define PROP_POS_RANGEX
Definition: netdefs.h:131
void calcOperatingPoints(void)
Definition: diac.cpp:125
y
Definition: parse_mdl.y:499
nr_double_t getV(int, nr_double_t)
Definition: circuit.cpp:941
nr_complex_t exp(const nr_complex_t z)
Compute complex exponential.
Definition: complex.cpp:205
void setOperatingPoint(const char *, nr_double_t)
Definition: circuit.cpp:533
#define NODE_A2
Definition: diac.cpp:36
nr_complex_t log(const nr_complex_t z)
Compute principal value of natural logarithm of z.
Definition: complex.cpp:215
qucs::matrix calcMatrixY(nr_double_t)
Definition: diac.cpp:144
void initDC(void)
Definition: diac.cpp:48
nr_double_t gi
Definition: diac.h:46
PROP_OPT[]
Definition: diac.cpp:201
#define PROP_NO_SUBSTRATE
Definition: netdefs.h:118
nr_double_t gd
Definition: diac.h:46