JUK1
AutoDiffTest.cpp
Go to the documentation of this file.
1 #include <iostream>
3 #include <assert.h>
4 #include <iomanip>
5 #include <chrono>
6 
7 namespace AD = AutoDifferentiation;
8 
9 void
11  constexpr AD::DiffVar<double, 2> x(1, 1, 0);
12  constexpr AD::DiffVar<double, 2> y(2, 0, 1);
13 
14  constexpr auto f = x * y;
15  auto sin = AD::sin(x);
16  auto sin2 = AD::sin(2 * x);
17  auto tanh = AD::tanh(1 + 2 * x);
18 
19  std::cout << "f\n" << f << std::endl;
20  std::cout << "sin\n" << sin << std::endl;
21  std::cout << "sin2\n" << sin2 << std::endl;
22  std::cout << "tanh2\n" << tanh << std::endl;
23 }
24 
25 template<typename T>
26 struct BJTResults {
27  T g_ee;
28  T g_ec;
29  T g_ce;
30  T g_cc;
31 
32  T I_e;
33  T I_c;
34 };
35 
36 template<typename T>
37 void
38 testBJTModelControl(const T & base_v_be, const T & base_v_bc,
39  BJTResults<T> & results) {
40  // The control
41 
42  constexpr T alpha_f = 0.99;
43  constexpr T alpha_r = 0.02;
44 
45  constexpr T I_es = 2e-14;
46  constexpr T V_Te = 26e-3;
47  constexpr T I_cs = 99e-14;
48  constexpr T V_Tc = 26e-3;
49 
50  T control_v_be = base_v_be;
51  T control_v_bc = base_v_bc;
52 
53  T control_i_e = -I_es * (std::exp(control_v_be / V_Te) - 1) +
54  alpha_r * I_cs * (std::exp(control_v_bc / V_Tc) - 1);
55  T control_i_c = alpha_f * I_es * (std::exp(control_v_be / V_Te) - 1) -
56  I_cs * (std::exp(control_v_bc / V_Tc) - 1);
57 
58  T control_g_ee = (I_es / V_Te) * std::exp(control_v_be / V_Te);
59  T control_g_ec = alpha_r * (I_cs / V_Tc) * std::exp(control_v_bc / V_Tc);
60  T control_g_ce = alpha_f * (I_es / V_Te) * std::exp(control_v_be / V_Te);
61  T control_g_cc = (I_cs / V_Tc) * std::exp(control_v_bc / V_Tc);
62 
63  T control_I_e = control_i_e + control_g_ee * control_v_be -
64  control_g_ec * control_v_bc;
65  T control_I_c = control_i_c - control_g_ce * control_v_be +
66  control_g_cc * control_v_bc;
67 
68  results.g_ee = control_g_ee;
69  results.g_ec = control_g_ec;
70  results.g_ce = control_g_ce;
71  results.g_cc = control_g_cc;
72 
73  results.I_e = control_I_e;
74  results.I_c = control_I_c;
75 }
76 
77 template<typename T>
78 void
79 testBJTModelAutoDiff(const T & base_v_be, const T & base_v_bc,
80  BJTResults<T> & results) {
81  // AutoDifferentiation
82  constexpr T alpha_f = 0.99;
83  constexpr T alpha_r = 0.02;
84 
85  constexpr T I_es = 2e-14;
86  constexpr T V_Te = 26e-3;
87  constexpr T I_cs = 99e-14;
88  constexpr T V_Tc = 26e-3;
89  using ADT = AD::DiffVar<T, 2>;
90 
91  ADT ad_v_be = ADT(base_v_be, 1, 0);
92  ADT ad_v_bc = ADT(base_v_bc, 0, 1);
93 
94  ADT ad_i_e = -I_es * (AD::exp(ad_v_be / V_Te) - 1) +
95  alpha_r * I_cs * (AD::exp(ad_v_bc / V_Tc) - 1);
96  ADT ad_i_c = alpha_f * I_es * (AD::exp(ad_v_be / V_Te) - 1) -
97  I_cs * (AD::exp(ad_v_bc / V_Tc) - 1);
98 
99  // Najm defines the g_ee and g_cc to be the negated partial
100  T ad_g_ee = -ad_i_e[1];
101  T ad_g_ec = ad_i_e[2];
102  T ad_g_ce = ad_i_c[1];
103  T ad_g_cc = -ad_i_c[2];
104 
105  T ad_I_e = ad_i_e[0] + ad_g_ee * ad_v_be[0] - ad_g_ec * ad_v_bc[0];
106  T ad_I_c = ad_i_c[0] - ad_g_ce * ad_v_be[0] + ad_g_cc * ad_v_bc[0];
107 
108  results.g_ee = ad_g_ee;
109  results.g_ec = ad_g_ec;
110  results.g_ce = ad_g_ce;
111  results.g_cc = ad_g_cc;
112 
113  results.I_e = ad_I_e;
114  results.I_c = ad_I_c;
115 }
116 
117 template<typename T>
118 [[clang::optnone]] void
120  // Model constants
121  constexpr T I_es = 2e-14;
122  constexpr T V_Te = 26e-3;
123  constexpr T I_cs = 99e-14;
124  constexpr T V_Tc = 26e-3;
125 
126  BJTResults<T> controlResults;
127  BJTResults<T> autoDiffResults;
128 
129  T V_bc_crit = V_Tc * std::log(V_Tc / (I_cs * std::sqrt(2)));
130  T V_be_crit = V_Te * std::log(V_Te / (I_es * std::sqrt(2)));
131 
132  std::array<T, 6> base_v_be_vec = {0, 1, 2, 3, 4, 5};
133  std::array<T, 6> base_v_bc_vec = {0, 1, 2, 3, 4, 5};
134  ;
135 
136  size_t controlAccumulate = 0;
137  size_t autoDiffAccumulate = 0;
138 
139  for (auto base_v_be : base_v_be_vec) {
140  for (auto base_v_bc : base_v_bc_vec) {
141  std::cout << "base_v_be=" << std::setw(10) << base_v_be
142  << ", base_v_bc=" << std::setw(10) << base_v_bc << std::endl;
143 
144  base_v_be = std::min(V_be_crit, base_v_be);
145  base_v_bc = std::min(V_bc_crit, base_v_bc);
146 
147  auto startTime = std::chrono::high_resolution_clock::now();
148  for (size_t i = 0; i < 10000; i++) {
149  testBJTModelControl(base_v_be, base_v_bc, controlResults);
150  }
151  auto endTime = std::chrono::high_resolution_clock::now();
152  auto timeTaken = std::chrono::duration_cast<std::chrono::microseconds>(
153  endTime - startTime)
154  .count();
155  controlAccumulate += timeTaken;
156 
157  std::cout << std::setw(15) << timeTaken << " us | ";
158 
159  startTime = std::chrono::high_resolution_clock::now();
160  for (size_t i = 0; i < 10000; i++) {
161  testBJTModelAutoDiff(base_v_be, base_v_bc, autoDiffResults);
162  }
163  endTime = std::chrono::high_resolution_clock::now();
164  timeTaken = std::chrono::duration_cast<std::chrono::microseconds>(
165  endTime - startTime)
166  .count();
167  autoDiffAccumulate += timeTaken;
168 
169  std::cout << std::setw(15) << timeTaken << " us" << std::endl;
170 
171  // Comparisons
172 
173  std::cout << "g_ee | control=" << std::setw(15) << controlResults.g_ee
174  << " | autoDiff=" << std::setw(15) << autoDiffResults.g_ee
175  << std::endl;
176  std::cout << "g_ec | control=" << std::setw(15) << controlResults.g_ec
177  << " | autoDiff=" << std::setw(15) << autoDiffResults.g_ec
178  << std::endl;
179  std::cout << "g_ce | control=" << std::setw(15) << controlResults.g_ce
180  << " | autoDiff=" << std::setw(15) << autoDiffResults.g_ce
181  << std::endl;
182  std::cout << "g_cc | control=" << std::setw(15) << controlResults.g_cc
183  << " | autoDiff=" << std::setw(15) << autoDiffResults.g_cc
184  << std::endl;
185 
186  std::cout << "I_e | control=" << std::setw(15) << controlResults.I_e
187  << " | autoDiff=" << std::setw(15) << autoDiffResults.I_e
188  << std::endl;
189  std::cout << "I_c | control=" << std::setw(15) << controlResults.I_c
190  << " | autoDiff=" << std::setw(15) << autoDiffResults.I_c
191  << std::endl;
192 
193  assert(std::abs(controlResults.I_e - autoDiffResults.I_e) < 1e-12);
194  assert(std::abs(controlResults.I_c - autoDiffResults.I_c) < 1e-12);
195  }
196  }
197 
198  std::cout << std::setw(15) << controlAccumulate << " us | ";
199  std::cout << std::setw(15) << autoDiffAccumulate << " us" << std::endl;
200 }
201 
202 template<typename T>
204  T var;
205  T diff1;
206  T diff2;
207 };
208 
209 template<typename T>
210 void
212  constexpr T alpha = 1.3;
213  constexpr T beta0 = 0.42;
214  constexpr T gamma = 0.0005;
215  constexpr T delta = 0.3;
216  constexpr T xi = 0.06;
217  constexpr T lambda = 1.5;
218  constexpr T mu = 0.0;
219  constexpr T zeta = 0.18;
220  constexpr T Vto = -2.4;
221 
222  T V_gs = V_gs_in;
223  T V_ds = V_ds_in;
224 
225  auto beta = beta0;
226  auto Vgst = V_gs - (1 + beta * beta) * Vto + gamma * V_ds;
227  auto Veff = 0.5 * (Vgst + std::pow(std::pow(Vgst, 2) + delta * delta, 0.5));
228  auto power = lambda / (1 + mu * std::pow(V_ds, 2) + xi * Veff);
229  auto area = alpha * V_ds * (1 + zeta * Veff);
230  auto f1 = std::tanh(area);
231  auto Ids_lim = beta * std::pow(Veff, power);
232  auto Idrain = Ids_lim * f1;
233  toRet.var = Idrain;
234 
235  auto dVeff_dVgs = 0.5 * (1 + Vgst * std::pow(Vgst * Vgst + delta * delta, -0.5));
236  auto dpower_dVgs = -lambda * xi * dVeff_dVgs * std::pow(power / lambda, 2);
237  auto df_dVgs = std::pow(1 / cosh(area), 2) * alpha * V_ds * zeta * dVeff_dVgs;
238  toRet.diff1 = Idrain *
239  (power * (dVeff_dVgs / Veff) + std::log(Veff) * dpower_dVgs) +
240  Ids_lim * df_dVgs;
241 
242  auto dVeff_dVds = 0.5 * (gamma + std::pow(Vgst * Vgst + delta * delta, -0.5) *
243  Vgst * gamma);
244  auto dpower_dVds = -lambda * (2 * mu * V_ds + xi * dVeff_dVds) *
245  std::pow(power / lambda, 2);
246  auto df_dVds = std::pow(1 / cosh(area), 2) * alpha *
247  (1 + zeta * (V_ds * dVeff_dVds + Veff));
248  toRet.diff2 = Idrain *
249  (power * (dVeff_dVds / Veff) + std::log(Veff) * dpower_dVds) +
250  Ids_lim * df_dVds;
251 }
252 
253 template<typename T>
254 void
255 transistorTestAudoDiff(T V_gs_in, T V_ds_in, AD::DiffVar<T, 2> & toRet) {
256  constexpr T alpha = 1.3;
257  constexpr T beta0 = 0.42;
258  constexpr T gamma = 0.0005;
259  constexpr T delta = 0.3;
260  constexpr T xi = 0.06;
261  constexpr T lambda = 1.5;
262  constexpr T mu = 0.0;
263  constexpr T zeta = 0.18;
264  constexpr T Vto = -2.4;
265 
266  using ADT = AD::DiffVar<T, 2>;
267  ADT V_gs(V_gs_in, 1, 0);
268  ADT V_ds(V_ds_in, 0, 1);
269 
270  auto beta = beta0;
271  auto Vgst = V_gs - (1 + beta * beta) * Vto + gamma * V_ds;
272  auto Veff = 0.5 * (Vgst + AD::sqrt(AD::pow(Vgst, 2) + delta * delta));
273  auto power = lambda / (1 + mu * AD::pow(V_ds, 2) + xi * Veff);
274  auto area = alpha * V_ds * (1 + zeta * Veff);
275  auto f1 = AD::tanh(area);
276  auto Ids_lim = beta * AD::pow(Veff, power);
277  toRet = Ids_lim * f1;
278 }
279 
280 template<typename T>
281 [[clang::optnone]] void
283  using ADT = AD::DiffVar<T, 2>;
284  std::vector<T> V_gs_in_vec = {0, 1, 2, 3};
285  std::vector<T> V_ds_in_vec = {0, 1, 2, 3};
286  size_t controlAccumulate = 0;
287  size_t autoDiffAccumulate = 0;
288  for (auto V_gs_in : V_gs_in_vec) {
289  for (auto V_ds_in : V_gs_in_vec) {
290  ADT autoDiffResult(0);
292  auto startTime = std::chrono::high_resolution_clock::now();
293  for (size_t i = 0; i < 10000; i++) {
294  transistorTestAudoDiff(V_gs_in, V_ds_in, autoDiffResult);
295  }
296  auto endTime = std::chrono::high_resolution_clock::now();
297  auto timeTaken = std::chrono::duration_cast<std::chrono::microseconds>(
298  endTime - startTime)
299  .count();
300  autoDiffAccumulate += timeTaken;
301  std::cout << std::setw(15) << timeTaken << " us | ";
302 
303  startTime = std::chrono::high_resolution_clock::now();
304  for (size_t i = 0; i < 10000; i++) {
305  transistorTestControl(V_gs_in, V_ds_in, res);
306  }
307  endTime = std::chrono::high_resolution_clock::now();
308  timeTaken = std::chrono::duration_cast<std::chrono::microseconds>(
309  endTime - startTime)
310  .count();
311  controlAccumulate += timeTaken;
312  std::cout << std::setw(15) << timeTaken << " us" << std::endl;
313 
314  std::cout << "V_gs: " << V_gs_in << " V_ds: " << V_ds_in << " "
315  << std::endl;
316  std::cout << std::setw(15) << res.var << " ";
317  std::cout << std::setw(15) << res.diff1 << " ";
318  std::cout << std::setw(15) << res.diff2 << std::endl;
319  std::cout << std::setw(15) << autoDiffResult[0] << " ";
320  std::cout << std::setw(15) << autoDiffResult[1] << " ";
321  std::cout << std::setw(15) << autoDiffResult[2] << std::endl
322  << std::endl;
323  assert(std::abs(res.var - autoDiffResult[0]) < 1e-12);
324  assert(std::abs(res.diff1 - autoDiffResult[1]) < 1e-12);
325  assert(std::abs(res.diff2 - autoDiffResult[2]) < 1e-12);
326  }
327  }
328  std::cout << std::setw(15) << autoDiffAccumulate << " us | ";
329  std::cout << std::setw(15) << controlAccumulate << " us" << std::endl;
330 }
331 
332 int
333 main(int argc, char * argv[]) {
335 
336  testBJTModel<double>();
337 
338  transistorTest<double>();
339 
340  return 0;
341 }
int main(int argc, char *argv[])
void testBasicOutput_NoCheck()
void transistorTest()
void testBJTModelAutoDiff(const T &base_v_be, const T &base_v_bc, BJTResults< T > &results)
void testBJTModelControl(const T &base_v_be, const T &base_v_bc, BJTResults< T > &results)
void transistorTestAudoDiff(T V_gs_in, T V_ds_in, AD::DiffVar< T, 2 > &toRet)
void testBJTModel()
void transistorTestControl(T V_gs_in, T V_ds_in, TransistorTestResult< T > &toRet)
f1
Definition: Freq.m:13
Extract these output variables res
for i
Obtain iteration resiudes for model x
Definition: getResidues.m:50
end if abs(real(dotprod))>rstoerst rstoerst
a namespace to hold the messiness of my auto-differentiator
ang(col sin()