156 "Set operational parameters in per unit: \n"
158 "Ld: {:e}\nLq: {:e}\nL0: {:e}\n"
159 "Ld_t: {:e}\nLq_t: {:e}\n"
160 "Td0_t: {:e}\nTq0_t: {:e}\n",
164template <
typename VarType>
167 Real nomFreq, Real H, Real Ld,
168 Real Lq, Real L0, Real Ld_t,
169 Real Lq_t, Real Td0_t, Real Tq0_t,
170 Real Ld_s, Real Lq_s, Real Td0_s,
171 Real Tq0_s, Real Taa) {
189 SPDLOG_LOGGER_INFO(this->
mSLog,
190 "Set base parameters: \n"
191 "nomPower: {:e}\nnomVolt: {:e}\nnomFreq: {:e}\n",
194 SPDLOG_LOGGER_INFO(this->
mSLog,
195 "Set operational parameters in per unit: \n"
197 "Ld: {:e}\nLq: {:e}\nL0: {:e}\n"
198 "Ld_t: {:e}\nLq_t: {:e}\n"
199 "Td0_t: {:e}\nTq0_t: {:e}\n"
200 "Ld_s: {:e}\nLq_s: {:e}\n"
201 "Td0_s: {:e}\nTq0_s: {:e}\n"
207template <
typename VarType>
209 Real scalingFactor) {
210 mH =
mH * scalingFactor;
213 "Scaling inertia with factor {:e}:\n resulting inertia: {:e}\n",
217template <
typename VarType>
218void Base::ReducedOrderSynchronGenerator<VarType>::calculateVBRconstants() {
221 if (mSGOrder == SGOrder::SG5Order) {
222 mYd = (mTd0_s / mTd0_t) * (mLd_s / mLd_t) * (mLd - mLd_t);
225 }
else if (mSGOrder == SGOrder::SG6aOrder) {
226 mYd = (mTd0_s / mTd0_t) * (mLd_s / mLd_t) * (mLd - mLd_t);
227 mYq = (mTq0_s / mTq0_t) * (mLq_s / mLq_t) * (mLq - mLq_t);
234 Real Zq_t = mLd - mLd_t - mYd;
235 Real Zd_t = mLq - mLq_t - mYq;
236 Real Zq_s = mLd_t - mLd_s + mYd;
237 Real Zd_s = mLq_t - mLq_s + mYq;
239 mAd_t = mTimeStep * Zd_t / (2 * mTq0_t + mTimeStep);
240 mBd_t = (2 * mTq0_t - mTimeStep) / (2 * mTq0_t + mTimeStep);
241 mAq_t = -mTimeStep * Zq_t / (2 * mTd0_t + mTimeStep);
242 mBq_t = (2 * mTd0_t - mTimeStep) / (2 * mTd0_t + mTimeStep);
243 mDq_t = mTimeStep * (1 - Tf) / (2 * mTd0_t + mTimeStep);
245 if (mSGOrder == SGOrder::SG5Order) {
246 mAd_s = (mTimeStep * (mLq - mLq_s)) / (2 * mTq0_s + mTimeStep);
247 mCd_s = (2 * mTq0_s - mTimeStep) / (2 * mTq0_s + mTimeStep);
248 mAq_s = (-mTimeStep * Zq_s + mTimeStep * mAq_t) / (2 * mTd0_s + mTimeStep);
249 mBq_s = (mTimeStep * mBq_t + mTimeStep) / (2 * mTd0_s + mTimeStep);
250 mCq_s = (2 * mTd0_s - mTimeStep) / (2 * mTd0_s + mTimeStep);
251 mDq_s = (mTimeStep * mDq_t + Tf * mTimeStep) / (2 * mTd0_s + mTimeStep);
252 }
else if (mSGOrder == SGOrder::SG6aOrder || mSGOrder == SGOrder::SG6bOrder) {
253 mAd_s = (mTimeStep * Zd_s + mTimeStep * mAd_t) / (2 * mTq0_s + mTimeStep);
254 mBd_s = (mTimeStep * mBd_t + mTimeStep) / (2 * mTq0_s + mTimeStep);
255 mCd_s = (2 * mTq0_s - mTimeStep) / (2 * mTq0_s + mTimeStep);
256 mAq_s = (-mTimeStep * Zq_s + mTimeStep * mAq_t) / (2 * mTd0_s + mTimeStep);
257 mBq_s = (mTimeStep * mBq_t + mTimeStep) / (2 * mTd0_s + mTimeStep);
258 mCq_s = (2 * mTd0_s - mTimeStep) / (2 * mTd0_s + mTimeStep);
259 mDq_s = (mTimeStep * mDq_t + Tf * mTimeStep) / (2 * mTd0_s + mTimeStep);
263template <
typename VarType>
265 VarType>::calculateResistanceMatrixConstants() {
266 if (mSGOrder == SGOrder::SG3Order) {
270 if (mSGOrder == SGOrder::SG4Order) {
274 if (mSGOrder == SGOrder::SG5Order || mSGOrder == SGOrder::SG6aOrder ||
275 mSGOrder == SGOrder::SG6bOrder) {
281template <
typename VarType>
282void Base::ReducedOrderSynchronGenerator<VarType>::setInitialValues(
283 Complex initComplexElectricalPower, Real initMechanicalPower,
284 Complex initTerminalVoltage) {
286 mInitElecPower = initComplexElectricalPower;
287 mInitMechPower = initMechanicalPower;
289 mInitVoltage = initTerminalVoltage;
290 mInitVoltageAngle = Math::phase(mInitVoltage);
292 mInitCurrent = std::conj(mInitElecPower / mInitVoltage);
293 mInitCurrentAngle = Math::phase(mInitCurrent);
295 mInitVoltage = mInitVoltage / mBase_V_RMS;
296 mInitCurrent = mInitCurrent / mBase_I_RMS;
298 mInitialValuesSet =
true;
300 SPDLOG_LOGGER_DEBUG(this->mSLog,
301 "\n--- Set initial values ---"
302 "\nInitial active power: {:}W = {:} p.u."
303 "\nInitial reactive power W: {:}W = {:} p.u."
304 "\nInitial terminal voltage magnitude: {:} p.u."
305 "\nInitial terminal voltage phase: {:} rad = ({:}°)"
306 "\nInitial current magnitude: {:} p.u."
307 "\nInitial current phase: {:} rad = ({:}°)"
308 "\n--- Set initial values finished ---\n",
310 mInitElecPower.real(), mInitElecPower.real() / mNomPower,
311 mInitElecPower.imag(), mInitElecPower.imag() / mNomPower,
312 Math::abs(mInitVoltage), Math::phase(mInitVoltage),
313 Math::phaseDeg(mInitVoltage), Math::abs(mInitCurrent),
314 Math::phase(mInitCurrent), Math::phaseDeg(mInitCurrent));
315 this->mSLog->flush();
322 this->updateMatrixNodeIndices();
324 if (!mInitialValuesSet)
325 this->setInitialValues(-this->terminal(0)->singlePower(),
326 -this->terminal(0)->singlePower().real(),
327 this->initialSingleVoltage(0));
330 **mMechTorque = mInitMechPower / mNomPower;
331 mMechTorque_prev = **mMechTorque;
334 Complex Eq0 = mInitVoltage + Complex(0, mLq) * mInitCurrent;
337 **mDelta = Math::phase(Eq0);
340 (**mIdq0)(0, 0) = Math::abs(mInitCurrent) * sin(**mDelta - mInitCurrentAngle);
341 (**mIdq0)(1, 0) = Math::abs(mInitCurrent) * cos(**mDelta - mInitCurrentAngle);
344 (**mVdq0)(0, 0) = Math::abs(mInitVoltage) * sin(**mDelta - mInitVoltageAngle);
345 (**mVdq0)(1, 0) = Math::abs(mInitVoltage) * cos(**mDelta - mInitVoltageAngle);
348 **mEf = Math::abs(Eq0) + (mLd - mLq) * (**mIdq0)(0, 0);
353 mExciter->initializeStates(Math::abs(mInitVoltage), **mEf);
355 if (mHasTurbineGovernor) {
356 mTurbineGovernor->initializeStates(**mMechTorque);
358 if (mHasGovernorAndTurbine) {
359 mGovernor->initializeStates(**mMechTorque);
360 mTurbine->initializeStates(**mMechTorque);
363 mPSS->initializeStates(mNomOmega / mBase_OmMech, **mMechTorque,
364 (**mVdq0)(0, 0), (**mVdq0)(1, 0));
369 (**mVdq0)(0, 0) * (**mIdq0)(0, 0) + (**mVdq0)(1, 0) * (**mIdq0)(1, 0);
372 **mOmMech = mNomOmega / mBase_OmMech;
375 **mThetaMech = **mDelta - PI / 2.;
378 (**mIntfCurrent)(0, 0) = (mInitCurrent * mBase_I).real();
379 (**mIntfCurrent)(1, 0) = (mInitCurrent * mBase_I * SHIFT_TO_PHASE_B).real();
380 (**mIntfCurrent)(2, 0) = (mInitCurrent * mBase_I * SHIFT_TO_PHASE_C).real();
383 (**mIntfVoltage)(0, 0) = (mInitVoltage * mBase_V).real();
384 (**mIntfVoltage)(1, 0) = (mInitVoltage * mBase_V * SHIFT_TO_PHASE_B).real();
385 (**mIntfVoltage)(2, 0) = (mInitVoltage * mBase_V * SHIFT_TO_PHASE_C).real();
387 SPDLOG_LOGGER_DEBUG(this->mSLog,
388 "\n--- Initialization from power flow ---"
389 "\nInitial Vd (per unit): {:f}"
390 "\nInitial Vq (per unit): {:f}"
391 "\nInitial Id (per unit): {:f}"
392 "\nInitial Iq (per unit): {:f}"
393 "\nInitial Ef (per unit): {:f}"
394 "\nInitial mechanical torque (per unit): {:f}"
395 "\nInitial electrical torque (per unit): {:f}"
396 "\nInitial initial mechanical theta (per unit): {:f}"
397 "\nInitial delta (per unit): {:f} (= {:f}°)"
398 "\n--- Initialization from power flow finished ---",
400 (**mVdq0)(0, 0), (**mVdq0)(1, 0), (**mIdq0)(0, 0),
401 (**mIdq0)(1, 0), **mEf, **mMechTorque, **mElecTorque,
402 **mThetaMech, **mDelta, **mDelta * 180 / PI);
403 this->mSLog->flush();
408 Complex>::initializeFromNodesAndTerminals(Real frequency) {
410 this->updateMatrixNodeIndices();
412 if (!mInitialValuesSet)
413 this->setInitialValues(-this->terminal(0)->singlePower(),
414 -this->terminal(0)->singlePower().real(),
415 this->initialSingleVoltage(0));
418 **mMechTorque = mInitMechPower / mNomPower;
419 mMechTorque_prev = **mMechTorque;
422 Complex Eq0 = mInitVoltage + Complex(0, mLq) * mInitCurrent;
425 **mDelta = Math::phase(Eq0);
428 (**mIdq)(0, 0) = Math::abs(mInitCurrent) * sin(**mDelta - mInitCurrentAngle);
429 (**mIdq)(1, 0) = Math::abs(mInitCurrent) * cos(**mDelta - mInitCurrentAngle);
432 (**mVdq)(0, 0) = Math::abs(mInitVoltage) * sin(**mDelta - mInitVoltageAngle);
433 (**mVdq)(1, 0) = Math::abs(mInitVoltage) * cos(**mDelta - mInitVoltageAngle);
436 **mEf = Math::abs(Eq0) + (mLd - mLq) * (**mIdq)(0, 0);
441 mExciter->initializeStates(Math::abs(mInitVoltage), **mEf);
443 if (mHasTurbineGovernor) {
444 mTurbineGovernor->initializeStates(**mMechTorque);
446 if (mHasGovernorAndTurbine) {
447 mGovernor->initializeStates(**mMechTorque);
448 mTurbine->initializeStates(**mMechTorque);
451 mPSS->initializeStates(mNomOmega / mBase_OmMech, **mMechTorque,
452 (**mVdq)(0, 0), (**mVdq)(1, 0));
457 (**mVdq)(0, 0) * (**mIdq)(0, 0) + (**mVdq)(1, 0) * (**mIdq)(1, 0);
460 **mOmMech = mNomOmega / mBase_OmMech;
463 **mThetaMech = **mDelta - PI / 2.;
466 (**mIntfCurrent)(0, 0) = mInitCurrent * mBase_I_RMS;
469 (**mIntfVoltage)(0, 0) = mInitVoltage * mBase_V_RMS;
471 SPDLOG_LOGGER_DEBUG(this->mSLog,
472 "\n--- Initialization from power flow ---"
473 "\nInitial Vd (per unit): {:f}"
474 "\nInitial Vq (per unit): {:f}"
475 "\nInitial Id (per unit): {:f}"
476 "\nInitial Iq (per unit): {:f}"
477 "\nInitial Ef (per unit): {:f}"
478 "\nInitial mechanical torque (per unit): {:f}"
479 "\nInitial electrical torque (per unit): {:f}"
480 "\nInitial initial mechanical theta (per unit): {:f}"
481 "\nInitial delta (per unit): {:f} (= {:f}°)"
482 "\n--- Initialization from power flow finished ---",
484 (**mVdq)(0, 0), (**mVdq)(1, 0), (**mIdq)(0, 0),
485 (**mIdq)(1, 0), **mEf, **mMechTorque, **mElecTorque,
486 **mThetaMech, **mDelta, **mDelta * 180 / PI);
487 this->mSLog->flush();
490template <
typename VarType>
491void Base::ReducedOrderSynchronGenerator<VarType>::mnaCompInitialize(
492 Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
494 this->updateMatrixNodeIndices();
495 mTimeStep = timeStep;
496 calculateVBRconstants();
497 calculateResistanceMatrixConstants();
498 initializeResistanceMatrix();
499 specificInitialization();
503void Base::ReducedOrderSynchronGenerator<Complex>::mnaCompPreStep(
504 Real time, Int timeStepCount) {
509 Real Vpss = mHasPSS ? mPSS->step(**mOmMech, **mElecTorque, (**mVdq)(0, 0),
510 (**mVdq)(1, 0), mTimeStep)
513 **mEf = mExciter->step((**mVdq)(0, 0), (**mVdq)(1, 0), mTimeStep, Vpss);
515 if (mHasGovernorAndTurbine) {
516 mMechTorque_prev = **mMechTorque;
517 Real Pgv = mGovernor->step(**mOmMech, mTimeStep);
518 **mMechTorque = mTurbine->step(Pgv, mTimeStep);
519 }
else if (mHasTurbineGovernor) {
520 mMechTorque_prev = **mMechTorque;
521 **mMechTorque = mTurbineGovernor->step(**mOmMech, mTimeStep);
526 (**mVdq)(0, 0) * (**mIdq)(0, 0) + (**mVdq)(1, 0) * (**mIdq)(1, 0);
527 **mOmMech = **mOmMech +
528 mTimeStep * (1. / (2. * mH) * (mMechTorque_prev - **mElecTorque));
529 **mThetaMech = **mThetaMech + mTimeStep * (**mOmMech * mBase_OmMech);
530 **mDelta = **mDelta + mTimeStep * (**mOmMech - 1.) * mBase_OmMech;
536 (**mRightVector).setZero();
537 mnaCompApplyRightSideVectorStamp(**mRightVector);
541void Base::ReducedOrderSynchronGenerator<Real>::mnaCompPreStep(
542 Real time, Int timeStepCount) {
547 Real Vpss = mHasPSS ? mPSS->step(**mOmMech, **mElecTorque, (**mVdq0)(0, 0),
548 (**mVdq0)(1, 0), mTimeStep)
551 **mEf = mExciter->step((**mVdq0)(0, 0), (**mVdq0)(1, 0), mTimeStep, Vpss);
553 if (mHasGovernorAndTurbine) {
554 mMechTorque_prev = **mMechTorque;
555 Real Pgv = mGovernor->step(**mOmMech, mTimeStep);
556 **mMechTorque = mTurbine->step(Pgv, mTimeStep);
557 }
else if (mHasTurbineGovernor) {
558 mMechTorque_prev = **mMechTorque;
559 **mMechTorque = mTurbineGovernor->step(**mOmMech, mTimeStep);
564 ((**mVdq0)(0, 0) * (**mIdq0)(0, 0) + (**mVdq0)(1, 0) * (**mIdq0)(1, 0));
565 **mOmMech = **mOmMech +
566 mTimeStep * (1. / (2. * mH) * (mMechTorque_prev - **mElecTorque));
567 **mThetaMech = **mThetaMech + mTimeStep * (**mOmMech * mBase_OmMech);
568 **mDelta = **mDelta + mTimeStep * (**mOmMech - 1.) * mBase_OmMech;
574 (**mRightVector).setZero();
575 mnaCompApplyRightSideVectorStamp(**mRightVector);
578template <
typename VarType>
581 AttributeBase::List &attributeDependencies,
582 AttributeBase::List &modifiedAttributes) {
587template <
typename VarType>
588void Base::ReducedOrderSynchronGenerator<VarType>::mnaCompPreStep(
589 Real time, Int timeStepCount) {
592 (**mRightVector).setZero();
593 mnaCompApplyRightSideVectorStamp(**mRightVector);
596template <
typename VarType>
599 AttributeBase::List &attributeDependencies,
600 AttributeBase::List &modifiedAttributes,
601 Attribute<Matrix>::Ptr &leftVector) {
602 attributeDependencies.push_back(leftVector);