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),
38 throw std::invalid_argument(
"Filter inductance lf must be positive.");
41 throw std::invalid_argument(
"Filter capacitance cf must be positive.");
44 throw std::invalid_argument(
"Filter resistance rf must be non-negative.");
47 throw std::invalid_argument(
"Coupling resistance rc must be positive.");
50 throw std::invalid_argument(
51 "Nominal angular frequency omegaN must be positive.");
53 if (omegaCutoff < 0.0)
54 throw std::invalid_argument(
55 "Power-filter cutoff frequency omegaCutoff must be non-negative.");
58 throw std::invalid_argument(
"PLL integral gain kiPLL must be non-zero.");
60 if (kiPowerCtrl == 0.0)
61 throw std::invalid_argument(
62 "Power-control integral gain kiPowerCtrl must be non-zero.");
64 if (kiCurrCtrl == 0.0)
65 throw std::invalid_argument(
66 "Current-control integral gain kiCurrCtrl must be non-zero.");
77 mOmegaCutoff = omegaCutoff;
80 mKpPowerCtrl = kpPowerCtrl;
81 mKiPowerCtrl = kiPowerCtrl;
82 mKpCurrCtrl = kpCurrCtrl;
83 mKiCurrCtrl = kiCurrCtrl;
85 const Matrix x0 = Matrix::Zero(12, 1);
86 const Matrix u0 = Matrix::Zero(2, 1);
88 Matrix aMatrix, bMatrix, cMatrix, dMatrix, eVector, fVector;
89 buildStateSpaceModel(x0, u0, aMatrix, bMatrix, cMatrix, dMatrix, eVector,
96void DP::Ph1::AvVoltSourceInverterStateSpace::buildStateSpaceModel(
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);
112 const Real uRe = u(0, 0);
113 const Real uIm = u(1, 0);
115 const Real cosPsi = std::cos(psi);
116 const Real sinPsi = std::sin(psi);
119 const Real vcD = vcRe * cosPsi + vcIm * sinPsi;
120 const Real vcQ = vcIm * cosPsi - vcRe * sinPsi;
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;
128 const Real dVcQByPsi = -vcIm * sinPsi - vcRe * cosPsi;
129 const Real dVcQByVcRe = -sinPsi;
130 const Real dVcQByVcIm = cosPsi;
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;
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;
146 const Real pInst = vcD * ircD + vcQ * ircQ;
147 const Real qInst = -vcD * ircQ + vcQ * ircD;
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;
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;
161 -mKpPowerCtrl * pF + mKiPowerCtrl * phiD + mKpPowerCtrl * mPRef;
163 mKpPowerCtrl * qF + mKiPowerCtrl * phiQ - mKpPowerCtrl * mQRef;
166 -mKpCurrCtrl * ircD + mKiCurrCtrl * gammaD + mKpCurrCtrl * iRefD;
168 -mKpCurrCtrl * ircQ + mKiCurrCtrl * gammaQ + mKpCurrCtrl * 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;
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;
190 const Real vRefEnvRe = vRefD * cosPsi - vRefQ * sinPsi;
191 const Real vRefEnvIm = vRefD * sinPsi + vRefQ * cosPsi;
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;
198 auto dVRefEnvRe = [&](
Real dD,
Real dQ) {
return dD * cosPsi - dQ * sinPsi; };
199 auto dVRefEnvIm = [&](
Real dD,
Real dQ) {
return dD * sinPsi + dQ * cosPsi; };
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);
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);
224 Matrix f = Matrix::Zero(12, 1);
225 f(Psi, 0) = mKpPLL * vcQ + mKiPLL * x(PhiPLL, 0);
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;
239 A = Matrix::Zero(12, 12);
240 B = Matrix::Zero(12, 2);
242 A(Psi, Psi) = mKpPLL * dVcQByPsi;
243 A(Psi, PhiPLL) = mKiPLL;
244 A(Psi, VcRe) = mKpPLL * dVcQByVcRe;
245 A(Psi, VcIm) = mKpPLL * dVcQByVcIm;
247 A(PhiPLL, Psi) = dVcQByPsi;
248 A(PhiPLL, VcRe) = dVcQByVcRe;
249 A(PhiPLL, VcIm) = dVcQByVcIm;
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;
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;
263 A(PhiD, PFiltered) = -1.0;
264 A(PhiQ, QFiltered) = 1.0;
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;
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;
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);
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);
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;
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;
321 E = f -
A * x -
B * u;
324 C = Matrix::Zero(2, 12);
325 C(0, VcRe) = -1.0 / mRc;
326 C(1, VcIm) = -1.0 / mRc;
328 D = Matrix::Zero(2, 2);
332 F = Matrix::Zero(2, 1);
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;
361 **mVcD = vcRe * cosPsi + vcIm * sinPsi;
362 **mVcQ = vcIm * cosPsi - vcRe * sinPsi;
363 **mIrcD = ircRe * cosPsi + ircIm * sinPsi;
364 **mIrcQ = ircIm * cosPsi - ircRe * sinPsi;
366 **mPInst = **mVcD * **mIrcD + **mVcQ * **mIrcQ;
367 **mQInst = -**mVcD * **mIrcQ + **mVcQ * **mIrcD;
369 **mOmegaPLL = mOmegaN + mKpPLL * **mVcQ + mKiPLL * x(PhiPLL, 0);
375 throw std::logic_error(
"setParameters() must be called before "
376 "initializeFromNodesAndTerminals().");
380 const Real omega = 2.0 *
PI * frequency;
381 const Complex powerRef(mPRef, mQRef);
395 const Complex iNext = std::conj(powerRef / vc);
396 const Complex vcNext = U + mRc * iNext;
409 const Complex ifCurrent = j * omega * mCf * vc + irc;
410 const Complex vRef = vc + (mRf + j * omega * mLf) * ifCurrent;
413 const Real psi0 = std::arg(vc);
414 const Complex rot0 = std::exp(-j * psi0);
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();
423 const Real pInit = vcD * ircD + vcQ * ircQ;
424 const Real qInit = -vcD * ircQ + vcQ * ircD;
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;
431 -mKpPowerCtrl * pInit + mKiPowerCtrl * phiD0 + mKpPowerCtrl * mPRef;
433 mKpPowerCtrl * qInit + mKiPowerCtrl * phiQ0 - mKpPowerCtrl * mQRef;
435 const Complex vRefDQ = vRef * rot0;
437 (vRefDQ.real() + mKpCurrCtrl * (ircD - iRefD0)) / mKiCurrCtrl;
439 (vRefDQ.imag() + mKpCurrCtrl * (ircQ - iRefQ0)) / mKiCurrCtrl;
443 x0(PhiPLL, 0) = phiPLL0;
444 x0(PFiltered, 0) = pInit;
445 x0(QFiltered, 0) = qInit;
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();
457 (**mIntfCurrent)(0, 0) = (U - vc) / mRc;
462 SPDLOG_LOGGER_INFO(
mSLog,
463 "\n--- Inverter SSN mixed real+complex initialization ---"
467 "\nP/Q init: [{:.6e}, {:.6e}]"
468 "\nVc dq: [{:.6e}, {:.6e}]"
469 "\nIinj dq: [{:.6e}, {:.6e}]"
470 "\n--- Initialization finished ---",
void updateLogAttributes(const Matrix &u) const override final
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)
void setOutputOffset(const Matrix &F)
static constexpr Int mInitializationMaxIterations
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.
static Matrix packComplex(const Complex &c)
void setStateOffset(const Matrix &E)
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.
static constexpr Real mInitializationTolerance
const Attribute< Matrix >::Ptr mX
Packed real state: [realStates..., Re(cplxState0), Im(cplxState0), ...].
Attribute< MatrixComp >::Ptr inputAttribute() const
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
static String matrixCompToString(const MatrixComp &mat)
static String matrixToString(const Matrix &mat)
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.
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
Dense matrix for real numbers.
std::complex< Real > Complex
Eigen::Matrix< Complex, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > MatrixComp
Dense matrix for complex numbers.