DPsim
Loading...
Searching...
No Matches
SP_Ph1_SynchronGeneratorTrStab.cpp
Go to the documentation of this file.
1/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2 * EONERC, RWTH Aachen University
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 *********************************************************************************/
8
10using namespace CPS;
11
15 CompositePowerComp<Complex>(uid, name, true, true, logLevel),
16 mEp(mAttributes->create<Complex>("Ep")),
17 mEp_abs(mAttributes->create<Real>("Ep_mag")),
18 mEp_phase(mAttributes->create<Real>("Ep_phase")),
19 mDelta_p(mAttributes->create<Real>("delta_r")),
20 mRefOmega(mAttributes->createDynamic<Real>("w_ref")),
21 mRefDelta(mAttributes->createDynamic<Real>("delta_ref")) {
24 **mIntfVoltage = MatrixComp::Zero(1, 1);
25 **mIntfCurrent = MatrixComp::Zero(1, 1);
26
27 mStates = Matrix::Zero(10, 1);
28}
29
34 copy->setStandardParametersPU(mNomPower, mNomVolt, mNomFreq, mXpd / mBase_Z,
35 **mInertia, **mRs, mKd);
36 return copy;
37}
38
40 Real nomPower, Real nomVolt, Real nomFreq, Real Ll, Real Lmd, Real Llfd,
41 Real inertia, Real D) {
42 setBaseParameters(nomPower, nomVolt, nomFreq);
43 SPDLOG_LOGGER_INFO(mSLog,
44 "\n--- Base Parameters ---"
45 "\nnomPower: {:f}"
46 "\nnomVolt: {:f}"
47 "\nnomFreq: {:f}",
49
50 // Input is in per unit but all values are converted to absolute values.
53
54 **mLl = Ll;
55 mLmd = Lmd;
56 **mLd = **mLl + mLmd;
57 mLlfd = Llfd;
58 mLfd = mLlfd + mLmd;
59 // M = 2*H where H = inertia
60 **mInertia = inertia;
61 // X'd in absolute values
62 mXpd = mNomOmega * (**mLd - mLmd * mLmd / mLfd) * mBase_L;
63 mLpd = (**mLd - mLmd * mLmd / mLfd) * mBase_L;
64
65 //The units of D are per unit power divided by per unit speed deviation.
66 // D is transformed to an absolute value to obtain Kd, which will be used in the swing equation
67 mKd = D * mNomPower / mNomOmega;
68
69 SPDLOG_LOGGER_INFO(mSLog,
70 "\n--- Parameters ---"
71 "\nimpedance: {:f}"
72 "\ninductance: {:f}"
73 "\ninertia: {:f}"
74 "\ndamping: {:f}",
75 mXpd, mLpd, **mInertia, mKd);
76}
77
79 Real nomPower, Real nomVolt, Real nomFreq, Int polePairNumber, Real Rs,
80 Real Lpd, Real inertiaJ, Real Kd) {
81 setBaseParameters(nomPower, nomVolt, nomFreq);
82 SPDLOG_LOGGER_INFO(mSLog,
83 "\n--- Base Parameters ---"
84 "\nnomPower: {:f}"
85 "\nnomVolt: {:f}"
86 "\nnomFreq: {:f}",
88
91
92 // M = 2*H where H = inertia
93 // H = J * 0.5 * omegaNom^2 / polePairNumber
94 **mInertia = calcHfromJ(inertiaJ, 2 * PI * nomFreq, polePairNumber);
95 // X'd in absolute values
96 mXpd = mNomOmega * Lpd;
97 mLpd = Lpd;
98
99 SPDLOG_LOGGER_INFO(mSLog,
100 "\n--- Parameters ---"
101 "\nimpedance: {:f}"
102 "\ninductance: {:f}"
103 "\ninertia: {:f}"
104 "\ndamping: {:f}",
105 mXpd, mLpd, **mInertia, mKd);
106}
107
109 Real nomPower, Real nomVolt, Real nomFreq, Real Xpd, Real inertia, Real Rs,
110 Real D) {
111 setBaseParameters(nomPower, nomVolt, nomFreq);
112 SPDLOG_LOGGER_INFO(mSLog,
113 "\n--- Base Parameters ---"
114 "\nnomPower: {:f}"
115 "\nnomVolt: {:f}"
116 "\nnomFreq: {:f}",
118
119 SPDLOG_LOGGER_INFO(mSLog,
120 "\n--- Parameters Per-Unit ---"
121 "\n Xpd: {:f} [p.u.]",
122 Xpd);
123
124 // Input is in per unit but all values are converted to absolute values.
127
128 // M = 2*H where H = inertia
129 **mInertia = inertia;
130 // X'd in absolute values
131 mXpd = Xpd * mBase_Z;
132 mLpd = Xpd * mBase_L;
133
134 **mRs = Rs;
135 //The units of D are per unit power divided by per unit speed deviation.
136 // D is transformed to an absolute value to obtain Kd, which will be used in the swing equation
137 mKd = D * mNomPower / mNomOmega;
138
139 SPDLOG_LOGGER_INFO(mSLog,
140 "\n--- Parameters ---"
141 "\nXpd: {:f} [Ohm]"
142 "\nLpd: {:f} [H]"
143 "\nInertia: {:f} [s]"
144 "\nDamping: {:f}",
145 mXpd, mLpd, **mInertia, mKd);
146}
147
149 Bool convertWithOmegaMech) {
150 mConvertWithOmegaMech = convertWithOmegaMech;
151
152 SPDLOG_LOGGER_INFO(mSLog,
153 "\n--- Model flags ---"
154 "\nconvertWithOmegaMech: {:s}",
155 std::to_string(mConvertWithOmegaMech));
156}
157
159 Real mechPower) {
160 mInitElecPower = elecPower;
161 mInitMechPower = mechPower;
162}
163
182
184 Real frequency) {
185 // Initialize omega mech with nominal system frequency
186 **mOmMech = mNomOmega;
187
188 // Static calculation based on load flow
189 (**mIntfVoltage)(0, 0) = initialSingleVoltage(0);
191 ? -terminal(0)->singlePower()
195
196 //I_intf is the current which is flowing into the Component, while mInitElecPower is flowing out of it
197 (**mIntfCurrent)(0, 0) = std::conj(-mInitElecPower / (**mIntfVoltage)(0, 0));
198
200
201 // Calculate initial emf behind reactance from power flow results
202 **mEp = (**mIntfVoltage)(0, 0) - mImpedance * (**mIntfCurrent)(0, 0);
203
204 // The absolute value of Ep is constant, only delta_p changes every step
205 **mEp_abs = Math::abs(**mEp);
206 // Delta_p is the angular position of mEp with respect to the synchronously rotating reference
207 **mDelta_p = Math::phase(**mEp);
208
209 // Update electrical power
210 // TODO: review for Rs != 0
212 ((**mIntfVoltage)(0, 0) * std::conj(-(**mIntfCurrent)(0, 0))).real();
214 ((**mIntfVoltage)(0, 0) * std::conj(-(**mIntfCurrent)(0, 0))).imag();
215
216 // Start in steady state so that electrical and mech. power are the same
217 // because of the initial condition mOmMech = mNomOmega the damping factor is not considered at the initialisation
218 // TODO: review for Rs != 0
220
221 // Initialize node between X'd and Ep
222 mVirtualNodes[0]->setInitialVoltage(**mEp);
223
224 // Set emf on the already-created voltage source; the framework's generic
225 // sub-init loop will initialize it after this hook returns.
226 mSubVoltageSource->setParameters(**mEp);
227
228 SPDLOG_LOGGER_INFO(mSLog,
229 "\n--- Initialize according to powerflow ---"
230 "\nTerminal 0 voltage: {:e}<{:e}"
231 "\nVoltage behind reactance: {:e}<{:e}"
232 "\ninitial electrical power: {:e}+j{:e}"
233 "\nactive electrical power: {:e}"
234 "\nreactive electrical power: {:e}"
235 "\nmechanical power: {:e}"
236 "\n--- End of powerflow initialization ---",
237 Math::abs((**mIntfVoltage)(0, 0)),
242}
243
245
246 // #### Calculations based on values from time step k ####
247 // Electrical power at time step k
248 // TODO: review for Rs != 0
250 ((**mIntfVoltage)(0, 0) * std::conj(-(**mIntfCurrent)(0, 0))).real();
252 ((**mIntfVoltage)(0, 0) * std::conj(-(**mIntfCurrent)(0, 0))).imag();
253
254 // Mechanical speed derivative at time step k
255 // convert torque to power with actual rotor angular velocity or nominal omega
256 Real dOmMech;
258 dOmMech =
259 mNomOmega * mNomOmega / (2. * **mInertia * mNomPower * **mOmMech) *
261 else
262 dOmMech =
263 mNomOmega / (2. * **mInertia * mNomPower) *
265
266 // #### Calculate states for time step k+1 applying semi-implicit Euler ####
267 // Mechanical speed at time step k+1 applying Euler forward
269 **mOmMech = **mOmMech + mTimeStep * dOmMech;
270
271 // Derivative of rotor angle at time step k + 1
272 // if reference omega is set, calculate delta with respect to reference
273 Real dDelta_p = **mOmMech - (mUseOmegaRef ? **mRefOmega : mNomOmega);
274
275 // Rotor angle at time step k + 1 applying Euler backward
276 // Update emf - only phase changes
278 **mDelta_p = **mDelta_p + mTimeStep * dDelta_p;
279 **mEp = Complex(**mEp_abs * cos(**mDelta_p), **mEp_abs * sin(**mDelta_p));
280 }
281
283 **mMechPower, **mDelta_p, **mOmMech, dOmMech, dDelta_p,
284 (**mIntfVoltage)(0, 0).real(), (**mIntfVoltage)(0, 0).imag();
285 SPDLOG_LOGGER_DEBUG(mSLog, "\nStates, time {:f}: \n{:s}", time,
287}
288
290 Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
291 mTimeStep = timeStep;
292
293 mMnaTasks.push_back(std::make_shared<AddBStep>(*this));
294}
295
297 AttributeBase::List &prevStepDependencies,
298 AttributeBase::List &attributeDependencies,
299 AttributeBase::List &modifiedAttributes) {
300 // other attributes generally also influence the pre step,
301 // but aren't marked as writable anyway
303 prevStepDependencies.push_back(mIntfVoltage);
304};
305
307 AttributeBase::List &prevStepDependencies,
308 AttributeBase::List &attributeDependencies,
309 AttributeBase::List &modifiedAttributes,
310 Attribute<Matrix>::Ptr &leftVector) {
311 attributeDependencies.push_back(leftVector);
312 modifiedAttributes.push_back(mIntfVoltage);
313};
314
316 Int timeStepCount) {
317 step(time);
318 //change V_ref of subvoltage source
319 mSubVoltageSource->mVoltageRef->set(**mEp);
320}
321
323 Int timeStepCount) {
324 **mGenerator.mRightVector = mGenerator.mSubInductor->mRightVector->get() +
325 mGenerator.mSubVoltageSource->mRightVector->get();
326}
327
329 Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector) {
330 mnaCompUpdateVoltage(**leftVector);
331 mnaCompUpdateCurrent(**leftVector);
332}
333
335 const Matrix &leftVector) {
336 SPDLOG_LOGGER_DEBUG(mSLog, "Read voltage from {:d}", matrixNodeIndex(0));
337 (**mIntfVoltage)(0, 0) =
339}
340
342 const Matrix &leftVector) {
343 SPDLOG_LOGGER_DEBUG(mSLog, "Read current from {:d}", matrixNodeIndex(0));
344 //Current flowing out of component
345 **mIntfCurrent = mSubInductor->mIntfCurrent->get();
346}
347
349 Attribute<Real>::Ptr refOmegaPtr, Attribute<Real>::Ptr refDeltaPtr) {
350 mRefOmega->setReference(refOmegaPtr);
351 mRefDelta->setReference(refDeltaPtr);
352 mUseOmegaRef = true;
353
354 SPDLOG_LOGGER_INFO(mSLog, "Use of reference omega.");
355}
std::vector< Ptr > List
Definition Attribute.h:123
AttributePointer< Attribute< T > > Ptr
Definition Attribute.h:250
Real mNomFreq
nominal frequency fn [Hz]
Real mTimeStep
Simulation time step.
Real mLmd
d-axis mutual inductance Lmd [H]
SynchronGenerator(CPS::AttributeList::Ptr attributeList)
Constructor.
Real mLlfd
field leakage inductance Llfd [H]
const Attribute< Real >::Ptr mMechPower
mechanical Power Pm [W]
Real mNomVolt
nominal voltage Vn [V] (phase-to-phase RMS)
Real mBase_L
base stator inductance
Real mBase_Z
base stator impedance
const Attribute< Real >::Ptr mRs
stator resistance Rs [Ohm]
const Attribute< Real >::Ptr mElecReactivePower
Reactive part of the electrical power.
const Attribute< Real >::Ptr mElecActivePower
Active part of the electrical power.
StateType mStateType
specifies if the machine parameters are transformed to per unit
Real mNomOmega
nominal angular frequency wn [Hz]
const Attribute< Real >::Ptr mLl
leakage inductance Ll [H]
void setBaseParameters(Real nomPower, Real nomVolt, Real nomFreq)
Real mLfd
field inductance Lfd [H]
const Attribute< Real >::Ptr mLd
d-axis inductance Ld [H]
Real mNomPower
nominal power Pn [VA]
const Attribute< Real >::Ptr mOmMech
rotor speed omega_r
Real calcHfromJ(Real J, Real omegaNominal, Int polePairNumber)
const Attribute< Real >::Ptr mInertia
inertia constant H [s] for per unit or moment of inertia J [kg*m^2]
void addMNASubComponent(typename SimPowerComp< Complex >::Ptr subc, MNA_SUBCOMP_TASK_ORDER preStepOrder, MNA_SUBCOMP_TASK_ORDER postStepOrder, Bool contributeToRightVector)
CompositePowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
const Attribute< String >::Ptr mName
Human readable name.
String uid()
Returns unique id.
AttributeList::Ptr mAttributes
Attribute List.
spdlog::level::level_enum Level
Definition Logger.h:33
static String matrixToString(const Matrix &mat)
Definition Logger.cpp:31
static Complex complexFromVectorElement(const Matrix &mat, Matrix::Index row, Int maxFreq=1, Int freqIdx=0)
Definition MathUtils.cpp:94
static Real phaseDeg(Complex value)
Definition MathUtils.cpp:25
static Real phase(Complex value)
Definition MathUtils.cpp:23
static Real abs(Complex value)
Definition MathUtils.cpp:27
Complex mImpedance
Equivalent impedance for loadflow calculation.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre and post step operations.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Bool mConvertWithOmegaMech
Flag for usage of actual mechanical speed for torque conversion (otherwise mNomOmega is used)
void mnaParentPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
SimPowerComp< Complex >::Ptr clone(String name) override
DEPRECATED: Delete method.
void initializeParentFromNodesAndTerminals(Real frequency) override
void setModelFlags(Bool convertWithOmegaMech)
Flags to modify model behavior.
void setInitialValues(Complex elecPower, Real mechPower)
void createSubComponents() override
Constructs and registers MNA subcomponents without emf value; idempotent.
std::shared_ptr< VoltageSource > mSubVoltageSource
Inner voltage source that represents the generator.
const Attribute< Complex >::Ptr mEp
True after createSubComponents() runs; prevents double-construction.
void setStandardParametersPU(Real nomPower, Real nomVolt, Real nomFreq, Real Xpd, Real inertia, Real Rs=0, Real D=0)
Initializes the machine parameters.
const Attribute< Real >::Ptr mDelta_p
Angle by which the emf Ep is leading the terminal voltage.
std::shared_ptr< Inductor > mSubInductor
Inner inductor that represents the generator impedance.
void setReferenceOmega(Attribute< Real >::Ptr refOmegaPtr, Attribute< Real >::Ptr refDeltaPtr)
SynchronGeneratorTrStab(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Real mLpd
Absolute d-axis transient inductance.
void mnaParentInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes variables of component.
void setStandardParametersSI(Real nomPower, Real nomVolt, Real nomFreq, Int polePairNumber, Real Rs, Real Lpd, Real inertiaJ, Real Kd=0)
Initializes the machine parameters.
Bool mUseOmegaRef
Flag for usage of attribute of w_ref (otherwise mNomOmega is used)
Real mXpd
Absolute d-axis transient reactance X'd.
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
void setFundamentalParametersPU(Real nomPower, Real nomVolt, Real nomFreq, Real Ll, Real Lmd, Real Llfd, Real inertia, Real D=0)
Initializes the machine parameters.
UInt matrixNodeIndex(UInt nodeIndex)
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
SimTerminal< Complex >::Ptr terminal(UInt index)
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
std::shared_ptr< SimPowerComp< VarType > > Ptr
SimNode< Complex >::List mVirtualNodes
Complex initialSingleVoltage(UInt index)
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.
static std::shared_ptr< SynchronGeneratorTrStab > make(Args &&...args)
Definition PtrFactory.h:19
#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
bool Bool
Definition Definitions.h:64