DPsim
Loading...
Searching...
No Matches
EMT_Ph3_Transformer.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
10
11using namespace CPS;
12
14 Logger::Level logLevel,
15 Bool withResistiveLosses)
17 CompositePowerComp<Real>(uid, name, true, true, logLevel) {
19 if (withResistiveLosses)
21 else
23
25
26 SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name);
27 **mIntfVoltage = Matrix::Zero(3, 1);
28 **mIntfCurrent = Matrix::Zero(1, 1);
29}
30
39
41 Real nomVoltageSecondary,
42 Real ratedPower, Real ratioAbs,
43 Real ratioPhase, Matrix resistance,
44 Matrix inductance) {
45
46 Base::Ph3::Transformer::setParameters(nomVoltagePrimary, nomVoltageSecondary,
47 ratedPower, ratioAbs, ratioPhase,
48 resistance, inductance);
49
50 SPDLOG_LOGGER_INFO(
51 mSLog,
52 "Nominal Voltage Primary = {} [V] Nominal Voltage Secondary = {} [V]",
54 SPDLOG_LOGGER_INFO(mSLog, "Rated Apparent Power = {} [VA]", mRatedPower);
55 SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]",
56 std::abs(**mRatio), std::arg(**mRatio));
57
58 mParametersSet = true;
59}
60
61void EMT::Ph3::Transformer::resolveWindingRoles() {
62 switch (mReferenceWinding) {
64 mReferenceTerminal = 0;
65 break;
67 mReferenceTerminal = 1;
68 break;
70 SPDLOG_LOGGER_ERROR(mSLog,
71 "Transformer {}: three-winding transformers are "
72 "not implemented",
73 this->name());
76 mReferenceTerminal =
77 (mNominalVoltagePrimary >= mNominalVoltageSecondary) ? 0 : 1;
78 break;
79 }
80 mRatioFromReference = (mReferenceTerminal == 0) ? **mRatio : 1. / **mRatio;
81 mOrientationSign = (mReferenceTerminal == 0) ? 1. : -1.;
82
83 if (Math::abs(std::arg(mRatioFromReference)) > 1e-9) {
84 SPDLOG_LOGGER_ERROR(mSLog,
85 "Turns ratio {} has a phase shift of {} rad. "
86 "EMT::Ph3::Transformer models in-phase turns ratios "
87 "only; a phase-shifting winding connection is not "
88 "implemented.",
89 Logger::complexToString(mRatioFromReference),
90 std::arg(mRatioFromReference));
92 }
93}
94
97 return;
98 mSubCompCreated = true;
99
100 resolveWindingRoles();
101
102 auto midpoint = mVirtualNodes[2];
103
104 mSubInductor =
105 std::make_shared<EMT::Ph3::Inductor>(**mName + "_ind", mLogLevel);
106 mSubInductor->setParameters(mInductance / 2.);
109
110 mSubInductor2 =
111 std::make_shared<EMT::Ph3::Inductor>(**mName + "_ind2", mLogLevel);
112 mSubInductor2->setParameters(mInductance / 2.);
115
116 if (mNumVirtualNodes == 5) {
117 mSubResistor =
118 std::make_shared<EMT::Ph3::Resistor>(**mName + "_res", mLogLevel);
119 mSubResistor->setParameters(mResistance / 2.);
120 mSubResistor->connect({node(mReferenceTerminal), mVirtualNodes[3]});
121 mSubInductor->connect({mVirtualNodes[3], midpoint});
124
125 mSubResistor2 =
126 std::make_shared<EMT::Ph3::Resistor>(**mName + "_res2", mLogLevel);
127 mSubResistor2->setParameters(mResistance / 2.);
128 mSubResistor2->connect({midpoint, mVirtualNodes[4]});
129 mSubInductor2->connect({mVirtualNodes[4], mVirtualNodes[0]});
130 addMNASubComponent(mSubResistor2,
133 } else {
134 mSubInductor->connect({node(mReferenceTerminal), midpoint});
135 mSubInductor2->connect({midpoint, mVirtualNodes[0]});
136 }
137
138 if (mRatedPower <= 0) {
139 SPDLOG_LOGGER_WARN(mSLog,
140 "Transformer {}: rated power is {} [VA], so the "
141 "magnetizing branch cannot be sized and is omitted",
142 this->name(), mRatedPower);
143 return;
144 }
145
146 if (mNoLoadCurrent <= mNoLoadLoss) {
147 SPDLOG_LOGGER_ERROR(mSLog,
148 "Transformer {}: no-load current {} must exceed the "
149 "no-load loss {}",
150 this->name(), mNoLoadCurrent, mNoLoadLoss);
152 }
153
154 Real magnetizingResistance =
155 std::pow(nominalVoltageAt(mReferenceTerminal), 2) /
156 (mNoLoadLoss * mRatedPower);
157 mMagnetizingResistance =
158 Math::singlePhaseParameterToThreePhase(magnetizingResistance);
159 mSubMagnetizingResistor =
160 std::make_shared<EMT::Ph3::Resistor>(**mName + "_mag_res", mLogLevel);
161 mSubMagnetizingResistor->setParameters(mMagnetizingResistance);
162 mSubMagnetizingResistor->connect({midpoint, EMT::SimNode::GND});
163 addMNASubComponent(mSubMagnetizingResistor,
166
167 mSubMagnetizingInductor =
168 std::make_shared<EMT::Ph3::Inductor>(**mName + "_mag_ind", mLogLevel);
169 mSubMagnetizingInductor->connect({midpoint, EMT::SimNode::GND});
170 addMNASubComponent(mSubMagnetizingInductor,
173}
174
176 Real frequency) {
177 // Set initial voltage of virtual node in between
178 mVirtualNodes[0]->setInitialVoltage(
179 initialSingleVoltage(nonReferenceTerminal()) * mRatioFromReference);
180
181 // Static calculations from load flow data
182 Real omega = 2. * PI * frequency;
183
184 if (mSubMagnetizingInductor) {
185 Real magnetizingSusceptance =
186 std::sqrt(std::pow(mNoLoadCurrent, 2) - std::pow(mNoLoadLoss, 2)) *
187 mRatedPower / std::pow(nominalVoltageAt(mReferenceTerminal), 2);
188 Real magnetizingInductance = 1. / (omega * magnetizingSusceptance);
189 mMagnetizingInductance =
190 Math::singlePhaseParameterToThreePhase(magnetizingInductance);
191 mSubMagnetizingInductor->setParameters(mMagnetizingInductance);
192 SPDLOG_LOGGER_INFO(mSLog, "Magnetizing inductance = {} [H]",
193 Logger::matrixToString(mMagnetizingInductance));
194 }
195
196 MatrixComp impedance = MatrixComp::Zero(3, 3);
197 impedance << Complex(mResistance(0, 0), omega * mInductance(0, 0)),
198 Complex(mResistance(0, 1), omega * mInductance(0, 1)),
199 Complex(mResistance(0, 2), omega * mInductance(0, 2)),
200 Complex(mResistance(1, 0), omega * mInductance(1, 0)),
201 Complex(mResistance(1, 1), omega * mInductance(1, 1)),
202 Complex(mResistance(1, 2), omega * mInductance(1, 2)),
203 Complex(mResistance(2, 0), omega * mInductance(2, 0)),
204 Complex(mResistance(2, 1), omega * mInductance(2, 1)),
205 Complex(mResistance(2, 2), omega * mInductance(2, 2));
206
207 SPDLOG_LOGGER_INFO(mSLog,
208 "Resistance (referred to higher voltage side) = {} [Ohm]",
210 SPDLOG_LOGGER_INFO(mSLog,
211 "Inductance (referred to higher voltage side) = {} [H]",
213 SPDLOG_LOGGER_INFO(mSLog,
214 "Reactance (referred to higher voltage side) = {} [Ohm]",
216
217 MatrixComp vInitABC = MatrixComp::Zero(3, 1);
218 vInitABC(0, 0) =
219 RMS3PH_TO_PEAK1PH * (mVirtualNodes[0]->initialSingleVoltage() -
220 initialSingleVoltage(mReferenceTerminal));
221 vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B;
222 vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C;
223
224 MatrixComp vTerminalABC = MatrixComp::Zero(3, 1);
225 vTerminalABC(0, 0) =
227 vTerminalABC(1, 0) = vTerminalABC(0, 0) * SHIFT_TO_PHASE_B;
228 vTerminalABC(2, 0) = vTerminalABC(0, 0) * SHIFT_TO_PHASE_C;
229
230 MatrixComp iInit = impedance.inverse() * vInitABC;
231 **mIntfCurrent = iInit.real();
232 **mIntfVoltage = vTerminalABC.real();
233
234 Complex halfImpedance =
235 Complex(mResistance(0, 0) / 2., omega * mInductance(0, 0) / 2.);
236 Complex magnetizingAdmittance = Complex(0, 0);
237 if (mSubMagnetizingInductor)
238 magnetizingAdmittance =
239 1. / mMagnetizingResistance(0, 0) +
240 1. / Complex(0, omega * mMagnetizingInductance(0, 0));
241
242 Complex referenceVoltage = initialSingleVoltage(mReferenceTerminal);
243 Complex midpointVoltage =
244 (referenceVoltage + mVirtualNodes[0]->initialSingleVoltage()) /
245 (2. + halfImpedance * magnetizingAdmittance);
246 mVirtualNodes[2]->setInitialVoltage(midpointVoltage);
247
248 if (mNumVirtualNodes == 5) {
249 Complex referenceCurrent =
250 (referenceVoltage - midpointVoltage) / halfImpedance;
251 Complex nonReferenceCurrent =
252 (midpointVoltage - mVirtualNodes[0]->initialSingleVoltage()) /
253 halfImpedance;
254 mVirtualNodes[3]->setInitialVoltage(
255 referenceVoltage - referenceCurrent * mResistance(0, 0) / 2.);
256 mVirtualNodes[4]->setInitialVoltage(
257 midpointVoltage - nonReferenceCurrent * mResistance(0, 0) / 2.);
258 }
259
260 SPDLOG_LOGGER_INFO(
261 mSLog,
262 "\n--- Initialization from powerflow ---"
263 "\nVoltage across: {:s}"
264 "\nCurrent: {:s}"
265 "\nTerminal 0 voltage: {:s}"
266 "\nTerminal 1 voltage: {:s}"
267 "\nVirtual Node 1 voltage: {:s}"
268 "\n--- Initialization from powerflow finished ---",
275}
276
278 Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
279 SPDLOG_LOGGER_INFO(
280 mSLog,
281 "\nTerminal 0 connected to {:s} = sim node {:d}"
282 "\nTerminal 1 connected to {:s} = sim node {:d}",
285}
286
288 SparseMatrixRow &systemMatrix) {
289 // Ideal transformer equations
290 if (terminalNotGrounded(mReferenceTerminal)) {
292 systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A),
295 systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B),
298 systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C),
300
301 Math::setMatrixElement(systemMatrix,
304 Math::setMatrixElement(systemMatrix,
307 Math::setMatrixElement(systemMatrix,
310 }
311 if (terminalNotGrounded(nonReferenceTerminal())) {
312 Math::setMatrixElement(systemMatrix,
313 matrixNodeIndex(nonReferenceTerminal(), 0),
315 mRatioFromReference.real());
316 Math::setMatrixElement(systemMatrix,
317 matrixNodeIndex(nonReferenceTerminal(), 1),
319 mRatioFromReference.real());
320 Math::setMatrixElement(systemMatrix,
321 matrixNodeIndex(nonReferenceTerminal(), 2),
323 mRatioFromReference.real());
324 Math::setMatrixElement(systemMatrix,
326 matrixNodeIndex(nonReferenceTerminal(), 0),
327 -mRatioFromReference.real());
328 Math::setMatrixElement(systemMatrix,
330 matrixNodeIndex(nonReferenceTerminal(), 1),
331 -mRatioFromReference.real());
332 Math::setMatrixElement(systemMatrix,
334 matrixNodeIndex(nonReferenceTerminal(), 2),
335 -mRatioFromReference.real());
336 }
337
338 // Add subcomps to system matrix
339 for (auto subcomp : mSubComponents)
340 if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
341 mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix);
342
343 if (terminalNotGrounded(0)) {
344 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
348 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
352 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
356
357 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
361 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
365 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
369 }
370 if (terminalNotGrounded(1)) {
371 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
374 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
377 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
380
381 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
384 matrixNodeIndex(1, 0));
385 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
388 matrixNodeIndex(1, 1));
389 SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
392 matrixNodeIndex(1, 2));
393 }
394}
395
397 AttributeBase::List &prevStepDependencies,
398 AttributeBase::List &attributeDependencies,
399 AttributeBase::List &modifiedAttributes) {
400 prevStepDependencies.push_back(mIntfCurrent);
401 prevStepDependencies.push_back(mIntfVoltage);
402 modifiedAttributes.push_back(mRightVector);
403}
404
408
410 AttributeBase::List &prevStepDependencies,
411 AttributeBase::List &attributeDependencies,
412 AttributeBase::List &modifiedAttributes,
413 Attribute<Matrix>::Ptr &leftVector) {
414 attributeDependencies.push_back(leftVector);
415 modifiedAttributes.push_back(mIntfVoltage);
416 modifiedAttributes.push_back(mIntfCurrent);
417}
418
420 Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector) {
421 mnaCompUpdateVoltage(**leftVector);
422 mnaCompUpdateCurrent(**leftVector);
423}
424
426 **mIntfCurrent = mOrientationSign * mSubInductor->intfCurrent();
427}
428
430 // v1 - v0
431 **mIntfVoltage = Matrix::Zero(3, 1);
432 if (terminalNotGrounded(1)) {
433 (**mIntfVoltage)(0, 0) =
435 (**mIntfVoltage)(1, 0) =
437 (**mIntfVoltage)(2, 0) =
439 }
440 if (terminalNotGrounded(0)) {
441 (**mIntfVoltage)(0, 0) =
442 (**mIntfVoltage)(0, 0) -
444 (**mIntfVoltage)(1, 0) =
445 (**mIntfVoltage)(1, 0) -
447 (**mIntfVoltage)(2, 0) =
448 (**mIntfVoltage)(2, 0) -
450 }
451}
std::vector< Ptr > List
Definition Attribute.h:123
AttributePointer< Attribute< T > > Ptr
Definition Attribute.h:249
Real mNominalVoltagePrimary
Nominal voltage of primary side.
Real mNominalVoltageSecondary
Nominal voltage of secondary side.
const Attribute< Complex >::Ptr mRatio
Transformer ratio.
void setParameters(Real nomVoltagePrimary, Real nomVoltageSecondary, Real ratedPower, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance)
Matrix mResistance
Resistance [Ohm].
Matrix mInductance
Inductance [H].
Real nominalVoltageAt(UInt terminal) const
Nominal voltage of the winding at the given terminal.
Real mRatedPower
Rated Apparent Power [VA].
void addMNASubComponent(typename SimPowerComp< Real >::Ptr subc, MNA_SUBCOMP_TASK_ORDER preStepOrder, MNA_SUBCOMP_TASK_ORDER postStepOrder, Bool contributeToRightVector)
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override
CompositePowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
Add MNA pre step dependencies.
Transformer(String uid, String name, Logger::Level logLevel=Logger::Level::off, Bool withResistiveLosses=false)
Defines UID, name and logging level.
void mnaParentPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
MNA post step operations.
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override
Stamps system matrix.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Updates internal voltage variable of the component.
SimPowerComp< Real >::Ptr clone(String name) override
DEPRECATED: Delete method.
void initializeParentFromNodesAndTerminals(Real frequency) override
Initializes component from power flow data.
void createSubComponents() override
Constructs and registers MNA subcomponents; idempotent.
void setParameters(Real nomVoltagePrimary, Real nomVoltageSecondary, Real ratedPower, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance)
Defines component parameters.
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre step operations.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Updates internal current variable of the component.
void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
Add MNA post step dependencies.
void mnaParentInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes internal variables of the component.
const Attribute< String >::Ptr mName
Human readable name.
String uid()
Returns unique id.
String type()
Get component type (cross-platform)
AttributeList::Ptr mAttributes
Attribute List.
spdlog::level::level_enum Level
Definition Logger.h:33
static String complexToString(const Complex &num)
Definition Logger.cpp:63
static String matrixToString(const Matrix &mat)
Definition Logger.cpp:31
static String phasorToString(const Complex &num)
Definition Logger.cpp:57
Attribute< Matrix >::Ptr mRightVector
static Real realFromVectorElement(const Matrix &mat, Matrix::Index row)
static void setMatrixElement(SparseMatrixRow &mat, Matrix::Index row, Matrix::Index column, Complex value, Int maxFreq=1, Int freqIdx=0)
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 Ptr GND
Definition SimNode.h:35
UInt matrixNodeIndex(UInt nodeIndex)
const Attribute< MatrixVar< Real > >::Ptr mIntfCurrent
SimTerminal< Real >::List mTerminals
SimNode< Real >::Ptr node(UInt index)
void setVirtualNodeNumber(UInt num)
const Attribute< MatrixVar< Real > >::Ptr mIntfVoltage
std::shared_ptr< SimPowerComp< VarType > > Ptr
SimNode< Real >::List mVirtualNodes
std::vector< std::shared_ptr< SimPowerComp< Real > > > mSubComponents
Bool terminalNotGrounded(UInt index)
Complex initialSingleVoltage(UInt index)
void setTerminalNumber(UInt num)
Logger::Level mLogLevel
Component logger control for internal variables.
UInt mNumVirtualNodes
Determines the number of virtual or internal Nodes.
bool mParametersSet
Flag indicating that parameters are set via setParameters() function.
Logger::Log mSLog
Component logger.
static std::shared_ptr< Transformer > make(Args &&...args)
Definition PtrFactory.h:19
#define PI
Definition Definitions.h:43
#define RMS3PH_TO_PEAK1PH
Definition Definitions.h:50
#define SHIFT_TO_PHASE_C
Definition Definitions.h:47
#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:79
std::string String
Definition Definitions.h:63
double Real
Definition Definitions.h:60
int Int
Definition Definitions.h:59
std::complex< Real > Complex
Definition Definitions.h:61
Eigen::Matrix< Complex, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > MatrixComp
Dense matrix for complex numbers.
Definition Definitions.h:82
bool Bool
Definition Definitions.h:62
Eigen::SparseMatrix< Real, Eigen::RowMajor > SparseMatrixRow
Sparse matrix for real numbers (row major).
Definition Definitions.h:72