1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
#include <stdio.h>
#include <inttypes.h>
#include <cmath>
#include "triode.h"
using std::abs;
#define DUMP(x) x
T Triode::compute(T a, T R, T Vg, T Vk) {
T Vgk = Vg - Vk;
T VakGuess = -mu * Vgk;
T Vak = VakGuess;
int iteration = 0;
T err = 1e6;
T b;
for (iteration = 0; (fabs(err)/fabs(Vak) > EPSILON) && (iteration <= ITER); iteration++){
VakGuess = iterateNewtonRaphson(Vak, TOLERANCE, Vgk, a, R);
err = Vak - VakGuess;
Vak = VakGuess;
}
b = Vak - R*getIa(Vgk, Vak);
//printf("Vgate=%f Vk=%f Vgk=%f b=%f\n", Vgate, Vk, Vgk, b);
return b;
}
T Triode::getIa(T Vgk, T Vpk) const {
if (Vpk < 0.0) {
Vpk = 0.0;
}
if (Vgk > 0.0) {
Vgk = 0.0;
}
/* exact solution (expensive) */
T ee1 = Vpk*log1p(exp(kp*(1./mu+Vgk/sqrt(kvb+Vpk*Vpk))))/kp;
if (ee1 < 0) {
return 0.;
}
//printf("Vpk=%f ans=%f e1=%f exact_e1=%f\n", Vpk, ans, e1, ee1);
return 1e+6*pow(ee1, kx) / kg1;
}
T Triode::iterateNewtonRaphson(T x, T dx, T Vgk, T a, T R) const {
T xIak = getIa(Vgk, x);
T dxIak = getIa(Vgk, x + dx);
T xNew = x - dx*(x + R*xIak - a)/(dx + R*(dxIak - xIak));
return xNew;
}
Triode::Triode()
{
/* good for low gain, broken at high gain
kvb = 300.;
mu = 103.2;
kx = 1.26;
kg1 = 446.0;
kp = 3.4;
*/
//12AX7 RSD-1 (custom)
mu = 100.;
kx = 1.4;
kg1 = 1060.;
kp = 600.;
kvb = 300.;
}
|