DPsim
DP_Ph1_Transformer.cpp
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 
9 #include <dpsim-models/DP/DP_Ph1_Transformer.h>
10 
11 using namespace CPS;
12 
13 DP::Ph1::Transformer::Transformer(String uid, String name,
14  Logger::Level logLevel,
15  Bool withResistiveLosses)
16  : Base::Ph1::Transformer(mAttributes),
17  CompositePowerComp<Complex>(uid, name, true, true, logLevel) {
18  if (withResistiveLosses)
19  setVirtualNodeNumber(3);
20  else
21  setVirtualNodeNumber(2);
22 
23  setTerminalNumber(2);
24 
25  SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name);
26  **mIntfVoltage = MatrixComp::Zero(1, 1);
27  **mIntfCurrent = MatrixComp::Zero(1, 1);
28 }
29 
32  auto copy = Transformer::make(name, mLogLevel);
33  copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2,
34  std::abs(**mRatio), std::arg(**mRatio), **mResistance,
35  **mInductance);
36  return copy;
37 }
38 
39 void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1,
40  Real nomVoltageEnd2, Real ratioAbs,
41  Real ratioPhase, Real resistance,
42  Real inductance) {
43 
44  Base::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2,
45  ratioAbs, ratioPhase, resistance,
46  inductance);
47 
48  SPDLOG_LOGGER_INFO(
49  mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]",
50  **mNominalVoltageEnd1, **mNominalVoltageEnd2);
51  SPDLOG_LOGGER_INFO(
52  mSLog,
53  "Resistance={} [Ohm] Inductance={} [Ohm] (referred to primary side)",
54  **mResistance, **mInductance);
55  SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [ ] Phase Shift={} [deg]",
56  std::abs(**mRatio), std::arg(**mRatio));
57  SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower);
58 
59  mParametersSet = true;
60 }
61 
62 void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1,
63  Real nomVoltageEnd2, Real ratedPower,
64  Real ratioAbs, Real ratioPhase,
65  Real resistance, Real inductance) {
66 
67  **mRatedPower = ratedPower;
68  SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower);
69 
70  DP::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs,
71  ratioPhase, resistance, inductance);
72 }
73 
75 
76  // Component parameters are referred to higher voltage side.
77  // Switch terminals to have terminal 0 at higher voltage side
78  // if transformer is connected the other way around.
79  if (Math::abs(**mRatio) < 1.) {
80  **mRatio = 1. / **mRatio;
81  std::shared_ptr<SimTerminal<Complex>> tmp = mTerminals[0];
82  mTerminals[0] = mTerminals[1];
83  mTerminals[1] = tmp;
84  Real tmpVolt = **mNominalVoltageEnd1;
85  **mNominalVoltageEnd1 = **mNominalVoltageEnd2;
86  **mNominalVoltageEnd2 = tmpVolt;
87  SPDLOG_LOGGER_INFO(mSLog, "Switching terminals to have first terminal at "
88  "higher voltage side. Updated parameters: ");
89  SPDLOG_LOGGER_INFO(
90  mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]",
91  **mNominalVoltageEnd1, **mNominalVoltageEnd2);
92  SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]",
93  std::abs(**mRatio), std::arg(**mRatio));
94  }
95 
96  // Set initial voltage of virtual node in between
97  mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(1) * **mRatio);
98 
99  // Static calculations from load flow data
100  Real omega = 2. * PI * frequency;
101  Complex impedance = {**mResistance, omega * **mInductance};
102  SPDLOG_LOGGER_INFO(mSLog, "Reactance={} [Ohm] (referred to primary side)",
103  omega * **mInductance);
104  (**mIntfVoltage)(0, 0) =
105  mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0);
106  (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance;
107 
108  // Create series sub components
109  mSubInductor =
110  std::make_shared<DP::Ph1::Inductor>(**mName + "_ind", mLogLevel);
111  mSubInductor->setParameters(**mInductance);
112  addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
113  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
114 
115  if (mNumVirtualNodes == 3) {
116  mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0));
117  mSubResistor =
118  std::make_shared<DP::Ph1::Resistor>(**mName + "_res", mLogLevel);
119  mSubResistor->setParameters(**mResistance);
120  mSubResistor->connect({node(0), mVirtualNodes[2]});
121  mSubInductor->connect({mVirtualNodes[2], mVirtualNodes[0]});
122  addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
123  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
124  } else {
125  mSubInductor->connect({node(0), mVirtualNodes[0]});
126  }
127 
128  // Create parallel sub components
129  Real pSnub = P_SNUB_TRANSFORMER * **mRatedPower;
130  Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower;
131 
132  // A snubber conductance is added on the higher voltage side
133  mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1), 2) / pSnub;
134  mSubSnubResistor1 =
135  std::make_shared<DP::Ph1::Resistor>(**mName + "_snub_res1", mLogLevel);
136  mSubSnubResistor1->setParameters(mSnubberResistance1);
137  mSubSnubResistor1->connect({node(0), DP::SimNode::GND});
138  SPDLOG_LOGGER_INFO(
139  mSLog,
140  "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]",
141  node(0)->name(), Logger::realToString(mSnubberResistance1));
142  addMNASubComponent(mSubSnubResistor1,
143  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
144  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
145 
146  // A snubber conductance is added on the lower voltage side
147  mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2), 2) / pSnub;
148  mSubSnubResistor2 =
149  std::make_shared<DP::Ph1::Resistor>(**mName + "_snub_res2", mLogLevel);
150  mSubSnubResistor2->setParameters(mSnubberResistance2);
151  mSubSnubResistor2->connect({node(1), DP::SimNode::GND});
152  SPDLOG_LOGGER_INFO(
153  mSLog,
154  "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]",
155  node(1)->name(), Logger::realToString(mSnubberResistance2));
156  addMNASubComponent(mSubSnubResistor2,
157  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
158  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
159 
160  // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse)
161  // mSnubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / omega;
162  // mSubSnubCapacitor1 = std::make_shared<DP::Ph1::Capacitor>(**mName + "_snub_cap1", mLogLevel);
163  // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1);
164  // mSubSnubCapacitor1->connect({ node(0), DP::SimNode::GND });
165  // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::realToString(mSnubberCapacitance1));
166  // mSubComponents.push_back(mSubSnubCapacitor1);
167 
168  // A snubber capacitance is added to lower voltage side
169  mSnubberCapacitance2 =
170  qSnub / std::pow(std::abs(**mNominalVoltageEnd2), 2) / omega;
171  mSubSnubCapacitor2 =
172  std::make_shared<DP::Ph1::Capacitor>(**mName + "_snub_cap2", mLogLevel);
173  mSubSnubCapacitor2->setParameters(mSnubberCapacitance2);
174  mSubSnubCapacitor2->connect({node(1), DP::SimNode::GND});
175  SPDLOG_LOGGER_INFO(
176  mSLog,
177  "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]",
178  node(1)->name(), Logger::realToString(mSnubberCapacitance2));
179  addMNASubComponent(mSubSnubCapacitor2,
180  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
181  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
182 
183  // Initialize electrical subcomponents
184  SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: ");
185  for (auto subcomp : mSubComponents) {
186  SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name());
187  subcomp->initialize(mFrequencies);
188  subcomp->initializeFromNodesAndTerminals(frequency);
189  }
190 
191  SPDLOG_LOGGER_INFO(
192  mSLog,
193  "\n--- Initialization from powerflow ---"
194  "\nVoltage across: {:s}"
195  "\nCurrent: {:s}"
196  "\nTerminal 0 voltage: {:s}"
197  "\nTerminal 1 voltage: {:s}"
198  "\nVirtual Node 1 voltage: {:s}"
199  "\n--- Initialization from powerflow finished ---",
200  Logger::phasorToString((**mIntfVoltage)(0, 0)),
201  Logger::phasorToString((**mIntfCurrent)(0, 0)),
202  Logger::phasorToString(initialSingleVoltage(0)),
203  Logger::phasorToString(initialSingleVoltage(1)),
204  Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage()));
205 }
206 
208  Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
209  SPDLOG_LOGGER_INFO(
210  mSLog,
211  "\nTerminal 0 connected to {:s} = sim node {:d}"
212  "\nTerminal 1 connected to {:s} = sim node {:d}",
213  mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(),
214  mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex());
215 }
216 
218  SparseMatrixRow &systemMatrix) {
219  // Ideal transformer equations
220  if (terminalNotGrounded(0)) {
221  Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(),
222  mVirtualNodes[1]->matrixNodeIndex(),
223  Complex(-1.0, 0));
224  Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(),
225  mVirtualNodes[0]->matrixNodeIndex(),
226  Complex(1.0, 0));
227  }
228  if (terminalNotGrounded(1)) {
229  Math::setMatrixElement(systemMatrix, matrixNodeIndex(1),
230  mVirtualNodes[1]->matrixNodeIndex(), **mRatio);
231  Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(),
232  matrixNodeIndex(1), -**mRatio);
233  }
234 
235  // Add subcomps to system matrix
236  for (auto subcomp : mSubComponents)
237  if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
238  mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix);
239 
240  if (terminalNotGrounded(0)) {
241  SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
242  Logger::complexToString(Complex(-1.0, 0)),
243  mVirtualNodes[0]->matrixNodeIndex(),
244  mVirtualNodes[1]->matrixNodeIndex());
245  SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
246  Logger::complexToString(Complex(1.0, 0)),
247  mVirtualNodes[1]->matrixNodeIndex(),
248  mVirtualNodes[0]->matrixNodeIndex());
249  }
250  if (terminalNotGrounded(1)) {
251  SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
252  Logger::complexToString(**mRatio), matrixNodeIndex(1),
253  mVirtualNodes[1]->matrixNodeIndex());
254  SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})",
255  Logger::complexToString(-**mRatio),
256  mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1));
257  }
258 }
259 
261  AttributeBase::List &prevStepDependencies,
262  AttributeBase::List &attributeDependencies,
263  AttributeBase::List &modifiedAttributes) {
264  prevStepDependencies.push_back(mIntfCurrent);
265  prevStepDependencies.push_back(mIntfVoltage);
266  modifiedAttributes.push_back(mRightVector);
267 }
268 
269 void DP::Ph1::Transformer::mnaParentPreStep(Real time, Int timeStepCount) {
270  this->mnaApplyRightSideVectorStamp(**this->mRightVector);
271 }
272 
274  AttributeBase::List &prevStepDependencies,
275  AttributeBase::List &attributeDependencies,
276  AttributeBase::List &modifiedAttributes,
277  Attribute<Matrix>::Ptr &leftVector) {
278  attributeDependencies.push_back(leftVector);
279  modifiedAttributes.push_back(mIntfVoltage);
280  modifiedAttributes.push_back(mIntfCurrent);
281 }
282 
284  Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector) {
285  this->mnaUpdateVoltage(**leftVector);
286  this->mnaUpdateCurrent(**leftVector);
287 }
288 
289 void DP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix &leftVector) {
290  (**mIntfCurrent)(0, 0) = mSubInductor->intfCurrent()(0, 0);
291 }
292 
293 void DP::Ph1::Transformer::mnaCompUpdateVoltage(const Matrix &leftVector) {
294  // v1 - v0
295  (**mIntfVoltage)(0, 0) = 0;
296  (**mIntfVoltage)(0, 0) =
297  Math::complexFromVectorElement(leftVector, matrixNodeIndex(1));
298  (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) -
299  Math::complexFromVectorElement(
300  leftVector, mVirtualNodes[0]->matrixNodeIndex());
301  SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}",
302  Logger::phasorToString((**mIntfVoltage)(0, 0)));
303 }
Base class for composite power components.
Transformer that includes an inductance and resistance.
void initializeFromNodesAndTerminals(Real frequency) override
Initializes component from power flow data.
void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance)
Defines component parameters.
Transformer(String uid, String name, Logger::Level logLevel=Logger::Level::off, Bool withResistiveLosses=false)
Defines UID, name and logging level.
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override
Stamps system matrix.
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre step operations.
void mnaParentInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes internal variables 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 mnaCompUpdateVoltage(const Matrix &leftVector) override
Updates internal voltage variable of the component.
SimPowerComp< Complex >::Ptr clone(String name) override
DEPRECATED: Delete method.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Updates internal current variable of the component.
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
Add MNA pre step dependencies.
void mnaParentPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
MNA post step operations.
String type()
Get component type (cross-platform)
Base class for all components that are transmitting power.
Definition: SimPowerComp.h:17
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
Current through component.
Definition: SimPowerComp.h:47
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
Voltage between terminals.
Definition: SimPowerComp.h:45
Logger::Log mSLog
Component logger.