9#include <dpsim-models/MathUtils.h>
10#include <dpsim-models/SP/SP_Ph1_Transformer.h>
16 Logger::Level logLevel,
17 Bool withResistiveLosses)
26 if (withResistiveLosses)
27 setVirtualNodeNumber(3);
29 setVirtualNodeNumber(2);
31 SPDLOG_LOGGER_INFO(
mSLog,
"Create {} {}", this->
type(), name);
42 Real nomVoltageEnd2, Real ratioAbs,
43 Real ratioPhase, Real resistance,
47 Base::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2,
48 ratioAbs, ratioPhase, resistance,
52 mSLog,
"Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]",
55 mSLog,
"Resistance={} [Ohm] Inductance={} [H] (referred to primary side)",
57 SPDLOG_LOGGER_INFO(
mSLog,
"Tap Ratio={} [/] Phase Shift={} [deg]",
61 mRatioAbs = std::abs(**
mRatio);
62 mRatioPhase = std::arg(**
mRatio);
68 Real nomVoltageEnd2, Real ratedPower,
69 Real ratioAbs, Real ratioPhase,
70 Real resistance, Real inductance) {
75 SPDLOG_LOGGER_ERROR(
mSLog,
"Rated power {} [VA] is negative; must be >= 0",
84 ratioPhase, resistance, inductance);
89 auto copy = Transformer::make(name,
mLogLevel);
102 if (Math::abs(**
mRatio) < 1.) {
104 mRatioAbs = std::abs(**
mRatio);
105 mRatioPhase = std::arg(**
mRatio);
106 std::shared_ptr<SimTerminal<Complex>> tmp =
mTerminals[0];
112 SPDLOG_LOGGER_INFO(
mSLog,
"Switching terminals to have first terminal at "
113 "higher voltage side. Updated parameters: ");
115 mSLog,
"Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]",
117 SPDLOG_LOGGER_INFO(
mSLog,
"Tap Ratio = {} [ ] Phase Shift = {} [deg]",
118 mRatioAbs, mRatioPhase);
124 mSubInductor = std::make_shared<SP::Ph1::Inductor>(
125 **
mUID +
"_ind", **
mName +
"_ind", Logger::Level::off);
128 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
131 mSubResistor = std::make_shared<SP::Ph1::Resistor>(
132 **
mUID +
"_res", **
mName +
"_res", Logger::Level::off);
137 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
146 bool snubbersEnabled =
147 (
mBehaviour == TopologicalPowerComp::Behaviour::Initialization ||
148 mBehaviour == TopologicalPowerComp::Behaviour::MNASimulation);
150 SPDLOG_LOGGER_WARN(
mSLog,
151 "Rated power is {} [VA]; snubbers disabled for this "
152 "transformer (cannot be sized off non-positive power).",
154 snubbersEnabled =
false;
156 if (snubbersEnabled) {
159 std::make_shared<SP::Ph1::Resistor>(**
mName +
"_snub_res1",
mLogLevel);
160 mSubSnubResistor1->connect({
node(0), SP::SimNode::GND});
162 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
163 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
166 std::make_shared<SP::Ph1::Resistor>(**
mName +
"_snub_res2",
mLogLevel);
167 mSubSnubResistor2->connect({
node(1), SP::SimNode::GND});
169 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
170 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
173 std::make_shared<SP::Ph1::Capacitor>(**
mName +
"_snub_cap2",
mLogLevel);
174 mSubSnubCapacitor2->connect({
node(1), SP::SimNode::GND});
176 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
177 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
183 mNominalOmega = 2. * PI * frequency;
185 SPDLOG_LOGGER_INFO(
mSLog,
"Reactance={} [Ohm] (referred to primary side)",
188 if (mSubSnubResistor1) {
194 mSubSnubResistor1->setParameters(mSnubberResistance1);
197 "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]",
198 node(0)->name(), Logger::realToString(mSnubberResistance1));
203 mSubSnubResistor2->setParameters(mSnubberResistance2);
206 "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]",
207 node(1)->name(), Logger::realToString(mSnubberResistance2));
220 mSnubberCapacitance2 =
222 mSubSnubCapacitor2->setParameters(mSnubberCapacitance2);
225 "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]",
226 node(1)->name(), Logger::realToString(mSnubberCapacitance2));
235 (**mIntfVoltage)(0, 0) =
236 mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0);
237 (**mIntfCurrent)(0, 0) = (**
mIntfVoltage)(0, 0) / impedance;
240 mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0));
244 "\n--- Initialization from powerflow ---"
245 "\nVoltage across: {:s}"
247 "\nTerminal 0 voltage: {:s}"
248 "\nTerminal 1 voltage: {:s}"
249 "\nVirtual Node 1 voltage: {:s}"
250 "\n--- Initialization from powerflow finished ---",
253 Logger::phasorToString(initialSingleVoltage(0)),
254 Logger::phasorToString(initialSingleVoltage(1)),
255 Logger::phasorToString(
mVirtualNodes[0]->initialSingleVoltage()));
268void SP::Ph1::Transformer::setBaseVoltage(Real baseVoltage) {
271 **mBaseVoltage = baseVoltage;
276 SPDLOG_LOGGER_INFO(
mSLog,
"#### Calculate Per Unit Parameters for {}",
278 mBaseApparentPower = baseApparentPower;
279 mBaseOmega = baseOmega;
280 SPDLOG_LOGGER_INFO(
mSLog,
"Base Power={} [VA] Base Omega={} [1/s]",
281 baseApparentPower, baseOmega);
284 mBaseAdmittance = 1.0 / mBaseImpedance;
285 mBaseCurrent = baseApparentPower /
288 SPDLOG_LOGGER_INFO(
mSLog,
"Base Voltage={} [V] Base Impedance={} [Ohm]",
291 mResistancePerUnit = **
mResistance / mBaseImpedance;
292 mReactancePerUnit = mReactance / mBaseImpedance;
293 SPDLOG_LOGGER_INFO(
mSLog,
"Resistance={} [pu] Reactance={} [pu]",
294 mResistancePerUnit, mReactancePerUnit);
296 mBaseInductance = mBaseImpedance / mBaseOmega;
297 mInductancePerUnit = **
mInductance / mBaseInductance;
299 mLeakagePerUnit = Complex(mResistancePerUnit, 1. * mInductancePerUnit);
300 SPDLOG_LOGGER_INFO(
mSLog,
"Leakage Impedance={} [pu] ", mLeakagePerUnit);
303 SPDLOG_LOGGER_INFO(
mSLog,
"Tap Ratio={} [pu]", mRatioAbsPerUnit);
306 if (mSubSnubResistor1)
307 mSubSnubResistor1->calculatePerUnitParameters(mBaseApparentPower);
308 if (mSubSnubResistor2)
309 mSubSnubResistor2->calculatePerUnitParameters(mBaseApparentPower);
310 if (mSubSnubCapacitor1)
311 mSubSnubCapacitor1->calculatePerUnitParameters(mBaseApparentPower);
312 if (mSubSnubCapacitor2)
313 mSubSnubCapacitor2->calculatePerUnitParameters(mBaseApparentPower);
317 SparseMatrixCompRow &Y) {
319 mY_element = MatrixComp(2, 2);
320 Complex y = Complex(1, 0) / mLeakagePerUnit;
322 mY_element(0, 0) = y;
323 mY_element(0, 1) = -y * mRatioAbsPerUnit;
324 mY_element(1, 0) = -y * mRatioAbsPerUnit;
325 mY_element(1, 1) = y * std::pow(mRatioAbsPerUnit, 2);
328 for (
int i = 0; i < 2; i++)
329 for (
int j = 0; j < 2; j++)
330 if (!Math::isFinite(mY_element.coeff(i, j))) {
333 "Transformer {}: non-finite per-unit admittance {} "
334 "in element Y({},{}) (leakage {}, tap {})",
335 this->name(), Logger::complexToString(mY_element.coeff(i, j)), i, j,
336 Logger::complexToString(mLeakage), mRatioAbsPerUnit);
341 Y.coeffRef(this->matrixNodeIndex(0), this->matrixNodeIndex(0)) +=
342 mY_element.coeff(0, 0);
343 Y.coeffRef(this->matrixNodeIndex(0), this->matrixNodeIndex(1)) +=
344 mY_element.coeff(0, 1);
345 Y.coeffRef(this->matrixNodeIndex(1), this->matrixNodeIndex(1)) +=
346 mY_element.coeff(1, 1);
347 Y.coeffRef(this->matrixNodeIndex(1), this->matrixNodeIndex(0)) +=
348 mY_element.coeff(1, 0);
350 SPDLOG_LOGGER_INFO(
mSLog,
"#### Y matrix stamping: {}", mY_element);
352 if (mSubSnubResistor1)
353 mSubSnubResistor1->pfApplyAdmittanceMatrixStamp(Y);
354 if (mSubSnubResistor2)
355 mSubSnubResistor2->pfApplyAdmittanceMatrixStamp(Y);
356 if (mSubSnubCapacitor1)
357 mSubSnubCapacitor1->pfApplyAdmittanceMatrixStamp(Y);
358 if (mSubSnubCapacitor2)
359 mSubSnubCapacitor2->pfApplyAdmittanceMatrixStamp(Y);
363 VectorComp &powerflow) {
364 **
mCurrent = current * mBaseCurrent;
379 Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
382 "\nTerminal 0 connected to {:s} = sim node {:d}"
383 "\nTerminal 1 connected to {:s} = sim node {:d}",
389 SparseMatrixRow &systemMatrix) {
391 if (terminalNotGrounded(0)) {
392 Math::setMatrixElement(systemMatrix,
mVirtualNodes[0]->matrixNodeIndex(),
395 Math::setMatrixElement(systemMatrix,
mVirtualNodes[1]->matrixNodeIndex(),
399 if (terminalNotGrounded(1)) {
400 Math::setMatrixElement(systemMatrix, matrixNodeIndex(1),
402 Math::setMatrixElement(systemMatrix,
mVirtualNodes[1]->matrixNodeIndex(),
403 matrixNodeIndex(1), -**
mRatio);
408 if (
auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
409 mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix);
411 if (terminalNotGrounded(0)) {
412 SPDLOG_LOGGER_INFO(
mSLog,
"Add {:s} to system at ({:d},{:d})",
413 Logger::complexToString(Complex(-1.0, 0)),
416 SPDLOG_LOGGER_INFO(
mSLog,
"Add {:s} to system at ({:d},{:d})",
417 Logger::complexToString(Complex(1.0, 0)),
421 if (terminalNotGrounded(1)) {
422 SPDLOG_LOGGER_INFO(
mSLog,
"Add {:s} to system at ({:d},{:d})",
423 Logger::complexToString(**
mRatio), matrixNodeIndex(1),
425 SPDLOG_LOGGER_INFO(
mSLog,
"Add {:s} to system at ({:d},{:d})",
426 Logger::complexToString(-**
mRatio),
432 AttributeBase::List &prevStepDependencies,
433 AttributeBase::List &attributeDependencies,
434 AttributeBase::List &modifiedAttributes) {
445 AttributeBase::List &prevStepDependencies,
446 AttributeBase::List &attributeDependencies,
447 AttributeBase::List &modifiedAttributes,
448 Attribute<Matrix>::Ptr &leftVector) {
449 attributeDependencies.push_back(leftVector);
455 Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector) {
461 (**mIntfCurrent)(0, 0) = mSubInductor->intfCurrent()(0, 0);
462 SPDLOG_LOGGER_DEBUG(
mSLog,
"Current {:s}",
468 (**mIntfVoltage)(0, 0) = 0;
469 (**mIntfVoltage)(0, 0) =
470 Math::complexFromVectorElement(leftVector, matrixNodeIndex(1));
472 Math::complexFromVectorElement(
474 SPDLOG_LOGGER_DEBUG(
mSLog,
"Voltage {:s}",
void addMNASubComponent(typename SimPowerComp< Complex >::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)
const Attribute< String >::Ptr mName
Human readable name.
String uid()
Returns unique id.
String type()
Get component type (cross-platform)
const Attribute< String >::Ptr mUID
Unique identifier.
AttributeList::Ptr mAttributes
Attribute List.
void mnaUpdateCurrent(const Matrix &leftVector) final
void mnaUpdateVoltage(const Matrix &leftVector) final
Attribute< Matrix >::Ptr mRightVector
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
SimTerminal< Complex >::List mTerminals
SimNode< Complex >::Ptr node(UInt index)
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
SimNode< Complex >::List mVirtualNodes
std::vector< std::shared_ptr< SimPowerComp< Complex > > > mSubComponents
void updateMatrixNodeIndices()
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.