DPsim
Loading...
Searching...
No Matches
DP_Ph1_AvVoltSourceInverterStateSpace.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University
2// SPDX-License-Identifier: MPL-2.0
3
4#include <cmath>
5#include <stdexcept>
6
8
9using namespace CPS;
10
13 : MixedVTypeVariableSSNComp(uid, name, 8, 2, logLevel), mLf(0.0), mCf(0.0),
14 mRf(0.0), mRc(0.0), mOmegaN(0.0), mKpPLL(0.0), mKiPLL(0.0),
15 mOmegaCutoff(0.0), mPRef(0.0), mQRef(0.0), mKpPowerCtrl(0.0),
16 mKiPowerCtrl(0.0), mKpCurrCtrl(0.0), mKiCurrCtrl(0.0),
17 mVcD(mAttributes->create<Real>("vc_d")),
18 mVcQ(mAttributes->create<Real>("vc_q")),
19 mIrcD(mAttributes->create<Real>("irc_d")),
20 mIrcQ(mAttributes->create<Real>("irc_q")),
21 mPInst(mAttributes->create<Real>("p_inst")),
22 mQInst(mAttributes->create<Real>("q_inst")),
23 mOmegaPLL(mAttributes->create<Real>("omega_pll")) {
24 **mVcD = 0.0;
25 **mVcQ = 0.0;
26 **mIrcD = 0.0;
27 **mIrcQ = 0.0;
28 **mPInst = 0.0;
29 **mQInst = 0.0;
30 **mOmegaPLL = 0.0;
31}
32
34 Real lf, Real cf, Real rf, Real rc, Real omegaN, Real kpPLL, Real kiPLL,
35 Real omegaCutoff, Real pRef, Real qRef, Real kpPowerCtrl, Real kiPowerCtrl,
36 Real kpCurrCtrl, Real kiCurrCtrl) {
37 if (lf <= 0.0)
38 throw std::invalid_argument("Filter inductance lf must be positive.");
39
40 if (cf <= 0.0)
41 throw std::invalid_argument("Filter capacitance cf must be positive.");
42
43 if (rf < 0.0)
44 throw std::invalid_argument("Filter resistance rf must be non-negative.");
45
46 if (rc <= 0.0)
47 throw std::invalid_argument("Coupling resistance rc must be positive.");
48
49 if (omegaN <= 0.0)
50 throw std::invalid_argument(
51 "Nominal angular frequency omegaN must be positive.");
52
53 if (omegaCutoff < 0.0)
54 throw std::invalid_argument(
55 "Power-filter cutoff frequency omegaCutoff must be non-negative.");
56
57 if (kiPLL == 0.0)
58 throw std::invalid_argument("PLL integral gain kiPLL must be non-zero.");
59
60 if (kiPowerCtrl == 0.0)
61 throw std::invalid_argument(
62 "Power-control integral gain kiPowerCtrl must be non-zero.");
63
64 if (kiCurrCtrl == 0.0)
65 throw std::invalid_argument(
66 "Current-control integral gain kiCurrCtrl must be non-zero.");
67
68 mLf = lf;
69 mCf = cf;
70 mRf = rf;
71 mRc = rc;
72
73 mOmegaN = omegaN;
74 mKpPLL = kpPLL;
75 mKiPLL = kiPLL;
76
77 mOmegaCutoff = omegaCutoff;
78 mPRef = pRef;
79 mQRef = qRef;
80 mKpPowerCtrl = kpPowerCtrl;
81 mKiPowerCtrl = kiPowerCtrl;
82 mKpCurrCtrl = kpCurrCtrl;
83 mKiCurrCtrl = kiCurrCtrl;
84
85 const Matrix x0 = Matrix::Zero(12, 1);
86 const Matrix u0 = Matrix::Zero(2, 1);
87
88 Matrix aMatrix, bMatrix, cMatrix, dMatrix, eVector, fVector;
89 buildStateSpaceModel(x0, u0, aMatrix, bMatrix, cMatrix, dMatrix, eVector,
90 fVector);
91
92 MixedVTypeVariableSSNComp::setParameters(aMatrix, bMatrix, cMatrix, dMatrix,
93 eVector, fVector);
94}
95
96void DP::Ph1::AvVoltSourceInverterStateSpace::buildStateSpaceModel(
97 const Matrix &x, const Matrix &u, Matrix &A, Matrix &B, Matrix &C,
98 Matrix &D, Matrix &E, Matrix &F) const {
99 // 1) Unpack the operating point. psi := theta0 - thetaN (never a state itself).
100 const Real psi = x(Psi, 0);
101 const Real pF = x(PFiltered, 0);
102 const Real qF = x(QFiltered, 0);
103 const Real phiD = x(PhiD, 0);
104 const Real phiQ = x(PhiQ, 0);
105 const Real gammaD = x(GammaD, 0);
106 const Real gammaQ = x(GammaQ, 0);
107 const Real vcRe = x(VcRe, 0);
108 const Real vcIm = x(VcIm, 0);
109 const Real ifRe = x(IfRe, 0);
110 const Real ifIm = x(IfIm, 0);
111
112 const Real uRe = u(0, 0);
113 const Real uIm = u(1, 0);
114
115 const Real cosPsi = std::cos(psi);
116 const Real sinPsi = std::sin(psi);
117
118 // 2) dq measurements: Vc*e^{-j*psi} and Irc*e^{-j*psi}, Irc = (Vc-U)/Rc.
119 const Real vcD = vcRe * cosPsi + vcIm * sinPsi;
120 const Real vcQ = vcIm * cosPsi - vcRe * sinPsi;
121
122 const Real ircRe = (vcRe - uRe) / mRc;
123 const Real ircIm = (vcIm - uIm) / mRc;
124 const Real ircD = ircRe * cosPsi + ircIm * sinPsi;
125 const Real ircQ = ircIm * cosPsi - ircRe * sinPsi;
126
127 // Jacobian of vcQ (only vq feeds the PLL rows).
128 const Real dVcQByPsi = -vcIm * sinPsi - vcRe * cosPsi;
129 const Real dVcQByVcRe = -sinPsi;
130 const Real dVcQByVcIm = cosPsi;
131
132 // Jacobian of ircD, ircQ.
133 const Real dIrcDByPsi = -ircRe * sinPsi + ircIm * cosPsi;
134 const Real dIrcDByVcRe = cosPsi / mRc;
135 const Real dIrcDByVcIm = sinPsi / mRc;
136 const Real dIrcDByURe = -cosPsi / mRc;
137 const Real dIrcDByUIm = -sinPsi / mRc;
138
139 const Real dIrcQByPsi = -ircIm * sinPsi - ircRe * cosPsi;
140 const Real dIrcQByVcRe = -sinPsi / mRc;
141 const Real dIrcQByVcIm = cosPsi / mRc;
142 const Real dIrcQByURe = sinPsi / mRc;
143 const Real dIrcQByUIm = -cosPsi / mRc;
144
145 // 3) Power: P+jQ = (1/Rc)*Vc*conj(Vc-U), evaluated as the dot product below.
146 const Real pInst = vcD * ircD + vcQ * ircQ;
147 const Real qInst = -vcD * ircQ + vcQ * ircD;
148
149 const Real dPByVcRe = (2.0 / mRc) * vcRe - (1.0 / mRc) * uRe;
150 const Real dPByVcIm = (2.0 / mRc) * vcIm - (1.0 / mRc) * uIm;
151 const Real dPByURe = -(1.0 / mRc) * vcRe;
152 const Real dPByUIm = -(1.0 / mRc) * vcIm;
153
154 const Real dQByVcRe = (1.0 / mRc) * uIm;
155 const Real dQByVcIm = -(1.0 / mRc) * uRe;
156 const Real dQByURe = -(1.0 / mRc) * vcIm;
157 const Real dQByUIm = (1.0 / mRc) * vcRe;
158
159 // 4) Outer power control and inner current control (dq).
160 const Real iRefD =
161 -mKpPowerCtrl * pF + mKiPowerCtrl * phiD + mKpPowerCtrl * mPRef;
162 const Real iRefQ =
163 mKpPowerCtrl * qF + mKiPowerCtrl * phiQ - mKpPowerCtrl * mQRef;
164
165 const Real vRefD =
166 -mKpCurrCtrl * ircD + mKiCurrCtrl * gammaD + mKpCurrCtrl * iRefD;
167 const Real vRefQ =
168 -mKpCurrCtrl * ircQ + mKiCurrCtrl * gammaQ + mKpCurrCtrl * iRefQ;
169
170 // d(vRefD)/d{...}, d(vRefQ)/d{...} via the chain rule through ircD/ircQ, iRefD/iRefQ.
171 const Real dVRefDByPsi = -mKpCurrCtrl * dIrcDByPsi;
172 const Real dVRefDByVcRe = -mKpCurrCtrl * dIrcDByVcRe;
173 const Real dVRefDByVcIm = -mKpCurrCtrl * dIrcDByVcIm;
174 const Real dVRefDByURe = -mKpCurrCtrl * dIrcDByURe;
175 const Real dVRefDByUIm = -mKpCurrCtrl * dIrcDByUIm;
176 const Real dVRefDByPF = -mKpCurrCtrl * mKpPowerCtrl;
177 const Real dVRefDByPhiD = mKpCurrCtrl * mKiPowerCtrl;
178 const Real dVRefDByGammaD = mKiCurrCtrl;
179
180 const Real dVRefQByPsi = -mKpCurrCtrl * dIrcQByPsi;
181 const Real dVRefQByVcRe = -mKpCurrCtrl * dIrcQByVcRe;
182 const Real dVRefQByVcIm = -mKpCurrCtrl * dIrcQByVcIm;
183 const Real dVRefQByURe = -mKpCurrCtrl * dIrcQByURe;
184 const Real dVRefQByUIm = -mKpCurrCtrl * dIrcQByUIm;
185 const Real dVRefQByQF = mKpCurrCtrl * mKpPowerCtrl;
186 const Real dVRefQByPhiQ = mKpCurrCtrl * mKiPowerCtrl;
187 const Real dVRefQByGammaQ = mKiCurrCtrl;
188
189 // 5) Bridge-voltage reference: VRefEnv = (vRefD+j*vRefQ)*e^{j*psi}; psi's partial needs the product rule, every other variable only enters implicitly.
190 const Real vRefEnvRe = vRefD * cosPsi - vRefQ * sinPsi;
191 const Real vRefEnvIm = vRefD * sinPsi + vRefQ * cosPsi;
192
193 const Real dVRefEnvReByPsi = dVRefDByPsi * cosPsi - vRefD * sinPsi -
194 dVRefQByPsi * sinPsi - vRefQ * cosPsi;
195 const Real dVRefEnvImByPsi = dVRefDByPsi * sinPsi + vRefD * cosPsi +
196 dVRefQByPsi * cosPsi - vRefQ * sinPsi;
197
198 auto dVRefEnvRe = [&](Real dD, Real dQ) { return dD * cosPsi - dQ * sinPsi; };
199 auto dVRefEnvIm = [&](Real dD, Real dQ) { return dD * sinPsi + dQ * cosPsi; };
200
201 const Real dVRefEnvReByPF = dVRefEnvRe(dVRefDByPF, 0.0);
202 const Real dVRefEnvReByQF = dVRefEnvRe(0.0, dVRefQByQF);
203 const Real dVRefEnvReByPhiD = dVRefEnvRe(dVRefDByPhiD, 0.0);
204 const Real dVRefEnvReByPhiQ = dVRefEnvRe(0.0, dVRefQByPhiQ);
205 const Real dVRefEnvReByGammaD = dVRefEnvRe(dVRefDByGammaD, 0.0);
206 const Real dVRefEnvReByGammaQ = dVRefEnvRe(0.0, dVRefQByGammaQ);
207 const Real dVRefEnvReByVcRe = dVRefEnvRe(dVRefDByVcRe, dVRefQByVcRe);
208 const Real dVRefEnvReByVcIm = dVRefEnvRe(dVRefDByVcIm, dVRefQByVcIm);
209 const Real dVRefEnvReByURe = dVRefEnvRe(dVRefDByURe, dVRefQByURe);
210 const Real dVRefEnvReByUIm = dVRefEnvRe(dVRefDByUIm, dVRefQByUIm);
211
212 const Real dVRefEnvImByPF = dVRefEnvIm(dVRefDByPF, 0.0);
213 const Real dVRefEnvImByQF = dVRefEnvIm(0.0, dVRefQByQF);
214 const Real dVRefEnvImByPhiD = dVRefEnvIm(dVRefDByPhiD, 0.0);
215 const Real dVRefEnvImByPhiQ = dVRefEnvIm(0.0, dVRefQByPhiQ);
216 const Real dVRefEnvImByGammaD = dVRefEnvIm(dVRefDByGammaD, 0.0);
217 const Real dVRefEnvImByGammaQ = dVRefEnvIm(0.0, dVRefQByGammaQ);
218 const Real dVRefEnvImByVcRe = dVRefEnvIm(dVRefDByVcRe, dVRefQByVcRe);
219 const Real dVRefEnvImByVcIm = dVRefEnvIm(dVRefDByVcIm, dVRefQByVcIm);
220 const Real dVRefEnvImByURe = dVRefEnvIm(dVRefDByURe, dVRefQByURe);
221 const Real dVRefEnvImByUIm = dVRefEnvIm(dVRefDByUIm, dVRefQByUIm);
222
223 // 6) RHS f(x,u) (x_dot = f(x,u)).
224 Matrix f = Matrix::Zero(12, 1);
225 f(Psi, 0) = mKpPLL * vcQ + mKiPLL * x(PhiPLL, 0);
226 f(PhiPLL, 0) = vcQ;
227 f(PFiltered, 0) = mOmegaCutoff * (pInst - pF);
228 f(QFiltered, 0) = mOmegaCutoff * (qInst - qF);
229 f(PhiD, 0) = mPRef - pF;
230 f(PhiQ, 0) = qF - mQRef;
231 f(GammaD, 0) = iRefD - ircD;
232 f(GammaQ, 0) = iRefQ - ircQ;
233 f(VcRe, 0) = ifRe / mCf + (uRe - vcRe) / (mCf * mRc) + mOmegaN * vcIm;
234 f(VcIm, 0) = ifIm / mCf + (uIm - vcIm) / (mCf * mRc) - mOmegaN * vcRe;
235 f(IfRe, 0) = (vRefEnvRe - vcRe - mRf * ifRe) / mLf + mOmegaN * ifIm;
236 f(IfIm, 0) = (vRefEnvIm - vcIm - mRf * ifIm) / mLf - mOmegaN * ifRe;
237
238 // 7) Analytic Jacobian A = df/dx, B = df/du.
239 A = Matrix::Zero(12, 12);
240 B = Matrix::Zero(12, 2);
241
242 A(Psi, Psi) = mKpPLL * dVcQByPsi;
243 A(Psi, PhiPLL) = mKiPLL;
244 A(Psi, VcRe) = mKpPLL * dVcQByVcRe;
245 A(Psi, VcIm) = mKpPLL * dVcQByVcIm;
246
247 A(PhiPLL, Psi) = dVcQByPsi;
248 A(PhiPLL, VcRe) = dVcQByVcRe;
249 A(PhiPLL, VcIm) = dVcQByVcIm;
250
251 A(PFiltered, PFiltered) = -mOmegaCutoff;
252 A(PFiltered, VcRe) = mOmegaCutoff * dPByVcRe;
253 A(PFiltered, VcIm) = mOmegaCutoff * dPByVcIm;
254 B(PFiltered, 0) = mOmegaCutoff * dPByURe;
255 B(PFiltered, 1) = mOmegaCutoff * dPByUIm;
256
257 A(QFiltered, QFiltered) = -mOmegaCutoff;
258 A(QFiltered, VcRe) = mOmegaCutoff * dQByVcRe;
259 A(QFiltered, VcIm) = mOmegaCutoff * dQByVcIm;
260 B(QFiltered, 0) = mOmegaCutoff * dQByURe;
261 B(QFiltered, 1) = mOmegaCutoff * dQByUIm;
262
263 A(PhiD, PFiltered) = -1.0;
264 A(PhiQ, QFiltered) = 1.0;
265
266 A(GammaD, PFiltered) = -mKpPowerCtrl;
267 A(GammaD, PhiD) = mKiPowerCtrl;
268 A(GammaD, Psi) = -dIrcDByPsi;
269 A(GammaD, VcRe) = -dIrcDByVcRe;
270 A(GammaD, VcIm) = -dIrcDByVcIm;
271 B(GammaD, 0) = -dIrcDByURe;
272 B(GammaD, 1) = -dIrcDByUIm;
273
274 A(GammaQ, QFiltered) = mKpPowerCtrl;
275 A(GammaQ, PhiQ) = mKiPowerCtrl;
276 A(GammaQ, Psi) = -dIrcQByPsi;
277 A(GammaQ, VcRe) = -dIrcQByVcRe;
278 A(GammaQ, VcIm) = -dIrcQByVcIm;
279 B(GammaQ, 0) = -dIrcQByURe;
280 B(GammaQ, 1) = -dIrcQByUIm;
281
282 A(VcRe, VcRe) = -1.0 / (mCf * mRc);
283 A(VcRe, VcIm) = mOmegaN;
284 A(VcRe, IfRe) = 1.0 / mCf;
285 B(VcRe, 0) = 1.0 / (mCf * mRc);
286
287 A(VcIm, VcRe) = -mOmegaN;
288 A(VcIm, VcIm) = -1.0 / (mCf * mRc);
289 A(VcIm, IfIm) = 1.0 / mCf;
290 B(VcIm, 1) = 1.0 / (mCf * mRc);
291
292 A(IfRe, Psi) = dVRefEnvReByPsi / mLf;
293 A(IfRe, PFiltered) = dVRefEnvReByPF / mLf;
294 A(IfRe, QFiltered) = dVRefEnvReByQF / mLf;
295 A(IfRe, PhiD) = dVRefEnvReByPhiD / mLf;
296 A(IfRe, PhiQ) = dVRefEnvReByPhiQ / mLf;
297 A(IfRe, GammaD) = dVRefEnvReByGammaD / mLf;
298 A(IfRe, GammaQ) = dVRefEnvReByGammaQ / mLf;
299 A(IfRe, VcRe) = dVRefEnvReByVcRe / mLf - 1.0 / mLf;
300 A(IfRe, VcIm) = dVRefEnvReByVcIm / mLf;
301 A(IfRe, IfRe) = -mRf / mLf;
302 A(IfRe, IfIm) = mOmegaN;
303 B(IfRe, 0) = dVRefEnvReByURe / mLf;
304 B(IfRe, 1) = dVRefEnvReByUIm / mLf;
305
306 A(IfIm, Psi) = dVRefEnvImByPsi / mLf;
307 A(IfIm, PFiltered) = dVRefEnvImByPF / mLf;
308 A(IfIm, QFiltered) = dVRefEnvImByQF / mLf;
309 A(IfIm, PhiD) = dVRefEnvImByPhiD / mLf;
310 A(IfIm, PhiQ) = dVRefEnvImByPhiQ / mLf;
311 A(IfIm, GammaD) = dVRefEnvImByGammaD / mLf;
312 A(IfIm, GammaQ) = dVRefEnvImByGammaQ / mLf;
313 A(IfIm, VcRe) = dVRefEnvImByVcRe / mLf;
314 A(IfIm, VcIm) = dVRefEnvImByVcIm / mLf - 1.0 / mLf;
315 A(IfIm, IfRe) = -mOmegaN;
316 A(IfIm, IfIm) = -mRf / mLf;
317 B(IfIm, 0) = dVRefEnvImByURe / mLf;
318 B(IfIm, 1) = dVRefEnvImByUIm / mLf;
319
320 // 8) Offset E = f(x,u) - A*x - B*u.
321 E = f - A * x - B * u;
322
323 // 9) SSN output: y = (u - Vc)/Rc (exact, no relinearization needed).
324 C = Matrix::Zero(2, 12);
325 C(0, VcRe) = -1.0 / mRc;
326 C(1, VcIm) = -1.0 / mRc;
327
328 D = Matrix::Zero(2, 2);
329 D(0, 0) = 1.0 / mRc;
330 D(1, 1) = 1.0 / mRc;
331
332 F = Matrix::Zero(2, 1);
333}
334
336 Matrix E;
337 Matrix F;
338
339 // Relinearized every step (mirrors EMT); change-check intentionally skipped.
340 buildStateSpaceModel(**mX, packComplex((**inputAttribute())(0, 0)), mA, mB,
341 mC, mD, E, F);
342
345
346 return true;
347}
348
350 const Matrix &u) const {
351 const Matrix &x = **mX;
352
353 const Real psi = x(Psi, 0);
354 const Real cosPsi = std::cos(psi);
355 const Real sinPsi = std::sin(psi);
356 const Real vcRe = x(VcRe, 0);
357 const Real vcIm = x(VcIm, 0);
358 const Real ircRe = (vcRe - u(0, 0)) / mRc;
359 const Real ircIm = (vcIm - u(1, 0)) / mRc;
360
361 **mVcD = vcRe * cosPsi + vcIm * sinPsi;
362 **mVcQ = vcIm * cosPsi - vcRe * sinPsi;
363 **mIrcD = ircRe * cosPsi + ircIm * sinPsi;
364 **mIrcQ = ircIm * cosPsi - ircRe * sinPsi;
365
366 **mPInst = **mVcD * **mIrcD + **mVcQ * **mIrcQ;
367 **mQInst = -**mVcD * **mIrcQ + **mVcQ * **mIrcD;
368
369 **mOmegaPLL = mOmegaN + mKpPLL * **mVcQ + mKiPLL * x(PhiPLL, 0);
370}
371
373 Real frequency) {
374 if (!mParametersSet)
375 throw std::logic_error("setParameters() must be called before "
376 "initializeFromNodesAndTerminals().");
377
378 // Initialized algebraically (mixed state), mirroring EMT::Ph3::AvVoltSourceInverterStateSpace.
379
380 const Real omega = 2.0 * PI * frequency;
381 const Complex powerRef(mPRef, mQRef);
382
383 const MatrixComp uInit = buildInitialInputFromNodes(frequency);
384 const Complex U = uInit(0, 0);
385
386 Complex vc = U;
387 Complex irc(0.0, 0.0);
388
389 for (Int iter = 0; iter < mInitializationMaxIterations; ++iter) {
390 if (std::abs(vc) < mInitializationTolerance) {
391 irc = Complex(0.0, 0.0);
392 break;
393 }
394
395 const Complex iNext = std::conj(powerRef / vc);
396 const Complex vcNext = U + mRc * iNext;
397
398 irc = iNext;
399
400 if (std::abs(vcNext - vc) < mInitializationTolerance) {
401 vc = vcNext;
402 break;
403 }
404
405 vc = vcNext;
406 }
407
408 const Complex j(0.0, 1.0);
409 const Complex ifCurrent = j * omega * mCf * vc + irc;
410 const Complex vRef = vc + (mRf + j * omega * mLf) * ifCurrent;
411
412 // thetaN(0) = 0, so psi0 = theta0 exactly.
413 const Real psi0 = std::arg(vc);
414 const Complex rot0 = std::exp(-j * psi0);
415
416 const Complex vcDQ = vc * rot0;
417 const Real vcD = vcDQ.real();
418 const Real vcQ = vcDQ.imag();
419 const Complex ircDQ = irc * rot0;
420 const Real ircD = ircDQ.real();
421 const Real ircQ = ircDQ.imag();
422
423 const Real pInit = vcD * ircD + vcQ * ircQ;
424 const Real qInit = -vcD * ircQ + vcQ * ircD;
425
426 const Real phiPLL0 = (omega - mOmegaN) / mKiPLL;
427 const Real phiD0 = (ircD + mKpPowerCtrl * (pInit - mPRef)) / mKiPowerCtrl;
428 const Real phiQ0 = (ircQ - mKpPowerCtrl * (qInit - mQRef)) / mKiPowerCtrl;
429
430 const Real iRefD0 =
431 -mKpPowerCtrl * pInit + mKiPowerCtrl * phiD0 + mKpPowerCtrl * mPRef;
432 const Real iRefQ0 =
433 mKpPowerCtrl * qInit + mKiPowerCtrl * phiQ0 - mKpPowerCtrl * mQRef;
434
435 const Complex vRefDQ = vRef * rot0;
436 const Real gammaD0 =
437 (vRefDQ.real() + mKpCurrCtrl * (ircD - iRefD0)) / mKiCurrCtrl;
438 const Real gammaQ0 =
439 (vRefDQ.imag() + mKpCurrCtrl * (ircQ - iRefQ0)) / mKiCurrCtrl;
440
441 Matrix x0 = Matrix::Zero(stateSize(), 1);
442 x0(Psi, 0) = psi0;
443 x0(PhiPLL, 0) = phiPLL0;
444 x0(PFiltered, 0) = pInit;
445 x0(QFiltered, 0) = qInit;
446 x0(PhiD, 0) = phiD0;
447 x0(PhiQ, 0) = phiQ0;
448 x0(GammaD, 0) = gammaD0;
449 x0(GammaQ, 0) = gammaQ0;
450 x0(VcRe, 0) = vc.real();
451 x0(VcIm, 0) = vc.imag();
452 x0(IfRe, 0) = ifCurrent.real();
453 x0(IfIm, 0) = ifCurrent.imag();
454
455 **mX = x0;
456 **mIntfVoltage = uInit;
457 (**mIntfCurrent)(0, 0) = (U - vc) / mRc;
458
461
462 SPDLOG_LOGGER_INFO(mSLog,
463 "\n--- Inverter SSN mixed real+complex initialization ---"
464 "\nInput u: {:s}"
465 "\nOutput y: {:s}"
466 "\nState x: {:s}"
467 "\nP/Q init: [{:.6e}, {:.6e}]"
468 "\nVc dq: [{:.6e}, {:.6e}]"
469 "\nIinj dq: [{:.6e}, {:.6e}]"
470 "\n--- Initialization finished ---",
473 Logger::matrixToString(**mX), pInit, qInit, vcD, vcQ, ircD,
474 ircQ);
475}
Bool updateComponentParameters() override final
Rebuild A/B/C/D/E/F from the current state/input; returns true if the stamp changed.
AvVoltSourceInverterStateSpace(String uid, String name, Logger::Level logLevel=Logger::Level::off)
void initializeFromNodesAndTerminals(Real frequency) override
Initializes Component variables according to power flow data stored in Nodes.
void setParameters(Real lf, Real cf, Real rf, Real rc, Real omegaN, Real kpPLL, Real kiPLL, Real omegaCutoff, Real pRef, Real qRef, Real kpPowerCtrl, Real kiPowerCtrl, Real kpCurrCtrl, Real kiCurrCtrl)
virtual MatrixComp buildInitialInputFromNodes(Real frequency)
Default: v = v_terminal1 - v_terminal0.
Matrix mA
Continuous-time real model over the packed state and packed [Re,Im] input/output.
void setParameters(const Matrix &A, const Matrix &B, const Matrix &C, const Matrix &D)
Int stateSize() const
Total packed real state size: realStateCount + 2*complexStateCount.
const Attribute< Matrix >::Ptr mX
Packed real state: [realStates..., Re(cplxState0), Im(cplxState0), ...].
MixedVTypeVariableSSNComp(String uid, String name, Int realStateCount, Int complexStateCount, Logger::Level logLevel=Logger::Level::off)
String uid()
Returns unique id.
AttributeList::Ptr mAttributes
Attribute List.
spdlog::level::level_enum Level
Definition Logger.h:33
static String matrixCompToString(const MatrixComp &mat)
Definition Logger.cpp:37
static String matrixToString(const Matrix &mat)
Definition Logger.cpp:31
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
bool mParametersSet
Flag indicating that parameters are set via setParameters() function.
Logger::Log mSLog
Component logger.
#define PI
Definition Definitions.h:43
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
Dense matrix for real numbers.
Definition Definitions.h:81
std::string String
Definition Definitions.h:65
double Real
Definition Definitions.h:62
int Int
Definition Definitions.h:61
std::complex< Real > Complex
Definition Definitions.h:63
Eigen::Matrix< Complex, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > MatrixComp
Dense matrix for complex numbers.
Definition Definitions.h:84
bool Bool
Definition Definitions.h:64