DPsim
Loading...
Searching...
No Matches
EMT_Ph3_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
13 Real theta, const Matrix &fabc) {
14 // Calculates fdq = Tdq * fabc
15 // Assumes that d-axis starts aligned with phase a
17 Matrix dqvector = Tdq * fabc;
18 return dqvector;
19}
20
22 Real theta) {
23 // Return park matrix for theta
24 // Assumes that d-axis starts aligned with phase a
25 Matrix Tdq = Matrix::Zero(2, 3);
26 Real k = sqrt(2. / 3.);
27 Tdq << k * cos(theta), k * cos(theta - 2. * M_PI / 3.),
28 k * cos(theta + 2. * M_PI / 3.), -k * sin(theta),
29 -k * sin(theta - 2. * M_PI / 3.), -k * sin(theta + 2. * M_PI / 3.);
30 return Tdq;
31}
32
36 CompositePowerComp<Real>(uid, name, true, true, logLevel),
37 mEp(mAttributes->create<Complex>("Ep")),
38 mEp_abs(mAttributes->create<Real>("Ep_mag")),
39 mEp_phase(mAttributes->create<Real>("Ep_phase")),
40 mDelta_p(mAttributes->create<Real>("delta_r")),
41 mRefOmega(mAttributes->createDynamic<Real>("w_ref")),
42 mRefDelta(mAttributes->createDynamic<Real>("delta_ref")) {
45 **mIntfVoltage = Matrix::Zero(3, 1);
46 **mIntfCurrent = Matrix::Zero(3, 1);
47
48 mStates = Matrix::Zero(10, 1);
49}
50
57
59 Real nomPower, Real nomVolt, Real nomFreq, Real Ll, Real Lmd, Real Llfd,
60 Real inertia, Real D) {
61 setBaseParameters(nomPower, nomVolt, nomFreq);
62
63 // Input is in per unit but all values are converted to absolute values.
66
67 **mLl = Ll;
68 mLmd = Lmd;
69 **mLd = **mLl + mLmd;
70 mLlfd = Llfd;
71 mLfd = mLlfd + mLmd;
72 // M = 2*H where H = inertia
73 **mInertia = inertia;
74 // X'd in absolute values
75 mXpd = mNomOmega * (**mLd - mLmd * mLmd / mLfd) * mBase_L;
76 mLpd = (**mLd - mLmd * mLmd / mLfd) * mBase_L;
77
78 SPDLOG_LOGGER_INFO(mSLog,
79 "\n--- Parameters ---"
80 "\nimpedance: {:f}"
81 "\ninductance: {:f}",
82 mXpd, mLpd);
83}
84
86 Real nomPower, Real nomVolt, Real nomFreq, Int polePairNumber, Real Rs,
87 Real Lpd, Real inertiaJ, Real Kd) {
88 setBaseParameters(nomPower, nomVolt, nomFreq);
89
92
93 // M = 2*H where H = inertia
94 // H = J * 0.5 * omegaNom^2 / polePairNumber
95 **mInertia = calcHfromJ(inertiaJ, 2 * PI * nomFreq, polePairNumber);
96 // X'd in absolute values
97 mXpd = mNomOmega * Lpd;
98 mLpd = Lpd;
99
100 SPDLOG_LOGGER_INFO(mSLog,
101 "\n--- Parameters ---"
102 "\nimpedance: {:f}"
103 "\ninductance: {:f}",
104 mXpd, mLpd);
105}
106
108 Real nomPower, Real nomVolt, Real nomFreq, Real Xpd, Real inertia, Real Rs,
109 Real D) {
110 setBaseParameters(nomPower, nomVolt, nomFreq);
111
112 // Input is in per unit but all values are converted to absolute values.
115
116 // M = 2*H where H = inertia
117 **mInertia = inertia;
118 // X'd in absolute values
119 mXpd = Xpd * mBase_Z;
120 mLpd = Xpd * mBase_L;
121
122 **mRs = Rs;
123 //The units of D are per unit power divided by per unit speed deviation.
124 // D is transformed to an absolute value to obtain Kd, which will be used in the swing equation
125 mKd = D * mNomPower / mNomOmega;
126
127 SPDLOG_LOGGER_INFO(mSLog,
128 "\n--- Parameters ---"
129 "\nimpedance: {:f}"
130 "\ninductance: {:f}",
131 mXpd, mLpd);
132}
133
135 Real mechPower) {
136 mInitElecPower = elecPower;
137 mInitMechPower = mechPower;
138}
139
160
162 Real frequency) {
163 // Initialize omega mech with nominal system frequency
164 **mOmMech = mNomOmega;
165
167 ? -terminal(0)->singlePower()
171
172 // use complex interface quantities for initialization calculations
173 MatrixComp intfVoltageComplex = MatrixComp::Zero(3, 1);
174 MatrixComp intfCurrentComplex = MatrixComp::Zero(3, 1);
175 // // derive complex threephase initialization from single phase initial values (only valid for balanced systems)
176 // intfVoltageComplex(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(0);
177 intfVoltageComplex(0, 0) = initialSingleVoltage(0);
178 intfVoltageComplex(1, 0) = intfVoltageComplex(0, 0) * SHIFT_TO_PHASE_B;
179 intfVoltageComplex(2, 0) = intfVoltageComplex(0, 0) * SHIFT_TO_PHASE_C;
180 intfCurrentComplex(0, 0) =
181 std::conj(-2. / 3. * mInitElecPower / intfVoltageComplex(0, 0));
182 intfCurrentComplex(1, 0) = intfCurrentComplex(0, 0) * SHIFT_TO_PHASE_B;
183 intfCurrentComplex(2, 0) = intfCurrentComplex(0, 0) * SHIFT_TO_PHASE_C;
184
185 //save real interface quantities calculated from complex ones
186 **mIntfVoltage = intfVoltageComplex.real();
187 **mIntfCurrent = intfCurrentComplex.real();
188
190
191 // Calculate initial emf behind reactance from power flow results
192 **mEp = intfVoltageComplex(0, 0) - mImpedance * intfCurrentComplex(0, 0);
193
194 // The absolute value of Ep is constant, only delta_p changes every step
195 **mEp_abs = Math::abs(**mEp);
196 // Delta_p is the angular position of mEp with respect to the synchronously rotating reference
197 **mDelta_p = Math::phase(**mEp);
198
199 // // Update active electrical power that is compared with the mechanical power
200 **mElecActivePower = (3. / 2. * intfVoltageComplex(0, 0) *
201 std::conj(-intfCurrentComplex(0, 0)))
202 .real();
203 // mElecActivePower = ( (mEp - (**mIntfVoltage)(0,0)) / mImpedance * (**mIntfVoltage)(0,0) ).real();
204 // For infinite power bus
205 // mElecActivePower = (Math::abs(mEp) * Math::abs((**mIntfVoltage)(0,0)) / mXpd) * sin(mDelta_p);
206
207 // Start in steady state so that electrical and mech. power are the same
208 // because of the initial condition mOmMech = mNomOmega the damping factor is not considered at the initialisation
210
211 // Initialize node between X'd and Ep
212 mVirtualNodes[0]->setInitialVoltage(PEAK1PH_TO_RMS3PH * **mEp);
213
214 MatrixComp vref = MatrixComp::Zero(3, 1);
216
217 // Set emf on the already-created voltage source; the framework's generic
218 // sub-init loop will initialize it after this hook returns.
219 mSubVoltageSource->setParameters(vref, frequency);
220
221 SPDLOG_LOGGER_INFO(mSLog,
222 "\n--- Initialize according to powerflow ---"
223 "\nTerminal 0 voltage: {:e}<{:e}"
224 "\nVoltage behind reactance: {:e}<{:e}"
225 "\ninitial electrical power: {:e}+j{:e}"
226 "\nactive electrical power: {:e}"
227 "\nmechanical power: {:e}"
228 "\n--- End of powerflow initialization ---",
229 Math::abs((**mIntfVoltage)(0, 0)),
233}
234
236 // #### Calculations on input of time step k ####
237 // Transform interface quantities to synchronously rotating DQ reference frame
240 // Update electrical power (minus sign to calculate generated power from consumed current)
241 **mElecActivePower = -1. * (intfVoltageDQ(0, 0) * intfCurrentDQ(0, 0) +
242 intfVoltageDQ(1, 0) * intfCurrentDQ(1, 0));
243
244 // The damping factor Kd is adjusted to obtain a damping ratio of 0.3
245 // Real MaxElecActivePower= Math::abs(mEp) * Math::abs((**mIntfVoltage)(0,0)) / mXpd;
246 // mKd=4*0.3*sqrt(mNomOmega*mInertia*MaxElecActivePower*0.5);
247 mKd = 1 * mNomPower;
248
249 // #### Calculate state for time step k+1 ####
250 // semi-implicit Euler or symplectic Euler method for mechanical equations
251 Real dOmMech =
252 mNomOmega / (2. * **mInertia * mNomPower) *
255 **mOmMech = **mOmMech + mTimeStep * dOmMech;
256 Real dDelta_p = **mOmMech - mNomOmega;
258 **mDelta_p = **mDelta_p + mTimeStep * dDelta_p;
259 // Update emf - only phase changes
261 **mEp = Complex(**mEp_abs * cos(**mDelta_p), **mEp_abs * sin(**mDelta_p));
262
263 // Update nominal system angle
265
266 // mStates << Math::abs(mEp), Math::phaseDeg(mEp), mElecActivePower, mMechPower,
267 // mDelta_p, mOmMech, dOmMech, dDelta_p, (**mIntfVoltage)(0,0).real(), (**mIntfVoltage)(0,0).imag();
268 // SPDLOG_LOGGER_DEBUG(mSLog, "\nStates, time {:f}: \n{:s}", time, Logger::matrixToString(mStates));
269}
270
272 Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
273 mTimeStep = timeStep;
274 mMnaTasks.push_back(std::make_shared<AddBStep>(*this));
275}
276
278 AttributeBase::List &prevStepDependencies,
279 AttributeBase::List &attributeDependencies,
280 AttributeBase::List &modifiedAttributes) {
281 prevStepDependencies.push_back(mIntfVoltage);
282};
283
285 AttributeBase::List &prevStepDependencies,
286 AttributeBase::List &attributeDependencies,
287 AttributeBase::List &modifiedAttributes,
288 Attribute<Matrix>::Ptr &leftVector) {
289 attributeDependencies.push_back(leftVector);
290 modifiedAttributes.push_back(mIntfVoltage);
291};
292
294 Int timeStepCount) {
295 step(time);
296 //change magnitude of subvoltage source
297 MatrixComp vref = MatrixComp::Zero(3, 1);
299 mSubVoltageSource->mVoltageRef->set(vref);
300}
301
303 Int timeStepCount) {
304 **mGenerator.mRightVector = **mGenerator.mSubInductor->mRightVector +
305 **mGenerator.mSubVoltageSource->mRightVector;
306}
307
309 Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector) {
310 mnaCompUpdateVoltage(**leftVector);
311 mnaCompUpdateCurrent(**leftVector);
312}
313
315 const Matrix &leftVector) {
316 SPDLOG_LOGGER_DEBUG(mSLog, "Read voltage from {:d}", matrixNodeIndex(0));
317 (**mIntfVoltage)(0, 0) =
319 (**mIntfVoltage)(1, 0) =
321 (**mIntfVoltage)(2, 0) =
323}
324
326 const Matrix &leftVector) {
327 SPDLOG_LOGGER_DEBUG(mSLog, "Read current from {:d}", matrixNodeIndex(0));
328
329 **mIntfCurrent = **mSubInductor->mIntfCurrent;
330}
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 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< Real >::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)
void setStandardParametersPU(Real nomPower, Real nomVolt, Real nomFreq, Real Xpd, Real inertia, Real Rs=0, Real D=0)
Initializes the machine parameters.
void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
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.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
std::shared_ptr< VoltageSource > mSubVoltageSource
Inner voltage source that represents the generator.
SimPowerComp< Real >::Ptr clone(String name) override
Returns a modified copy of the component with the given suffix added to the name and without.
void mnaParentPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
Retrieves calculated voltage from simulation for next step.
SynchronGeneratorTrStab(String uid, String name, Logger::Level logLevel=Logger::Level::off)
const Attribute< Complex >::Ptr mEp
True after createSubComponents() runs; prevents double-construction.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Matrix parkTransformPowerInvariant(Real theta, const Matrix &fabc)
void mnaParentPreStep(Real time, Int timeStepCount) override
Complex mImpedance
Equivalent impedance for loadflow calculation.
std::shared_ptr< Inductor > mSubInductor
Inner inductor that represents the generator impedance.
void initializeParentFromNodesAndTerminals(Real frequency) override
const Attribute< Real >::Ptr mDelta_p
Angle by which the emf Ep is leading the terminal voltage.
void setInitialValues(Complex elecPower, Real mechPower)
void createSubComponents() override
Constructs and registers MNA subcomponents without emf value; idempotent.
void setFundamentalParametersPU(Real nomPower, Real nomVolt, Real nomFreq, Real Ll, Real Lmd, Real Llfd, Real inertia, Real D=0)
Initializes the machine parameters.
Real mLpd
Absolute d-axis transient inductance.
Real mXpd
Absolute d-axis transient reactance X'd.
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 Real realFromVectorElement(const Matrix &mat, Matrix::Index row)
static Real phaseDeg(Complex value)
Definition MathUtils.cpp:25
static Real phase(Complex value)
Definition MathUtils.cpp:23
static Matrix singlePhaseParameterToThreePhase(Real parameter)
To convert single phase parameters to symmetrical three phase ones.
static Real abs(Complex value)
Definition MathUtils.cpp:27
static MatrixComp singlePhaseVariableToThreePhase(Complex var_1ph)
To convert single phase complex variables (voltages, currents) to symmetrical three phase ones.
static Ptr GND
Definition SimNode.h:35
UInt matrixNodeIndex(UInt nodeIndex)
const Attribute< MatrixVar< Real > >::Ptr mIntfCurrent
SimTerminal< Real >::Ptr terminal(UInt index)
void setVirtualNodeNumber(UInt num)
const Attribute< MatrixVar< Real > >::Ptr mIntfVoltage
std::shared_ptr< SimPowerComp< VarType > > Ptr
SimNode< Real >::List mVirtualNodes
Complex initialSingleVoltage(UInt index)
void setTerminalNumber(UInt num)
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
#define SHIFT_TO_PHASE_C
Definition Definitions.h:47
#define M_PI
Definition Definitions.h:41
#define PEAK1PH_TO_RMS3PH
Definition Definitions.h:51
#define SHIFT_TO_PHASE_B
Definition Definitions.h:46
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
Eigen::Matrix< Complex, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > MatrixComp
Dense matrix for complex numbers.
Definition Definitions.h:84