-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathSimulation.cpp
More file actions
212 lines (160 loc) · 7.4 KB
/
Simulation.cpp
File metadata and controls
212 lines (160 loc) · 7.4 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include "Simulation.h"
//Default Constructor with default values for samplerate and vcc
//Constructor with Args, calls the superclass constructor with the same sampleRate
Simulation::Simulation(double _sampleRate, double _vcc) : Circuit(_sampleRate)
{
//initialise sim values
initialiseSimValues();
//set vcc to _vcc
vcc = _vcc;
//Initialise the matrices used in simulation
initialiseSimulationParameters();
//Get the system to a steady State
getSteadyState();
}
void Simulation::initialiseSimValues() {
vcc = DEFAULT_VCC; //steady state voltage
durfade = DURFADE; //duration of the faded power up
steadyStatePeriodFactor = STEADY_STATE_FACTOR; //Factor which controls the size of the window window used to reach steady state (where window size in samples = hanWin*steadyStateFactor)
maxIterations = MAX_ITERATIONS;
maxSubIterations = MAX_SUB_ITERATIONS;
//Specified tolerance in nonlinear voltage vd
tol = TOL;
//tol^2, used for end conditions of the NR solver
tols = tol*tol;
}
//Initialise the matrices used in the simulation
void Simulation::initialiseSimulationParameters() {
//Set up a 3x1 vector stateVector and set all vals to 0 - xz
stateSpaceVectorMem.setZero();
//Set up a 4x1 vector vdVector and set all vals to 0 - vdz
nonLinVoltageVectorMem.setZero();
//Set up a 2x1 vector inputVector and set all vals to 0 - u
inputVector.setZero();
}
//Get the system to steady state ready for processing
void Simulation::getSteadyState() {
//zero input used as signal for warmup phase / getSteadyState
float* zeroInput = new float(ZERO_INPUT);
//hanWin value is used to get to steady state
hanWin = (int)ceil(durfade * sampleRate);
//TM = 1./hanWin
//Declare the variable TM used in the time vector
samplePeriod = 1 / sampleRate;
//Resize the vccv vector to match hanWin
vccv.resize(hanWin);
//Resize the win vector to match 2*hanWin
win.resize(2 * hanWin);
/*VCCV Hanning multiplier to achieve steady state*/
//Hanning win multiplier
for (int i = 0; i < 2 * hanWin; i++) {
//calculate the hanning value at angle "i"
double multiplier = 0.5*(1 - cos((2 * PI * i) / (2 * hanWin - 1)));
//set the value at index win(i) equal to the multiplier
win(i) = multiplier;
}
//Population loop, populates the vcc dummyData
for (int i = 0; i < hanWin; i++) {
//Multiply vcc by the ramp up section to get ramp up voltage
//Multiply the hanning value by max voltage vcc at index "i" and input into vccv
vccv(i) = win(i) * vcc;
}
//process until steady state is reached
for (int i = 0; i < hanWin*steadyStatePeriodFactor; i++) {
//Process the full hanWin window then pad the rest of the vccv values with vcc = 9;
if (i < hanWin) {
processSample(zeroInput, vccv(i));
}
else {
processSample(zeroInput, vcc);
}
}
//Get rid of the zeroInput pointer to free the memory
delete zeroInput;
zeroInput = NULL;
}
//Process the incoming sample
void Simulation::processSample(float* _channelData, double _vcc) {
inputVector(0) = *_channelData; //sets the input vector equal to the input channelData
inputVector(1) = _vcc;
//Prepare the nonlinear solver
//pd = Kdinv*(G*xz + H*u);
nonLinSolverInput = (alteredStateSpaceK.inverse())*(stateSpaceG*stateSpaceVectorMem + stateSpaceH*inputVector); //define input to the Nonlinear equation --- MATLAB pd
nonLinVoltageVector = nonLinVoltageVectorMem; //sets the nonlinVoltageVector as the memorised vector vd = vdz
nrms = 1.; //sets the nrms high to begin with
iteration = 0;
subIterationTotal = 0;
while (nrms > tols && iteration < maxIterations) {
//TERM = IS*exp(vd/VT);
calcTemp = saturationCurrent * (nonLinVoltageVector / thermalVoltage).array().exp();
//f = TERM - IS;
nonLinTransistorFunction = calcTemp.array() - saturationCurrent;
//fd = diag(TERM/VT);
nonLinTransistorFunctionAltered = (calcTemp / thermalVoltage).asDiagonal();
//g = M*vd + f - pd;
nodalDKNonlinearG = (nonLinEquationMatrix * nonLinVoltageVector) //M*vd
+ nonLinTransistorFunction //+ f
- nonLinSolverInput; //- pd
//gd = M + fd;
nodalDKNonlinearGAltered = nonLinEquationMatrix + nonLinTransistorFunctionAltered;
//STEP = gd\g;
newtonStep = nodalDKNonlinearGAltered.inverse() * nodalDKNonlinearG;
//vdnew = vd - STEP;
nonLinVoltageVectorNew = nonLinVoltageVector - newtonStep;
//gnew = M*vdnew + IS*(exp(vdnew/VT) - 1) - pd;
nodalDKNonlinearGNew = (nonLinEquationMatrix * nonLinVoltageVectorNew) + //M*vdnew +
(saturationCurrent* ((nonLinVoltageVectorNew / thermalVoltage).array().exp() - 1).matrix()) //IS*(exp(vdnew/VT) - 1)
- nonLinSolverInput; //-pd
//m = 0
subIterCounter = 0;
//STP = STEP;
newtonStepTemp = newtonStep;
while ((nodalDKNonlinearGNew.squaredNorm() > (nodalDKNonlinearG.squaredNorm())) && subIterCounter < maxSubIterations)
{
//m = m+1
subIterCounter++;
//STP = (2^(-m))*STEP; % adjusted step
newtonStepTemp.array() /= 2.; //half the step with each iteration
//vdnew = vd - STP
nonLinVoltageVectorNew = nonLinVoltageVector - newtonStepTemp;
//gnew = M*vdnew + IS*(exp(vdnew/VT) - 1) - pd;
nodalDKNonlinearGNew = (nonLinEquationMatrix * nonLinVoltageVectorNew) + //M*vdnew +
(saturationCurrent* ((nonLinVoltageVectorNew / thermalVoltage).array().exp() - 1).matrix()) //IS*(exp(vdnew/VT) - 1)
- nonLinSolverInput; //-pd
}
//nrms = STP'*STP;
nrms = newtonStepTemp.squaredNorm(); //squared norm used to limit iterations
//vd = vdnew;
nonLinVoltageVector = nonLinVoltageVectorNew; //set the nonLinVoltageVector to the new value after calculation
//subiter = subiter + m;
subIterationTotal += subIterCounter; //keep track of the subiterations
//iter = iter + 1;
iteration++; //keep track of the iterations
}
//Update nonlinear currents, state and output
nonLinearCurrent = psi * (saturationCurrent*((nonLinVoltageVector / thermalVoltage).array().exp() - 1).matrix()); // i = PSI*(IS*(exp(vd/VT) - 1));
stateSpaceVector = (stateSpaceA * stateSpaceVectorMem) + (stateSpaceB*inputVector) + (stateSpaceC*nonLinearCurrent); // x = A*xz + B*u + C*i;
output = ((stateSpaceD*stateSpaceVectorMem) + (stateSpaceE*inputVector) + (stateSpaceF*nonLinearCurrent))(0); // y = D*xz + E*u + F*i
//when declaring output = RHS, the RHS is technically an Eigen Vector of size 1x1, so you must use the (0) to select the value at index 0
stateSpaceVectorMem = stateSpaceVector; //xz = x; Memorise the stateSpaceVector
nonLinVoltageVectorMem = nonLinVoltageVector; //vdz = vd; Memorise the nonLinVoltageVector
*_channelData = output;
//return output; //returns the processed sample
}
//Set the sampleRate and return the system to steady state
void Simulation::setSimSampleRate(double _sampleRate)
{
setCircuitSampleRate(_sampleRate);
sampleRate = _sampleRate;
//Sets up the statespace matrices used in the simulation
refreshFullCircuit();
//Initialise the matrices used in simulation
initialiseSimulationParameters();
//Get the system to a steady State
getSteadyState();
}
//Default Destructor
Simulation::~Simulation()
{
std::cout << "end sim" << std::endl;
}