JUK1
NLCurrentSource.hpp
Go to the documentation of this file.
1 #ifndef _NLCURRENTSOURCE_HPP_INC_
2 #define _NLCURRENTSOURCE_HPP_INC_
6 
10 template<typename T>
11 struct NLCurrentSource : public Component<T> {
12  public:
13  T value = 0;
14 
15  size_t n1 = 0;
16  size_t n2 = 0;
17 
18  size_t r1_pos = 0;
19  size_t r1_neg = 0;
20  size_t r2_pos = 0;
21  size_t r2_neg = 0;
22 
23  void
24  addNonLinearStampTo(Stamp<T> & stamp, const Matrix<T> & solutionMatrix,
25  const size_t currentSolutionIndex, T timestep = 0) const {
26  constexpr T alpha = 1.3;
27  constexpr T beta0 = 0.42;
28  constexpr T gamma = 0.0005;
29  constexpr T delta = 0.3;
30  constexpr T xi = 0.06;
31  constexpr T lambda = 1.5;
32  constexpr T mu = 0.0;
33  constexpr T zeta = 0.18;
34  constexpr T Vto = -2.4;
35 
36  size_t n1p = n1 - 1;
37  size_t n2p = n2 - 1;
38  size_t r1p_pos = r1_pos - 1;
39  size_t r1p_neg = r1_neg - 1;
40  size_t r2p_pos = r2_pos - 1;
41  size_t r2p_neg = r2_neg - 1;
42 
43  T u = 0;
44  T r1 = 0;
45  T r2 = 0;
46 
47  if (n1 > 0) {
48  u = solutionMatrix(n1p, currentSolutionIndex);
49  }
50 
51  if (n2 > 0) {
52  u -= solutionMatrix(n2p, currentSolutionIndex);
53  }
54 
55  if (r1_pos > 0) {
56  r1 = solutionMatrix(r1p_pos, currentSolutionIndex);
57  }
58 
59  if (r1_neg > 0) {
60  r1 -= solutionMatrix(r1p_neg, currentSolutionIndex);
61  }
62 
63  if (r2_pos > 0) {
64  r2 = solutionMatrix(r2p_pos, currentSolutionIndex);
65  }
66 
67  if (r2_neg > 0) {
68  r2 -= solutionMatrix(r2p_neg, currentSolutionIndex);
69  }
70 
71  namespace AD = AutoDifferentiation;
72 
73  using ADT = AD::DiffVar<T, 2>;
74  ADT V_gs(r1, 1, 0);
75  ADT V_ds(r2, 0, 1);
76 
77  auto beta = beta0;
78  auto Vgst = V_gs - (1 + beta * beta) * Vto + gamma * V_ds;
79  auto Veff = 0.5 * (Vgst + AD::sqrt(AD::pow(Vgst, 2) + delta * delta));
80  auto power = lambda / (1 + mu * AD::pow(V_ds, 2) + xi * Veff);
81  auto area = alpha * V_ds * (1 + zeta * Veff);
82  auto f1 = AD::tanh(area);
83  auto Ids_lim = beta * AD::pow(Veff, power);
84  auto Idrain = Ids_lim * f1;
85  auto I_ds = Idrain[0] - Idrain[1] * r1 - Idrain[2] * r2;
86 
87  if (n1 > 0) {
88  stamp.s(n1p, 0) += -I_ds;
89  if (r1_pos > 0) {
90  stamp.G(n1p, r1p_pos) += Idrain[1];
91  }
92  if (r1_neg > 0) {
93  stamp.G(n1p, r1p_neg) += -Idrain[1];
94  }
95  if (r2_pos > 0) {
96  stamp.G(n1p, r2p_pos) += Idrain[2];
97  }
98  if (r2_neg > 0) {
99  stamp.G(n1p, r2p_neg) += -Idrain[2];
100  }
101  }
102 
103  if (n2 > 0) {
104  stamp.s(n2p, 0) += +I_ds;
105  if (r1_pos > 0) {
106  stamp.G(n2p, r1p_pos) += -Idrain[1];
107  }
108  if (r1_neg > 0) {
109  stamp.G(n2p, r1p_neg) += Idrain[1];
110  }
111  if (r2_pos > 0) {
112  stamp.G(n2p, r2p_pos) += -Idrain[2];
113  }
114  if (r2_neg > 0) {
115  stamp.G(n2p, r2p_neg) += Idrain[2];
116  }
117  }
118  }
119 
120  void addDCAnalysisStampTo(Stamp<T> & stamp, const Matrix<T> & solutionVector,
121  size_t numCurrents) const {
122  addNonLinearStampTo(stamp, solutionVector, 0, 0);
123  }
124 
125 
126  static void
127  addToElements(const std::string & line, CircuitElements<T> & elements,
128  size_t & numNodes, size_t & numCurrents, size_t & numDCCurrents) {
129  std::regex currentSourceRegex = generateRegex("I", "n n n n n n");
130  NLCurrentSource<T> currentSource;
131  std::smatch matches;
132 
133  std::regex_match(line, matches, currentSourceRegex);
134  currentSource.n1 = std::stoi(matches.str(2));
135  currentSource.n2 = std::stoi(matches.str(3));
136  currentSource.r1_pos = std::stoi(matches.str(4));
137  currentSource.r1_neg = std::stoi(matches.str(5));
138  currentSource.r2_pos = std::stoi(matches.str(6));
139  currentSource.r2_neg = std::stoi(matches.str(7));
140 
141  numNodes = std::max(numNodes, std::stoull(matches.str(2)));
142  numNodes = std::max(numNodes, std::stoull(matches.str(3)));
143  numNodes = std::max(numNodes, std::stoull(matches.str(4)));
144  numNodes = std::max(numNodes, std::stoull(matches.str(5)));
145  numNodes = std::max(numNodes, std::stoull(matches.str(6)));
146  numNodes = std::max(numNodes, std::stoull(matches.str(7)));
147 
148  elements.nonLinearElements.emplace_back(
149  std::make_shared<NLCurrentSource<T> >(currentSource));
150  }
151 };
152 
153 #endif
std::regex generateRegex(std::string indentifier, std::string simplifiedMatching, bool startAnchor=true, bool endAnchor=true)
a helper function to aid in the construction of regexes for parsing netlist files
f1
Definition: Freq.m:13
common weighting for all matrix elements
Definition: QPpassive.m:47
a namespace to hold the messiness of my auto-differentiator
a glorified container for the different types of components.
A template base class to define the fundamental things a component should define.
Definition: Component.hpp:108
A matrix class with support for LU-decomposition, and left division.
An non-linear current source for the COBRA transistor model.
static void addToElements(const std::string &line, CircuitElements< T > &elements, size_t &numNodes, size_t &numCurrents, size_t &numDCCurrents)
void addNonLinearStampTo(Stamp< T > &stamp, const Matrix< T > &solutionMatrix, const size_t currentSolutionIndex, T timestep=0) const
adds this component's non-linear stamp to the target stamp.
void addDCAnalysisStampTo(Stamp< T > &stamp, const Matrix< T > &solutionVector, size_t numCurrents) const
adds this component's DC stamp to the target stamp.
A helper struct to store the preallocated stamps for MNA.
Definition: Component.hpp:23
Matrix< T > s
Definition: Component.hpp:28
Matrix< T > G
Definition: Component.hpp:27