9 #include <dpsim-models/Base/Base_ReducedOrderSynchronGenerator.h>
15 String uid, String name, Logger::Level logLevel)
17 mVdq0(mAttributes->create<Matrix>(
"Vdq0")),
18 mIdq0(mAttributes->create<Matrix>(
"Idq0")),
19 mElecTorque(mAttributes->create<Real>(
"Te")),
20 mMechTorque(mAttributes->create<Real>(
"Tm")),
21 mOmMech(mAttributes->create<Real>(
"w_r")),
22 mThetaMech(mAttributes->create<Real>(
"Theta")),
23 mDelta(mAttributes->create<Real>(
"delta")),
24 mEf(mAttributes->create<Real>(
"Ef")) {
29 **mVdq0 = Matrix::Zero(3, 1);
30 **mIdq0 = Matrix::Zero(3, 1);
33 mModelAsNortonSource =
true;
34 SPDLOG_LOGGER_DEBUG(this->mSLog,
35 "SG per default modelled as Norton equivalent");
40 String uid, String name, Logger::Level logLevel)
42 mVdq(mAttributes->create<Matrix>(
"Vdq0")),
43 mIdq(mAttributes->create<Matrix>(
"Idq0")),
44 mElecTorque(mAttributes->create<Real>(
"Te")),
45 mMechTorque(mAttributes->create<Real>(
"Tm")),
46 mOmMech(mAttributes->create<Real>(
"w_r")),
47 mThetaMech(mAttributes->create<Real>(
"Theta")),
48 mDelta(mAttributes->create<Real>(
"delta")),
49 mEf(mAttributes->create<Real>(
"Ef")) {
55 **mVdq = Matrix::Zero(2, 1);
56 **mIdq = Matrix::Zero(2, 1);
59 mModelAsNortonSource =
true;
60 SPDLOG_LOGGER_DEBUG(this->mSLog,
61 "SG per default modelled as Norton equivalent");
64 template <
typename VarType>
66 Bool modelAsCurrentSource) {
67 mModelAsNortonSource = modelAsCurrentSource;
69 if (mModelAsNortonSource) {
70 this->setVirtualNodeNumber(0);
71 SPDLOG_LOGGER_DEBUG(this->mSLog,
"Setting SG model to Norton equivalent");
73 this->setVirtualNodeNumber(2);
74 SPDLOG_LOGGER_DEBUG(this->mSLog,
"Setting SG model to Thevenin equivalent");
78 template <
typename VarType>
80 Real nomPower, Real nomVolt, Real nomFreq) {
88 mNomOmega = nomFreq * 2 * PI;
91 mBase_V_RMS = mNomVolt;
92 mBase_V = mNomVolt / sqrt(3) * sqrt(2);
93 mBase_I_RMS = mNomPower / mBase_V_RMS;
94 mBase_I = mNomPower / ((3. / 2.) * mBase_V);
95 mBase_Z = mBase_V_RMS / mBase_I_RMS;
96 mBase_OmElec = mNomOmega;
97 mBase_OmMech = mBase_OmElec;
98 mBase_L = mBase_Z / mBase_OmElec;
101 template <
typename VarType>
103 VarType>::setOperationalParametersPerUnit(Real nomPower, Real nomVolt,
104 Real nomFreq, Real H, Real Ld,
105 Real Lq, Real L0, Real Ld_t,
108 setBaseParameters(nomPower, nomVolt, nomFreq);
117 SPDLOG_LOGGER_INFO(this->mSLog,
118 "Set base parameters: \n"
119 "nomPower: {:e}\nnomVolt: {:e}\nnomFreq: {:e}\n",
120 mNomPower, mNomVolt, mNomFreq);
122 SPDLOG_LOGGER_INFO(this->mSLog,
123 "Set operational parameters in per unit: \n"
125 "Ld: {:e}\nLq: {:e}\nL0: {:e}\n"
126 "Ld_t: {:e}\nTd0_t: {:e}\n",
127 mH, mLd, mLq, mL0, mLd_t, mTd0_t);
130 template <
typename VarType>
132 VarType>::setOperationalParametersPerUnit(Real nomPower, Real nomVolt,
133 Real nomFreq, Real H, Real Ld,
134 Real Lq, Real L0, Real Ld_t,
135 Real Lq_t, Real Td0_t,
138 setBaseParameters(nomPower, nomVolt, nomFreq);
149 SPDLOG_LOGGER_INFO(this->mSLog,
150 "Set base parameters: \n"
151 "nomPower: {:e}\nnomVolt: {:e}\nnomFreq: {:e}\n",
152 mNomPower, mNomVolt, mNomFreq);
154 SPDLOG_LOGGER_INFO(this->mSLog,
155 "Set operational parameters in per unit: \n"
157 "Ld: {:e}\nLq: {:e}\nL0: {:e}\n"
158 "Ld_t: {:e}\nLq_t: {:e}\n"
159 "Td0_t: {:e}\nTq0_t: {:e}\n",
160 mH, mLd, mLq, mL0, mLd_t, mLq_t, mTd0_t, mTq0_t);
163 template <
typename VarType>
165 VarType>::setOperationalParametersPerUnit(Real nomPower, Real nomVolt,
166 Real nomFreq, Real H, Real Ld,
167 Real Lq, Real L0, Real Ld_t,
168 Real Lq_t, Real Td0_t, Real Tq0_t,
169 Real Ld_s, Real Lq_s, Real Td0_s,
170 Real Tq0_s, Real Taa) {
172 setBaseParameters(nomPower, nomVolt, nomFreq);
188 SPDLOG_LOGGER_INFO(this->mSLog,
189 "Set base parameters: \n"
190 "nomPower: {:e}\nnomVolt: {:e}\nnomFreq: {:e}\n",
191 mNomPower, mNomVolt, mNomFreq);
193 SPDLOG_LOGGER_INFO(this->mSLog,
194 "Set operational parameters in per unit: \n"
196 "Ld: {:e}\nLq: {:e}\nL0: {:e}\n"
197 "Ld_t: {:e}\nLq_t: {:e}\n"
198 "Td0_t: {:e}\nTq0_t: {:e}\n"
199 "Ld_s: {:e}\nLq_s: {:e}\n"
200 "Td0_s: {:e}\nTq0_s: {:e}\n"
202 mH, mLd, mLq, mL0, mLd_t, mLq_t, mTd0_t, mTq0_t, mLd_s,
203 mLq_s, mTd0_s, mTq0_s, mTaa);
206 template <
typename VarType>
208 Real scalingFactor) {
209 mH = mH * scalingFactor;
212 "Scaling inertia with factor {:e}:\n resulting inertia: {:e}\n",
216 template <
typename VarType>
220 if (mSGOrder == SGOrder::SG5Order) {
221 mYd = (mTd0_s / mTd0_t) * (mLd_s / mLd_t) * (mLd - mLd_t);
224 }
else if (mSGOrder == SGOrder::SG6aOrder) {
225 mYd = (mTd0_s / mTd0_t) * (mLd_s / mLd_t) * (mLd - mLd_t);
226 mYq = (mTq0_s / mTq0_t) * (mLq_s / mLq_t) * (mLq - mLq_t);
233 Real Zq_t = mLd - mLd_t - mYd;
234 Real Zd_t = mLq - mLq_t - mYq;
235 Real Zq_s = mLd_t - mLd_s + mYd;
236 Real Zd_s = mLq_t - mLq_s + mYq;
238 mAd_t = mTimeStep * Zd_t / (2 * mTq0_t + mTimeStep);
239 mBd_t = (2 * mTq0_t - mTimeStep) / (2 * mTq0_t + mTimeStep);
240 mAq_t = -mTimeStep * Zq_t / (2 * mTd0_t + mTimeStep);
241 mBq_t = (2 * mTd0_t - mTimeStep) / (2 * mTd0_t + mTimeStep);
242 mDq_t = mTimeStep * (1 - Tf) / (2 * mTd0_t + mTimeStep);
244 if (mSGOrder == SGOrder::SG5Order) {
245 mAd_s = (mTimeStep * (mLq - mLq_s)) / (2 * mTq0_s + mTimeStep);
246 mCd_s = (2 * mTq0_s - mTimeStep) / (2 * mTq0_s + mTimeStep);
247 mAq_s = (-mTimeStep * Zq_s + mTimeStep * mAq_t) / (2 * mTd0_s + mTimeStep);
248 mBq_s = (mTimeStep * mBq_t + mTimeStep) / (2 * mTd0_s + mTimeStep);
249 mCq_s = (2 * mTd0_s - mTimeStep) / (2 * mTd0_s + mTimeStep);
250 mDq_s = (mTimeStep * mDq_t + Tf * mTimeStep) / (2 * mTd0_s + mTimeStep);
251 }
else if (mSGOrder == SGOrder::SG6aOrder || mSGOrder == SGOrder::SG6bOrder) {
252 mAd_s = (mTimeStep * Zd_s + mTimeStep * mAd_t) / (2 * mTq0_s + mTimeStep);
253 mBd_s = (mTimeStep * mBd_t + mTimeStep) / (2 * mTq0_s + mTimeStep);
254 mCd_s = (2 * mTq0_s - mTimeStep) / (2 * mTq0_s + mTimeStep);
255 mAq_s = (-mTimeStep * Zq_s + mTimeStep * mAq_t) / (2 * mTd0_s + mTimeStep);
256 mBq_s = (mTimeStep * mBq_t + mTimeStep) / (2 * mTd0_s + mTimeStep);
257 mCq_s = (2 * mTd0_s - mTimeStep) / (2 * mTd0_s + mTimeStep);
258 mDq_s = (mTimeStep * mDq_t + Tf * mTimeStep) / (2 * mTd0_s + mTimeStep);
262 template <
typename VarType>
264 VarType>::calculateResistanceMatrixConstants() {
265 if (mSGOrder == SGOrder::SG3Order) {
269 if (mSGOrder == SGOrder::SG4Order) {
273 if (mSGOrder == SGOrder::SG5Order || mSGOrder == SGOrder::SG6aOrder ||
274 mSGOrder == SGOrder::SG6bOrder) {
280 template <
typename VarType>
282 Complex initComplexElectricalPower, Real initMechanicalPower,
283 Complex initTerminalVoltage) {
285 mInitElecPower = initComplexElectricalPower;
286 mInitMechPower = initMechanicalPower;
288 mInitVoltage = initTerminalVoltage;
289 mInitVoltageAngle = Math::phase(mInitVoltage);
291 mInitCurrent = std::conj(mInitElecPower / mInitVoltage);
292 mInitCurrentAngle = Math::phase(mInitCurrent);
294 mInitVoltage = mInitVoltage / mBase_V_RMS;
295 mInitCurrent = mInitCurrent / mBase_I_RMS;
297 mInitialValuesSet =
true;
299 SPDLOG_LOGGER_DEBUG(this->mSLog,
300 "\n--- Set initial values ---"
301 "\nInitial active power: {:}W = {:} p.u."
302 "\nInitial reactive power W: {:}W = {:} p.u."
303 "\nInitial terminal voltage magnitude: {:} p.u."
304 "\nInitial terminal voltage phase: {:} rad = ({:}°)"
305 "\nInitial current magnitude: {:} p.u."
306 "\nInitial current phase: {:} rad = ({:}°)"
307 "\n--- Set initial values finished ---\n",
309 mInitElecPower.real(), mInitElecPower.real() / mNomPower,
310 mInitElecPower.imag(), mInitElecPower.imag() / mNomPower,
311 Math::abs(mInitVoltage), Math::phase(mInitVoltage),
312 Math::phaseDeg(mInitVoltage), Math::abs(mInitCurrent),
313 Math::phase(mInitCurrent), Math::phaseDeg(mInitCurrent));
314 this->mSLog->flush();
321 this->updateMatrixNodeIndices();
323 if (!mInitialValuesSet)
324 this->setInitialValues(-this->terminal(0)->singlePower(),
325 -this->terminal(0)->singlePower().real(),
326 this->initialSingleVoltage(0));
329 **mMechTorque = mInitMechPower / mNomPower;
330 mMechTorque_prev = **mMechTorque;
333 Complex Eq0 = mInitVoltage + Complex(0, mLq) * mInitCurrent;
336 **mDelta = Math::phase(Eq0);
339 (**mIdq0)(0, 0) = Math::abs(mInitCurrent) * sin(**mDelta - mInitCurrentAngle);
340 (**mIdq0)(1, 0) = Math::abs(mInitCurrent) * cos(**mDelta - mInitCurrentAngle);
343 (**mVdq0)(0, 0) = Math::abs(mInitVoltage) * sin(**mDelta - mInitVoltageAngle);
344 (**mVdq0)(1, 0) = Math::abs(mInitVoltage) * cos(**mDelta - mInitVoltageAngle);
347 **mEf = Math::abs(Eq0) + (mLd - mLq) * (**mIdq0)(0, 0);
352 mExciter->initialize(Math::abs(mInitVoltage), **mEf);
354 if (mHasTurbineGovernor) {
355 mTurbineGovernor->initialize(**mMechTorque);
360 (**mVdq0)(0, 0) * (**mIdq0)(0, 0) + (**mVdq0)(1, 0) * (**mIdq0)(1, 0);
363 **mOmMech = mNomOmega / mBase_OmMech;
366 **mThetaMech = **mDelta - PI / 2.;
369 (**mIntfCurrent)(0, 0) = (mInitCurrent * mBase_I).real();
370 (**mIntfCurrent)(1, 0) = (mInitCurrent * mBase_I * SHIFT_TO_PHASE_B).real();
371 (**mIntfCurrent)(2, 0) = (mInitCurrent * mBase_I * SHIFT_TO_PHASE_C).real();
374 (**mIntfVoltage)(0, 0) = (mInitVoltage * mBase_V).real();
375 (**mIntfVoltage)(1, 0) = (mInitVoltage * mBase_V * SHIFT_TO_PHASE_B).real();
376 (**mIntfVoltage)(2, 0) = (mInitVoltage * mBase_V * SHIFT_TO_PHASE_C).real();
378 SPDLOG_LOGGER_DEBUG(this->mSLog,
379 "\n--- Initialization from power flow ---"
380 "\nInitial Vd (per unit): {:f}"
381 "\nInitial Vq (per unit): {:f}"
382 "\nInitial Id (per unit): {:f}"
383 "\nInitial Iq (per unit): {:f}"
384 "\nInitial Ef (per unit): {:f}"
385 "\nInitial mechanical torque (per unit): {:f}"
386 "\nInitial electrical torque (per unit): {:f}"
387 "\nInitial initial mechanical theta (per unit): {:f}"
388 "\nInitial delta (per unit): {:f} (= {:f}°)"
389 "\n--- Initialization from power flow finished ---",
391 (**mVdq0)(0, 0), (**mVdq0)(1, 0), (**mIdq0)(0, 0),
392 (**mIdq0)(1, 0), **mEf, **mMechTorque, **mElecTorque,
393 **mThetaMech, **mDelta, **mDelta * 180 / PI);
394 this->mSLog->flush();
399 Complex>::initializeFromNodesAndTerminals(Real frequency) {
401 this->updateMatrixNodeIndices();
403 if (!mInitialValuesSet)
404 this->setInitialValues(-this->terminal(0)->singlePower(),
405 -this->terminal(0)->singlePower().real(),
406 this->initialSingleVoltage(0));
409 **mMechTorque = mInitMechPower / mNomPower;
410 mMechTorque_prev = **mMechTorque;
413 Complex Eq0 = mInitVoltage + Complex(0, mLq) * mInitCurrent;
416 **mDelta = Math::phase(Eq0);
419 (**mIdq)(0, 0) = Math::abs(mInitCurrent) * sin(**mDelta - mInitCurrentAngle);
420 (**mIdq)(1, 0) = Math::abs(mInitCurrent) * cos(**mDelta - mInitCurrentAngle);
423 (**mVdq)(0, 0) = Math::abs(mInitVoltage) * sin(**mDelta - mInitVoltageAngle);
424 (**mVdq)(1, 0) = Math::abs(mInitVoltage) * cos(**mDelta - mInitVoltageAngle);
427 **mEf = Math::abs(Eq0) + (mLd - mLq) * (**mIdq)(0, 0);
432 mExciter->initialize(Math::abs(mInitVoltage), **mEf);
434 if (mHasTurbineGovernor) {
435 mTurbineGovernor->initialize(**mMechTorque);
440 (**mVdq)(0, 0) * (**mIdq)(0, 0) + (**mVdq)(1, 0) * (**mIdq)(1, 0);
443 **mOmMech = mNomOmega / mBase_OmMech;
446 **mThetaMech = **mDelta - PI / 2.;
449 (**mIntfCurrent)(0, 0) = mInitCurrent * mBase_I_RMS;
452 (**mIntfVoltage)(0, 0) = mInitVoltage * mBase_V_RMS;
454 SPDLOG_LOGGER_DEBUG(this->mSLog,
455 "\n--- Initialization from power flow ---"
456 "\nInitial Vd (per unit): {:f}"
457 "\nInitial Vq (per unit): {:f}"
458 "\nInitial Id (per unit): {:f}"
459 "\nInitial Iq (per unit): {:f}"
460 "\nInitial Ef (per unit): {:f}"
461 "\nInitial mechanical torque (per unit): {:f}"
462 "\nInitial electrical torque (per unit): {:f}"
463 "\nInitial initial mechanical theta (per unit): {:f}"
464 "\nInitial delta (per unit): {:f} (= {:f}°)"
465 "\n--- Initialization from power flow finished ---",
467 (**mVdq)(0, 0), (**mVdq)(1, 0), (**mIdq)(0, 0),
468 (**mIdq)(1, 0), **mEf, **mMechTorque, **mElecTorque,
469 **mThetaMech, **mDelta, **mDelta * 180 / PI);
470 this->mSLog->flush();
473 template <
typename VarType>
477 this->updateMatrixNodeIndices();
478 mTimeStep = timeStep;
479 calculateVBRconstants();
480 calculateResistanceMatrixConstants();
481 initializeResistanceMatrix();
482 specificInitialization();
487 Real time, Int timeStepCount) {
493 **mEf = mExciter->step((**mVdq)(0, 0), (**mVdq)(1, 0), mTimeStep);
495 if (mHasTurbineGovernor) {
496 mMechTorque_prev = **mMechTorque;
497 **mMechTorque = mTurbineGovernor->step(**mOmMech, mTimeStep);
502 (**mVdq)(0, 0) * (**mIdq)(0, 0) + (**mVdq)(1, 0) * (**mIdq)(1, 0);
503 **mOmMech = **mOmMech +
504 mTimeStep * (1. / (2. * mH) * (mMechTorque_prev - **mElecTorque));
505 **mThetaMech = **mThetaMech + mTimeStep * (**mOmMech * mBase_OmMech);
506 **mDelta = **mDelta + mTimeStep * (**mOmMech - 1.) * mBase_OmMech;
512 (**mRightVector).setZero();
513 mnaCompApplyRightSideVectorStamp(**mRightVector);
518 Real time, Int timeStepCount) {
524 **mEf = mExciter->step((**mVdq0)(0, 0), (**mVdq0)(1, 0), mTimeStep);
526 if (mHasTurbineGovernor) {
527 mMechTorque_prev = **mMechTorque;
528 **mMechTorque = mTurbineGovernor->step(**mOmMech, mTimeStep);
533 ((**mVdq0)(0, 0) * (**mIdq0)(0, 0) + (**mVdq0)(1, 0) * (**mIdq0)(1, 0));
534 **mOmMech = **mOmMech +
535 mTimeStep * (1. / (2. * mH) * (mMechTorque_prev - **mElecTorque));
536 **mThetaMech = **mThetaMech + mTimeStep * (**mOmMech * mBase_OmMech);
537 **mDelta = **mDelta + mTimeStep * (**mOmMech - 1.) * mBase_OmMech;
543 (**mRightVector).setZero();
544 mnaCompApplyRightSideVectorStamp(**mRightVector);
547 template <
typename VarType>
550 AttributeBase::List &attributeDependencies,
551 AttributeBase::List &modifiedAttributes) {
552 modifiedAttributes.push_back(mRightVector);
553 prevStepDependencies.push_back(mIntfVoltage);
556 template <
typename VarType>
558 Real time, Int timeStepCount) {
561 (**mRightVector).setZero();
562 mnaCompApplyRightSideVectorStamp(**mRightVector);
565 template <
typename VarType>
568 AttributeBase::List &attributeDependencies,
569 AttributeBase::List &modifiedAttributes,
571 attributeDependencies.push_back(leftVector);
572 modifiedAttributes.push_back(mIntfVoltage);
575 template <
typename VarType>
578 mnaCompPostStep(**leftVector);
581 template <
typename VarType>
586 mExciter = Signal::Exciter::make(**this->mName +
"_Exciter", this->mLogLevel);
587 mExciter->setParameters(Ta, Ka, Te, Ke, Tf, Kf, Tr);
591 template <
typename VarType>
593 std::shared_ptr<Signal::Exciter> exciter) {
598 template <
typename VarType>
600 Real T3, Real T4, Real T5, Real Tc, Real Ts, Real R, Real Pmin, Real Pmax,
601 Real OmRef, Real TmRef) {
602 mTurbineGovernor = Signal::TurbineGovernorType1::make(
603 **this->mName +
"_TurbineGovernor", this->mLogLevel);
604 mTurbineGovernor->setParameters(T3, T4, T5, Tc, Ts, R, Pmin, Pmax, OmRef);
605 mTurbineGovernor->initialize(TmRef);
606 mHasTurbineGovernor =
true;
609 template <
typename VarType>
611 std::shared_ptr<Signal::TurbineGovernorType1> turbineGovernor) {
612 mTurbineGovernor = turbineGovernor;
613 mHasTurbineGovernor =
true;
Base class for all MNA components that are transmitting power.