DPsim
EMT_Ph3_RXLoad.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/EMT/EMT_Ph3_RXLoad.h>
10 
11 using namespace CPS;
12 
13 EMT::Ph3::RXLoad::RXLoad(String uid, String name, Logger::Level logLevel)
14  : CompositePowerComp<Real>(uid, name, true, true, logLevel),
15  mActivePower(mAttributes->create<Matrix>("P")),
16  mReactivePower(mAttributes->create<Matrix>("Q")),
17  mNomVoltage(mAttributes->create<Real>("V_nom")) {
18  mPhaseType = PhaseType::ABC;
19  setTerminalNumber(1);
20 
21  SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name);
22  **mIntfVoltage = Matrix::Zero(3, 1);
23  **mIntfCurrent = Matrix::Zero(3, 1);
24  mSLog->flush();
25 }
26 
27 EMT::Ph3::RXLoad::RXLoad(String name, Logger::Level logLevel)
28  : RXLoad(name, name, logLevel) {}
29 
30 EMT::Ph3::RXLoad::RXLoad(String name, Matrix activePower, Matrix reactivePower,
31  Real volt, Logger::Level logLevel)
32  : RXLoad(name, logLevel) {
33  **mActivePower = activePower;
34  **mReactivePower = reactivePower;
35  mPower = MatrixComp::Zero(3, 3);
36  mPower << Complex((**mActivePower)(0, 0), (**mReactivePower)(0, 0)),
37  Complex((**mActivePower)(0, 1), (**mReactivePower)(0, 1)),
38  Complex((**mActivePower)(0, 2), (**mReactivePower)(0, 2)),
39  Complex((**mActivePower)(1, 0), (**mReactivePower)(1, 0)),
40  Complex((**mActivePower)(1, 1), (**mReactivePower)(1, 1)),
41  Complex((**mActivePower)(1, 2), (**mReactivePower)(1, 2)),
42  Complex((**mActivePower)(2, 0), (**mReactivePower)(2, 0)),
43  Complex((**mActivePower)(2, 1), (**mReactivePower)(2, 1)),
44  Complex((**mActivePower)(2, 2), (**mReactivePower)(2, 2));
45 
46  **mNomVoltage = volt;
47  initPowerFromTerminal = false;
48 }
49 
50 void EMT::Ph3::RXLoad::setParameters(Matrix activePower, Matrix reactivePower,
51  Real volt) {
52  **mActivePower = activePower;
53  **mReactivePower = reactivePower;
54 
55  // complex power
56  mPower = MatrixComp::Zero(3, 3);
57  mPower(0, 0) = {(**mActivePower)(0, 0), (**mReactivePower)(0, 0)};
58  mPower(1, 1) = {(**mActivePower)(1, 1), (**mReactivePower)(1, 1)};
59  mPower(2, 2) = {(**mActivePower)(2, 2), (**mReactivePower)(2, 2)};
60 
61  **mNomVoltage = volt;
62 
63  SPDLOG_LOGGER_INFO(mSLog,
64  "\nActive Power [W]: {}"
65  "\nReactive Power [VAr]: {}",
66  Logger::matrixToString(**mActivePower),
67  Logger::matrixToString(**mReactivePower));
68  SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage={} [V]", **mNomVoltage);
69 
70  initPowerFromTerminal = false;
71 }
72 
74 
75  if (initPowerFromTerminal) {
76  **mActivePower = Matrix::Zero(3, 3);
77  (**mActivePower)(0, 0) = mTerminals[0]->singleActivePower() / 3.;
78  (**mActivePower)(1, 1) = mTerminals[0]->singleActivePower() / 3.;
79  (**mActivePower)(2, 2) = mTerminals[0]->singleActivePower() / 3.;
80 
81  **mReactivePower = Matrix::Zero(3, 3);
82  (**mReactivePower)(0, 0) = mTerminals[0]->singleReactivePower() / 3.;
83  (**mReactivePower)(1, 1) = mTerminals[0]->singleReactivePower() / 3.;
84  (**mReactivePower)(2, 2) = mTerminals[0]->singleReactivePower() / 3.;
85 
86  // complex power
87  mPower = MatrixComp::Zero(3, 3);
88  mPower(0, 0) = {(**mActivePower)(0, 0), (**mReactivePower)(0, 0)};
89  mPower(1, 1) = {(**mActivePower)(1, 1), (**mReactivePower)(1, 1)};
90  mPower(2, 2) = {(**mActivePower)(2, 2), (**mReactivePower)(2, 2)};
91 
92  **mNomVoltage = std::abs(mTerminals[0]->initialSingleVoltage());
93 
94  SPDLOG_LOGGER_INFO(mSLog,
95  "\nActive Power [W]: {}"
96  "\nReactive Power [VAr]: {}",
97  Logger::matrixToString(**mActivePower),
98  Logger::matrixToString(**mReactivePower));
99  SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage={} [V]", **mNomVoltage);
100  }
101 
102  if ((**mActivePower)(0, 0) != 0) {
103  mResistance =
104  std::pow(**mNomVoltage / sqrt(3), 2) * (**mActivePower).inverse();
105  mSubResistor =
106  std::make_shared<EMT::Ph3::Resistor>(**mName + "_res", mLogLevel);
107  mSubResistor->setParameters(mResistance);
108  mSubResistor->connect({SimNode::GND, mTerminals[0]->node()});
109  mSubResistor->initialize(mFrequencies);
110  mSubResistor->initializeFromNodesAndTerminals(frequency);
111  addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
112  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
113  **mIntfCurrent += mSubResistor->intfCurrent();
114  }
115 
116  if ((**mReactivePower)(0, 0) != 0)
117  mReactance =
118  std::pow(**mNomVoltage / sqrt(3), 2) * (**mReactivePower).inverse();
119  else
120  mReactance = Matrix::Zero(1, 1);
121 
122  if (mReactance(0, 0) > 0) {
123  mInductance = mReactance / (2 * PI * frequency);
124 
125  mSubInductor =
126  std::make_shared<EMT::Ph3::Inductor>(**mName + "_ind", mLogLevel);
127  mSubInductor->setParameters(mInductance);
128  mSubInductor->connect({SimNode::GND, mTerminals[0]->node()});
129  mSubInductor->initialize(mFrequencies);
130  mSubInductor->initializeFromNodesAndTerminals(frequency);
131  addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
132  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
133  **mIntfCurrent += mSubInductor->intfCurrent();
134  } else if (mReactance(0, 0) < 0) {
135  mCapacitance = -1 / (2 * PI * frequency) * mReactance.inverse();
136 
137  mSubCapacitor =
138  std::make_shared<EMT::Ph3::Capacitor>(**mName + "_cap", mLogLevel);
139  mSubCapacitor->setParameters(mCapacitance);
140  mSubCapacitor->connect({SimNode::GND, mTerminals[0]->node()});
141  mSubCapacitor->initialize(mFrequencies);
142  mSubCapacitor->initializeFromNodesAndTerminals(frequency);
143  addMNASubComponent(mSubCapacitor,
144  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
145  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
146  **mIntfCurrent += mSubCapacitor->intfCurrent();
147  }
148 
149  MatrixComp vInitABC = MatrixComp::Zero(3, 1);
150  vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * mTerminals[0]->initialSingleVoltage();
151  vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B;
152  vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C;
153  **mIntfVoltage = vInitABC.real();
154 
155  SPDLOG_LOGGER_INFO(
156  mSLog,
157  "\n--- Initialization from powerflow ---"
158  "\nVoltage across: {:s}"
159  "\nCurrent: {:s}"
160  "\nTerminal 0 voltage: {:s}"
161  "\nActive Power: {:s}"
162  "\nReactive Power: {:s}"
163  "\nResistance: {:s}"
164  "\nReactance: {:s}"
165  "\n--- Initialization from powerflow finished ---",
166  Logger::matrixToString(**mIntfVoltage),
167  Logger::matrixToString(**mIntfCurrent),
168  Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)),
169  Logger::matrixToString(**mActivePower),
170  Logger::matrixToString(**mReactivePower),
171  Logger::matrixToString(mResistance), Logger::matrixToString(mReactance));
172  mSLog->flush();
173 }
174 
175 void EMT::Ph3::RXLoad::mnaParentAddPreStepDependencies(
176  AttributeBase::List &prevStepDependencies,
177  AttributeBase::List &attributeDependencies,
178  AttributeBase::List &modifiedAttributes) {
179  modifiedAttributes.push_back(mRightVector);
180 };
181 
182 void EMT::Ph3::RXLoad::mnaParentAddPostStepDependencies(
183  AttributeBase::List &prevStepDependencies,
184  AttributeBase::List &attributeDependencies,
185  AttributeBase::List &modifiedAttributes,
186  Attribute<Matrix>::Ptr &leftVector) {
187  attributeDependencies.push_back(leftVector);
188  modifiedAttributes.push_back(mIntfCurrent);
189  modifiedAttributes.push_back(mIntfVoltage);
190 };
191 
192 void EMT::Ph3::RXLoad::mnaParentPreStep(Real time, Int timeStepCount) {
193  mnaCompApplyRightSideVectorStamp(**mRightVector);
194 }
195 
196 void EMT::Ph3::RXLoad::mnaParentPostStep(Real time, Int timeStepCount,
197  Attribute<Matrix>::Ptr &leftVector) {
198  mnaCompUpdateVoltage(**leftVector);
199  mnaCompUpdateCurrent(**leftVector);
200 }
201 
202 void EMT::Ph3::RXLoad::mnaCompUpdateVoltage(const Matrix &leftVector) {
203  **mIntfVoltage = Matrix::Zero(3, 1);
204  (**mIntfVoltage)(0, 0) =
205  Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0));
206  (**mIntfVoltage)(1, 0) =
207  Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1));
208  (**mIntfVoltage)(2, 0) =
209  Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2));
210 }
211 
212 void EMT::Ph3::RXLoad::mnaCompUpdateCurrent(const Matrix &leftVector) {
213  **mIntfCurrent = Matrix::Zero(3, 1);
214  for (auto &subc : mSubComponents) {
215  **mIntfCurrent += subc->intfCurrent();
216  }
217 }
Base class for composite power components.
TODO: currently modelled as an impedance, which obviously doesn't have a constant power characteristi...
const Attribute< Matrix >::Ptr mActivePower
Active power [Watt].
RXLoad(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and logging level.
MatrixComp mPower
Power [Watt].
const Attribute< Real >::Ptr mNomVoltage
Nominal voltage [V].
void initializeFromNodesAndTerminals(Real frequency) override
Initializes component from power flow data.
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre and post step operations.
const Attribute< Matrix >::Ptr mReactivePower
Reactive power [VAr].
String type()
Get component type (cross-platform)
const Attribute< MatrixVar< Real > >::Ptr mIntfCurrent
Current through component.
Definition: SimPowerComp.h:47
const Attribute< MatrixVar< Real > >::Ptr mIntfVoltage
Voltage between terminals.
Definition: SimPowerComp.h:45
Logger::Log mSLog
Component logger.