My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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: diac.cpp 1825 2011-03-11 20:42:14Z ela $
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 device;
40 
41 // Constructor for the diac.
42 diac::diac () : circuit (3) {
43  type = CIR_DIAC;
44 }
45 
46 // Callback for initializing the DC analysis.
47 void diac::initDC (void) {
48  Ud_last = 0.0;
49  // allocate MNA matrices
50  allocMatrixMNA ();
51  // create internal node
52  setInternalNode (NODE_IN, "int");
53 }
54 
55 // Callback for DC analysis.
56 void diac::calcDC (void) {
57  calcTheModel (false);
58 }
59 
60 void diac::calcTheModel (bool last) {
61  // get device properties
62  nr_double_t Ubo = getPropertyDouble ("Vbo");
63  nr_double_t Ibo = getPropertyDouble ("Ibo");
64  nr_double_t Is = getPropertyDouble ("Is");
65  nr_double_t N = getPropertyDouble ("N");
66  nr_double_t gi = 1.0 / getPropertyDouble ("Ri");
67  nr_double_t T = getPropertyDouble ("Temp");
68 
69  bool isOn;
70  if (last)
71  Ud = fabs (Ud_last);
72  else
73  Ud = fabs (real (getV (NODE_A1) - getV (NODE_IN)));
74  isOn = Ud > (Ibo / gi);
75 
76  nr_double_t Ut, Ieq, Vd;
77 
78  if (isOn)
79  Ut = N * kelvin (T) * kBoverQ;
80  else
81  Ut = Ubo / log (Ibo / Is);
82 
83  Vd = Ud = real (getV (NODE_IN) - getV (NODE_A2));
84  Ud = fabs (Ud) / Ut;
85  Id = sign (Vd) * Is;
86 
87  if (Ud >= 80.0) {
88  Id *= exp (80.0) * (1.0 + Ud - 80.0) - 1.0;
89  Ud = 80.0;
90  }
91  else
92  Id *= exp (Ud) - 1.0;
93 
94  gd = Is / Ut * exp (Ud);
95  Ieq = Id - Vd * gd;
96 
97  // fill in I-Vector
98  setI (NODE_A2, +Ieq);
99  setI (NODE_IN, -Ieq);
100  setI (NODE_A1, +0.0);
101 
102  // fill in G-Matrix
103  setY (NODE_A2, NODE_A2, +gd); setY (NODE_IN, NODE_IN, +gd);
104  setY (NODE_A2, NODE_IN, -gd); setY (NODE_IN, NODE_A2, -gd);
105  setY (NODE_A1, NODE_A1, +gi); addY (NODE_IN, NODE_IN, +gi);
106  setY (NODE_A1, NODE_IN, -gi); setY (NODE_IN, NODE_A1, -gi);
107 }
108 
109 // Saves operating points (voltages).
111  nr_double_t Vd = real (getV (NODE_IN) - getV (NODE_A2));
112  nr_double_t Vi = real (getV (NODE_A1) - getV (NODE_IN));
113  setOperatingPoint ("Vd", Vd);
114  setOperatingPoint ("Vi", Vi);
115 }
116 
117 // Loads operating points (voltages).
119  Ud = getOperatingPoint ("Vd");
120  Ui = getOperatingPoint ("Vi");
121 }
122 
123 // Calculates and saves operating points.
125  nr_double_t Cj0 = getPropertyDouble ("Cj0");
126  // calculate capacitances and charges
127  nr_double_t Ci;
128  Ci = Cj0;
129  Qi = Cj0 * Ud;
130  // save operating points
131  setOperatingPoint ("gi", gi);
132  setOperatingPoint ("gd", gd);
133  setOperatingPoint ("Id", Id);
134  setOperatingPoint ("Ci", Ci);
135 }
136 
137 // Callback for initializing the AC analysis.
138 void diac::initAC (void) {
139  initDC ();
140 }
141 
142 // Build admittance matrix for AC and SP analysis.
143 matrix diac::calcMatrixY (nr_double_t frequency) {
144  nr_double_t gd = getOperatingPoint ("gd");
145  nr_double_t gi = getOperatingPoint ("gi");
146  nr_double_t Ci = getOperatingPoint ("Ci");
147  nr_complex_t yd = rect (gd, Ci * 2.0 * M_PI * frequency);
148  matrix y (3);
149  y.set (NODE_A2, NODE_A2, +yd);
150  y.set (NODE_IN, NODE_IN, +yd +gi);
151  y.set (NODE_A2, NODE_IN, -yd);
152  y.set (NODE_IN, NODE_A2, -yd);
153  y.set (NODE_A1, NODE_A1, +gi);
154  y.set (NODE_A1, NODE_IN, -gi);
155  y.set (NODE_IN, NODE_A1, -gi);
156  return y;
157 }
158 
159 // Callback for the AC analysis.
160 void diac::calcAC (nr_double_t frequency) {
161  setMatrixY (calcMatrixY (frequency));
162 }
163 
164 // Callback for S-parameter analysis.
165 void diac::calcSP (nr_double_t frequency) {
166  setMatrixS (ytos (calcMatrixY (frequency)));
167 }
168 
169 #define qState 0 // charge state
170 #define cState 1 // current state
171 
172 // Callback for initializing the TR analysis.
173 void diac::initTR (void) {
174  setStates (2);
175  initDC ();
176  time_prev = -1.0;
177 }
178 
179 // Callback for the TR analysis.
180 void diac::calcTR (nr_double_t time) {
181  if (time_prev < time) {
182  time_prev = time;
183  Ud_last = real (getV (NODE_A1) - getV (NODE_IN));
184  }
185  calcTheModel (true);
186 
190 
191  nr_double_t Ci = getOperatingPoint ("Ci");
192  transientCapacitance (qState, NODE_IN, NODE_A2, Ci, Ud, Qi);
193 }
194 
195 // properties
196 PROP_REQ [] = {
197  { "Ibo", PROP_REAL, { 50e-6, PROP_NO_STR }, PROP_POS_RANGEX },
198  { "Vbo", PROP_REAL, { 30, PROP_NO_STR }, PROP_POS_RANGEX },
199  PROP_NO_PROP };
200 PROP_OPT [] = {
201  { "Cj0", PROP_REAL, { 10e-12, PROP_NO_STR }, PROP_POS_RANGE },
202  { "Is", PROP_REAL, { 1e-10, PROP_NO_STR }, PROP_POS_RANGE },
203  { "N", PROP_REAL, { 2.0, PROP_NO_STR }, PROP_RNGII (0.1, 100) },
204  { "Ri", PROP_REAL, { 10.0, PROP_NO_STR }, PROP_POS_RANGEX },
205  { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
206  PROP_NO_PROP };
207 struct define_t diac::cirdef =