9 #include <dpsim-models/EMT/EMT_Ph3_SynchronGeneratorDQ.h>
17 Logger::Level logLevel)
19 Base::SynchronGenerator(mAttributes) {
20 mPhaseType = PhaseType::ABC;
27 Logger::Level logLevel)
30 EMT::Ph3::SynchronGeneratorDQ::~SynchronGeneratorDQ() {}
32 Real EMT::Ph3::SynchronGeneratorDQ::electricalTorque()
const {
33 return **mElecTorque * mBase_T;
36 Real EMT::Ph3::SynchronGeneratorDQ::rotationalSpeed()
const {
37 return **mOmMech * mBase_OmMech;
40 Real EMT::Ph3::SynchronGeneratorDQ::rotorPosition()
const {
return mThetaMech; }
43 Real nomPower, Real nomVolt, Real nomFreq, Int poleNumber, Real nomFieldCur,
44 Real Rs, Real Ll, Real Lmd, Real Lmq, Real Rfd, Real Llfd, Real Rkd,
45 Real Llkd, Real Rkq1, Real Llkq1, Real Rkq2, Real Llkq2, Real inertia,
46 Real initActivePower, Real initReactivePower, Real initTerminalVolt,
47 Real initVoltAngle, Real initMechPower) {
50 nomPower, nomVolt, nomFreq, nomFieldCur, poleNumber, Rs, Ll, Lmd, Lmq,
51 Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2, Llkq2, inertia);
53 SPDLOG_LOGGER_INFO(mSLog,
54 "Set base and fundamental parameters in per unit: \n"
55 "nomPower: {:e}\nnomVolt: {:e}\nnomFreq: "
56 "{:e}\npoleNumber: {:d}\nnomFieldCur: {:e}\n"
57 "Rs: {:e}\nLl: {:e}\nLmd: {:e}\nLmq: {:e}\nRfd: "
58 "{:e}\nLlfd: {:e}\nRkd: {:e}\n"
59 "Llkd: {:e}\nRkq1: {:e}\nLlkq1: {:e}\nRkq2: {:e}\nLlkq2: "
60 "{:e}\ninertia: {:e}",
61 nomPower, nomVolt, nomFreq, poleNumber, nomFieldCur, Rs,
62 Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,
65 Base::SynchronGenerator::setInitialValues(initActivePower, initReactivePower,
66 initTerminalVolt, initVoltAngle,
71 "Set initial values: \n"
72 "initActivePower: {:e} [W]\n"
73 "initReactivePower: {:e} [VAr]\n"
74 "initTerminalVolt: {:e} [V] (initTerminalVolt: {:e} [pu])\n"
75 "initVoltAngle: {:e} [deg] \n"
76 "initMechPower: {:e} [W]",
77 mInitElecPower.real(), mInitElecPower.imag(), mInitTerminalVoltage,
78 mInitTerminalVoltage / mBase_V, CPS::Math::radtoDeg(mInitVoltAngle),
82 void EMT::Ph3::SynchronGeneratorDQ::setParametersOperationalPerUnit(
83 Real nomPower, Real nomVolt, Real nomFreq, Int poleNumber, Real nomFieldCur,
84 Real Rs, Real Ld, Real Lq, Real Ld_t, Real Lq_t, Real Ld_s, Real Lq_s,
85 Real Ll, Real Td0_t, Real Tq0_t, Real Td0_s, Real Tq0_s, Real inertia) {
87 setBaseParameters(nomPower, nomVolt, nomFreq, nomFieldCur);
90 "Set base parameters: \n"
91 "nomPower: {:e}\nnomVolt: {:e}\nnomFreq: {:e}\n nomFieldCur: {:e}\n",
92 nomPower, nomVolt, nomFreq, nomFieldCur);
94 setOperationalPerUnitParameters(poleNumber, inertia, Rs, Ld, Lq, Ll, Ld_t,
95 Lq_t, Ld_s, Lq_s, Td0_t, Tq0_t, Td0_s, Tq0_s);
96 SPDLOG_LOGGER_INFO(mSLog,
97 "Set operational parameters in per unit: \n"
98 "poleNumber: {:d}\ninertia: {:e}\n"
99 "Rs: {:e}\nLd: {:e}\nLq: {:e}\nLl: {:e}\n"
100 "Ld_t: {:e}\nLq_t: {:e}\nLd_s: {:e}\nLq_s: {:e}\n"
101 "Td0_t: {:e}\nTq0_t: {:e}\nTd0_s: {:e}\nTq0_s: {:e}\n",
102 poleNumber, inertia, Rs, Ld, Lq, Ll, Ld_t, Lq_t, Ld_s,
103 Lq_s, Td0_t, Tq0_t, Td0_s, Tq0_s);
105 Base::SynchronGenerator::calculateFundamentalFromOperationalParameters();
108 "Set fundamental parameters in per unit: \n"
109 "Rs: {:e}\nLl: {:e}\nLmd: {:e}\nLmq: {:e}\nRfd: {:e}\nLlfd: {:e}\nRkd: "
111 "Llkd: {:e}\nRkq1: {:e}\nLlkq1: {:e}\nRkq2: {:e}\nLlkq2: {:e}\n",
112 **mRs, **mLl, mLmd, mLmq, mRfd, mLlfd, mRkd, mLlkd, mRkq1, mLlkq1, mRkq2,
117 Real initReactivePower,
118 Real initTerminalVolt,
120 Real initMechPower) {
122 Base::SynchronGenerator::setInitialValues(initActivePower, initReactivePower,
123 initTerminalVolt, initVoltAngle,
128 "Set initial values: \n"
129 "initActivePower: {:e} [W]\n"
130 "initReactivePower: {:e} [VAr]\n"
131 "initTerminalVolt: {:e} [V] (initTerminalVolt: {:e} [pu])\n"
132 "initVoltAngle: {:e} [deg] \n"
133 "initMechPower: {:e} [W]",
134 mInitElecPower.real(), mInitElecPower.imag(), mInitTerminalVoltage,
135 mInitTerminalVoltage / mBase_V, CPS::Math::radtoDeg(mInitVoltAngle),
141 SPDLOG_LOGGER_INFO(mSLog,
142 "Apply operational parameters in per unit: \n"
143 "poleNumber: {:d}\ninertia: {:e}\n"
144 "Rs: {:e}\nLd: {:e}\nLq: {:e}\nLl: {:e}\n"
145 "Ld_t: {:e}\nLq_t: {:e}\nLd_s: {:e}\nLq_s: {:e}\n"
146 "Td0_t: {:e}\nTq0_t: {:e}\nTd0_s: {:e}\nTq0_s: {:e}\n",
147 mPoleNumber, **mInertia, **mRs, **mLd, **mLq, **mLl,
148 **mLd_t, **mLq_t, **mLd_s, **mLq_s, **mTd0_t, **mTq0_t,
151 Base::SynchronGenerator::calculateFundamentalFromOperationalParameters();
154 "Updated fundamental parameters in per unit: \n"
155 "Rs: {:e}\nLl: {:e}\nLmd: {:e}\nLmq: {:e}\nRfd: {:e}\nLlfd: {:e}\nRkd: "
157 "Llkd: {:e}\nRkq1: {:e}\nLlkq1: {:e}\nRkq2: {:e}\nLlkq2: {:e}\n",
158 **mRs, **mLl, mLmd, mLmq, mRfd, mLlfd, mRkd, mLlkd, mRkq1, mLlkq1, mRkq2,
164 if (!mInitialValuesSet) {
165 SPDLOG_LOGGER_INFO(mSLog,
"--- Initialization from powerflow ---");
168 Real activePower = -terminal(0)->singlePower().real();
169 Real reactivePower = -terminal(0)->singlePower().imag();
172 Real voltMagnitude = RMS3PH_TO_PEAK1PH * Math::abs(initialSingleVoltage(0));
174 this->setInitialValues(activePower, reactivePower, voltMagnitude,
175 Math::phase(initialSingleVoltage(0)), activePower);
177 SPDLOG_LOGGER_INFO(mSLog,
178 "\nTerminal 0 voltage: {:s}"
179 "\nTerminal 0 power: {:s}"
180 "\n--- Initialization from powerflow finished ---",
181 Logger::phasorToString(initialSingleVoltage(0)),
182 Logger::complexToString(terminal(0)->singlePower()));
184 SPDLOG_LOGGER_INFO(mSLog,
"Initial values already set, skipping "
185 "initializeFromNodesAndTerminals.");
196 mCompensationOn =
false;
197 mCompensationCurrent = Matrix::Zero(3, 1);
199 mRcomp = mRcomp * mBase_Z;
203 calcStateSpaceMatrixDQ();
208 mVdq0 = Matrix::Zero(3, 1);
209 mIdq0 = Matrix::Zero(3, 1);
210 if (mNumDampingWindings == 2) {
211 mVdq0 << mVsr(0, 0), mVsr(3, 0), mVsr(6, 0);
212 mIdq0 << mIsr(0, 0), mIsr(3, 0), mIsr(6, 0);
214 mVdq0 << mVsr(0, 0), mVsr(3, 0), mVsr(5, 0);
215 mIdq0 << mIsr(0, 0), mIsr(3, 0), mIsr(5, 0);
218 **mIntfVoltage = mBase_V * dq0ToAbcTransform(mThetaMech, mVdq0);
219 **mIntfCurrent = mBase_I * dq0ToAbcTransform(mThetaMech, mIdq0);
222 void EMT::Ph3::SynchronGeneratorDQ::mnaCompApplySystemMatrixStamp(
223 SparseMatrixRow &systemMatrix) {
224 if (!mCompensationOn)
227 Real conductance = 1. / mRcomp;
229 if (terminalNotGrounded(0)) {
230 Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0),
231 matrixNodeIndex(0, 0), conductance);
232 Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1),
233 matrixNodeIndex(0, 1), conductance);
234 Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2),
235 matrixNodeIndex(0, 2), conductance);
236 SPDLOG_LOGGER_INFO(mSLog,
"Add {} to {}, {}", conductance,
237 matrixNodeIndex(0, 0), matrixNodeIndex(0, 0));
238 SPDLOG_LOGGER_INFO(mSLog,
"Add {} to {}, {}", conductance,
239 matrixNodeIndex(0, 1), matrixNodeIndex(0, 1));
240 SPDLOG_LOGGER_INFO(mSLog,
"Add {} to {}, {}", conductance,
241 matrixNodeIndex(0, 2), matrixNodeIndex(0, 2));
245 void EMT::Ph3::SynchronGeneratorDQ::mnaCompApplyRightSideVectorStamp(
246 Matrix &rightVector) {
248 mCompensationCurrent = **mIntfVoltage / mRcomp;
253 if (terminalNotGrounded(0)) {
254 Math::setVectorElement(rightVector, matrixNodeIndex(0, 0),
255 -(**mIntfCurrent)(0, 0) +
256 mCompensationCurrent(0, 0));
257 Math::setVectorElement(rightVector, matrixNodeIndex(0, 1),
258 -(**mIntfCurrent)(1, 0) +
259 mCompensationCurrent(1, 0));
260 Math::setVectorElement(rightVector, matrixNodeIndex(0, 2),
261 -(**mIntfCurrent)(2, 0) +
262 mCompensationCurrent(2, 0));
267 const Matrix &leftVector) {
268 (**mIntfVoltage)(0, 0) =
269 Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0));
270 (**mIntfVoltage)(1, 0) =
271 Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1));
272 (**mIntfVoltage)(2, 0) =
273 Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2));
277 AttributeBase::List &prevStepDependencies,
278 AttributeBase::List &attributeDependencies,
279 AttributeBase::List &modifiedAttributes,
281 attributeDependencies.push_back(leftVector);
282 modifiedAttributes.push_back(mIntfVoltage);
285 void EMT::Ph3::SynchronGeneratorDQ::mnaCompPostStep(
287 mnaCompUpdateVoltage(**leftVector);
292 Matrix dq0Vector(3, 1);
293 Matrix abcToDq0(3, 3);
296 abcToDq0 << 2. / 3. * cos(theta), 2. / 3. * cos(theta - 2. * PI / 3.),
297 2. / 3. * cos(theta + 2. * PI / 3.), -2. / 3. * sin(theta),
298 -2. / 3. * sin(theta - 2. * PI / 3.),
299 -2. / 3. * sin(theta + 2. * PI / 3.), 1. / 3., 1. / 3., 1. / 3.;
301 dq0Vector = abcToDq0 * abcVector;
308 Matrix abcVector(3, 1);
309 Matrix dq0ToAbc(3, 3);
312 dq0ToAbc << cos(theta), -sin(theta), 1., cos(theta - 2. * PI / 3.),
313 -sin(theta - 2. * PI / 3.), 1., cos(theta + 2. * PI / 3.),
314 -sin(theta + 2. * PI / 3.), 1.;
316 abcVector = dq0ToAbc * dq0Vector;
void setBaseAndFundamentalPerUnitParameters(Real nomPower, Real nomVolt, Real nomFreq, Real nomFieldCur, Int poleNumber, Real Rs, Real Ll, Real Lmd, Real Lmq, Real Rfd, Real Llfd, Real Rkd, Real Llkd, Real Rkq1, Real Llkq1, Real Rkq2, Real Llkq2, Real inertia)
Initializes the base and fundamental machine parameters in per unit.
Synchronous generator model in dq-reference frame.
void initialize(Matrix frequencies) override
Initialize components with correct network frequencies.
Matrix dq0ToAbcTransform(Real theta, Matrix &dq0)
Inverse Park transform as described in Krause.
virtual void mnaCompUpdateVoltage(const Matrix &leftVector) override
Retrieves calculated voltage from simulation for next step.
void applyParametersOperationalPerUnit()
Calculates fundamental from operational parameters and applies them to the model.
void initializeMatrixAndStates()
Initializes internal states and matrix.
void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
Add MNA post step dependencies.
void setInitialValues(Real initActivePower, Real initReactivePower, Real initTerminalVolt, Real initVoltAngle, Real initMechPower)
Initialize states according to desired initial electrical powerflow and mechanical input power.
void setParametersFundamentalPerUnit(Real nomPower, Real nomVolt, Real nomFreq, Int poleNumber, Real nomFieldCur, Real Rs, Real Ll, Real Lmd, Real Lmq, Real Rfd, Real Llfd, Real Rkd, Real Llkd, Real Rkq1, Real Llkq1, Real Rkq2, Real Llkq2, Real inertia, Real initActivePower, Real initReactivePower, Real initTerminalVolt, Real initVoltAngle, Real initMechPower)
Matrix abcToDq0Transform(Real theta, Matrix &abc)
Park transform as described in Krause.
void initializeFromNodesAndTerminals(Real frequency) override
Initializes component from power flow data.
SynchronGeneratorDQ(String name, String uid, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and logging level.
Base class for all MNA components that are transmitting power.
virtual void initialize(Matrix frequencies)
Initialize components with correct network frequencies.
const Attribute< MatrixVar< Real > >::Ptr mIntfCurrent
Current through component.
const Attribute< MatrixVar< Real > >::Ptr mIntfVoltage
Voltage between terminals.