9 #include <dpsim-models/MathUtils.h>
14 Real Math::radtoDeg(Real rad) {
return rad * 180 / PI; }
16 Real Math::degToRad(Real deg) {
return deg * PI / 180; }
18 Real Math::phase(Complex value) {
return std::arg(value); }
20 Real Math::phaseDeg(Complex value) {
return radtoDeg(phase(value)); }
22 Real Math::abs(Complex value) {
return std::abs(value); }
24 Matrix Math::abs(
const MatrixComp &mat) {
25 size_t nRows = mat.rows();
26 size_t nCols = mat.cols();
27 Matrix res(mat.rows(), mat.cols());
29 for (
size_t i = 0; i < nRows; ++i) {
30 for (
size_t j = 0; j < nCols; ++j) {
31 res(i, j) = std::abs(mat(i, j));
37 Matrix Math::phase(
const MatrixComp &mat) {
38 size_t nRows = mat.rows();
39 size_t nCols = mat.cols();
40 Matrix res(mat.rows(), mat.cols());
42 for (
size_t i = 0; i < nRows; ++i) {
43 for (
size_t j = 0; j < nCols; ++j) {
44 res(i, j) = std::arg(mat(i, j));
50 Complex Math::polar(Real abs, Real phase) {
51 return std::polar<Real>(abs, phase);
54 Complex Math::polarDeg(Real abs, Real phase) {
55 return std::polar<Real>(abs, radtoDeg(phase));
58 void Math::setVectorElement(Matrix &mat, Matrix::Index row, Complex value,
59 Int maxFreq, Int freqIdx, Matrix::Index colOffset) {
60 Eigen::Index harmonicOffset = mat.rows() / maxFreq;
61 Eigen::Index complexOffset = harmonicOffset / 2;
62 Eigen::Index harmRow = row + harmonicOffset * freqIdx;
64 mat(harmRow, colOffset) = value.real();
65 mat(harmRow + complexOffset, colOffset) = value.imag();
68 void Math::addToVectorElement(Matrix &mat, Matrix::Index row, Complex value,
69 Int maxFreq, Int freqIdx) {
70 Eigen::Index harmonicOffset = mat.rows() / maxFreq;
71 Eigen::Index complexOffset = harmonicOffset / 2;
72 Eigen::Index harmRow = row + harmonicOffset * freqIdx;
74 mat(harmRow, 0) = mat(harmRow, 0) + value.real();
75 mat(harmRow + complexOffset, 0) =
76 mat(harmRow + complexOffset, 0) + value.imag();
79 Complex Math::complexFromVectorElement(
const Matrix &mat, Matrix::Index row,
80 Int maxFreq, Int freqIdx) {
81 Eigen::Index harmonicOffset = mat.rows() / maxFreq;
82 Eigen::Index complexOffset = harmonicOffset / 2;
83 Eigen::Index harmRow = row + harmonicOffset * freqIdx;
85 return Complex(mat(harmRow, 0), mat(harmRow + complexOffset, 0));
88 void Math::addToVectorElement(Matrix &mat, Matrix::Index row, Real value) {
89 mat(row, 0) = mat(row, 0) + value;
92 void Math::setVectorElement(Matrix &mat, Matrix::Index row, Real value) {
96 Real Math::realFromVectorElement(
const Matrix &mat, Matrix::Index row) {
100 void Math::setMatrixElement(SparseMatrixRow &mat, Matrix::Index row,
101 Matrix::Index column, Complex value, Int maxFreq,
104 Eigen::Index harmonicOffset = mat.rows() / maxFreq;
105 Eigen::Index complexOffset = harmonicOffset / 2;
106 Eigen::Index harmRow = row + harmonicOffset * freqIdx;
107 Eigen::Index harmCol = column + harmonicOffset * freqIdx;
109 mat.coeffRef(harmRow, harmCol) = value.real();
110 mat.coeffRef(harmRow + complexOffset, harmCol + complexOffset) = value.real();
111 mat.coeffRef(harmRow, harmCol + complexOffset) = -value.imag();
112 mat.coeffRef(harmRow + complexOffset, harmCol) = value.imag();
115 void Math::addToMatrixElement(SparseMatrixRow &mat, Matrix::Index row,
116 Matrix::Index column, Complex value, Int maxFreq,
119 Eigen::Index harmonicOffset = mat.rows() / maxFreq;
120 Eigen::Index complexOffset = harmonicOffset / 2;
121 Eigen::Index harmRow = row + harmonicOffset * freqIdx;
122 Eigen::Index harmCol = column + harmonicOffset * freqIdx;
124 mat.coeffRef(harmRow, harmCol) += value.real();
125 mat.coeffRef(harmRow + complexOffset, harmCol + complexOffset) +=
127 mat.coeffRef(harmRow, harmCol + complexOffset) -= value.imag();
128 mat.coeffRef(harmRow + complexOffset, harmCol) += value.imag();
131 void Math::addToMatrixElement(SparseMatrixRow &mat, Matrix::Index row,
132 Matrix::Index column, Matrix value, Int maxFreq,
135 Eigen::Index harmonicOffset = mat.rows() / maxFreq;
136 Eigen::Index complexOffset = harmonicOffset / 2;
137 Eigen::Index harmRow = row + harmonicOffset * freqIdx;
138 Eigen::Index harmCol = column + harmonicOffset * freqIdx;
140 mat.coeffRef(harmRow, harmCol) += value(0, 0);
141 mat.coeffRef(harmRow + complexOffset, harmCol + complexOffset) += value(1, 1);
142 mat.coeffRef(harmRow, harmCol + complexOffset) += value(0, 1);
143 mat.coeffRef(harmRow + complexOffset, harmCol) += value(1, 0);
146 void Math::setMatrixElement(SparseMatrixRow &mat, Matrix::Index row,
147 Matrix::Index column, Real value) {
148 mat.coeffRef(row, column) = value;
151 void Math::addToMatrixElement(SparseMatrixRow &mat, std::vector<UInt> rows,
152 std::vector<UInt> columns, Complex value) {
153 for (UInt phase = 0; phase < rows.size(); phase++)
154 addToMatrixElement(mat, rows[phase], columns[phase], value);
157 void Math::addToMatrixElement(SparseMatrixRow &mat, Matrix::Index row,
158 Matrix::Index column, Real value) {
159 mat.coeffRef(row, column) = mat.coeff(row, column) + value;
162 void Math::addToMatrixElement(SparseMatrixRow &mat, std::vector<UInt> rows,
163 std::vector<UInt> columns, Real value) {
164 for (UInt phase = 0; phase < rows.size(); phase++)
165 addToMatrixElement(mat, rows[phase], columns[phase], value);
168 void Math::invertMatrix(
const Matrix &mat, Matrix &matInv) {
169 const Int n = Eigen::internal::convert_index<Int>(mat.cols());
171 const Real determinant = mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0);
172 matInv(0, 0) = mat(1, 1) / determinant;
173 matInv(0, 1) = -mat(0, 1) / determinant;
174 matInv(1, 0) = -mat(1, 0) / determinant;
175 matInv(1, 1) = mat(0, 0) / determinant;
177 const Real determinant =
178 (mat(0, 0) * mat(1, 1) * mat(2, 2) + mat(0, 1) * mat(1, 2) * mat(2, 0) +
179 mat(1, 0) * mat(2, 1) * mat(0, 2)) -
180 (mat(2, 0) * mat(1, 1) * mat(0, 2) + mat(1, 0) * mat(0, 1) * mat(2, 2) +
181 mat(2, 1) * mat(1, 2) * mat(0, 0));
183 (mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1)) / determinant;
185 (mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2)) / determinant;
187 (mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1)) / determinant;
189 (mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2)) / determinant;
191 (mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0)) / determinant;
193 (mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2)) / determinant;
195 (mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0)) / determinant;
197 (mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1)) / determinant;
199 (mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0)) / determinant;
201 matInv = mat.inverse();
206 MatrixComp var_3ph = MatrixComp::Zero(3, 1);
207 var_3ph << var_1ph, var_1ph * SHIFT_TO_PHASE_B, var_1ph * SHIFT_TO_PHASE_C;
212 Matrix param_3ph = Matrix::Zero(3, 3);
213 param_3ph << parameter, 0., 0., 0., parameter, 0., 0, 0., parameter;
218 Matrix power_3ph = Matrix::Zero(3, 3);
219 power_3ph << power / 3., 0., 0., 0., power / 3., 0., 0, 0., power / 3.;
223 Matrix Math::StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix B, Real dt,
224 Matrix u_new, Matrix u_old) {
225 Matrix::Index n = states.rows();
226 Matrix I = Matrix::Identity(n, n);
228 Matrix F1 = I + (dt / 2.) * A;
229 Matrix F2 = I - (dt / 2.) * A;
230 Matrix F2inv = F2.inverse();
232 return F2inv * F1 * states + F2inv * (dt / 2.) * B * (u_new + u_old);
235 Matrix Math::StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix B, Matrix C,
236 Real dt, Matrix u_new, Matrix u_old) {
237 Matrix::Index n = states.rows();
238 Matrix I = Matrix::Identity(n, n);
240 Matrix F1 = I + (dt / 2.) * A;
241 Matrix F2 = I - (dt / 2.) * A;
242 Matrix F2inv = F2.inverse();
244 return F2inv * F1 * states + F2inv * (dt / 2.) * B * (u_new + u_old) +
248 Matrix Math::StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix B, Matrix C,
250 Matrix::Index n = states.rows();
251 Matrix I = Matrix::Identity(n, n);
253 Matrix F1 = I + (dt / 2.) * A;
254 Matrix F2 = I - (dt / 2.) * A;
255 Matrix F2inv = F2.inverse();
257 return F2inv * F1 * states + F2inv * dt * B * u + F2inv * dt * C;
260 Real Math::StateSpaceTrapezoidal(Real states, Real A, Real B, Real C, Real dt,
262 Real F1 = 1. + (dt / 2.) * A;
263 Real F2 = 1. - (dt / 2.) * A;
264 Real F2inv = 1. / F2;
266 return F2inv * F1 * states + F2inv * dt * B * u + F2inv * dt * C;
269 Matrix Math::StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix B, Real dt,
271 Matrix::Index n = states.rows();
272 Matrix I = Matrix::Identity(n, n);
274 Matrix F1 = I + (dt / 2.) * A;
275 Matrix F2 = I - (dt / 2.) * A;
276 Matrix F2inv = F2.inverse();
278 return F2inv * F1 * states + F2inv * dt * B * u;
281 Matrix Math::StateSpaceTrapezoidal(Matrix states, Matrix A, Matrix input,
283 Matrix::Index n = states.rows();
284 Matrix I = Matrix::Identity(n, n);
286 Matrix F1 = I + (dt / 2.) * A;
287 Matrix F2 = I - (dt / 2.) * A;
288 Matrix F2inv = F2.inverse();
290 return F2inv * F1 * states + F2inv * dt * input;
293 Real Math::StateSpaceTrapezoidal(Real states, Real A, Real B, Real dt, Real u) {
294 Real F1 = 1. + (dt / 2.) * A;
295 Real F2 = 1. - (dt / 2.) * A;
296 Real F2inv = 1. / F2;
298 return F2inv * F1 * states + F2inv * dt * B * u;
301 Matrix Math::StateSpaceEuler(Matrix states, Matrix A, Matrix B, Real dt,
303 return states + dt * (A * states + B * u);
306 Real Math::StateSpaceEuler(Real states, Real A, Real B, Real dt, Real u) {
307 return states + dt * (A * states + B * u);
310 Matrix Math::StateSpaceEuler(Matrix states, Matrix A, Matrix B, Matrix C,
312 return states + dt * (A * states + B * u + C);
315 Real Math::StateSpaceEuler(Real states, Real A, Real B, Real C, Real dt,
317 return states + dt * (A * states + B * u + C);
320 Matrix Math::StateSpaceEuler(Matrix states, Matrix A, Matrix input, Real dt) {
321 return states + dt * (A * states + input);
327 const Real &dt, Matrix &Ad,
328 Matrix &Bd, Matrix &Cd) {
329 Matrix::Index n = A.rows();
330 Matrix I = Matrix::Identity(n, n);
332 Matrix F1 = I + (dt / 2.) * A;
333 Matrix F2 = I - (dt / 2.) * A;
334 Matrix F2inv = F2.inverse();
337 Bd = F2inv * (dt / 2.) * B;
344 const Matrix &statesPrevStep,
345 const Matrix &inputCurrStep,
346 const Matrix &inputPrevStep) {
347 return Ad * statesPrevStep + Bd * (inputCurrStep + inputPrevStep) + Cd;
350 void Math::FFT(std::vector<Complex> &samples) {
352 size_t N = samples.size();
355 double thetaT = M_PI / N;
356 Complex phiT = Complex(cos(thetaT), -sin(thetaT)), T;
362 for (
size_t l = 0; l < k; l++) {
363 for (
size_t a = l; a < N; a += n) {
365 Complex t = samples[a] - samples[b];
366 samples[a] += samples[b];
373 UInt m =
static_cast<UInt
>(log2(N));
374 for (UInt a = 0; a < N; a++) {
377 b = (((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1));
378 b = (((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2));
379 b = (((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4));
380 b = (((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8));
381 b = ((b >> 16) | (b << 16)) >> (32 - m);
383 Complex t = samples[a];
384 samples[a] = samples[b];
390 Complex Math::rotatingFrame2to1(Complex f2, Real theta1, Real theta2) {
391 Real delta = theta2 - theta1;
392 Real f1_real = f2.real() * cos(delta) - f2.imag() * sin(delta);
393 Real f1_imag = f2.real() * sin(delta) + f2.imag() * cos(delta);
394 return Complex(f1_real, f1_imag);
static Matrix singlePhasePowerToThreePhase(Real power)
To convert single phase power to symmetrical three phase.
static void calculateStateSpaceTrapezoidalMatrices(const Matrix &A, const Matrix &B, const Matrix &C, const Real &dt, Matrix &Ad, Matrix &Bd, Matrix &Cd)
Calculate the discretized state space matrices Ad, Bd, Cd using trapezoidal rule.
static Matrix applyStateSpaceTrapezoidalMatrices(const Matrix &Ad, const Matrix &Bd, const Matrix &Cd, const Matrix &statesPrevStep, const Matrix &inputCurrStep, const Matrix &inputPrevStep)
Apply the trapezoidal based state space matrices Ad, Bd, Cd to get the states at the current time ste...
static Matrix singlePhaseParameterToThreePhase(Real parameter)
To convert single phase parameters to symmetrical three phase ones.
static MatrixComp singlePhaseVariableToThreePhase(Complex var_1ph)
To convert single phase complex variables (voltages, currents) to symmetrical three phase ones.