DPsim
Loading...
Searching...
No Matches
EMT_Ph3_RXLoad.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 : CompositePowerComp<Real>(uid, name, true, true, Logger::Level::trace),
15 mActivePower(mAttributes->create<Matrix>("P")),
16 mReactivePower(mAttributes->create<Matrix>("Q")),
17 mNomVoltage(mAttributes->create<Real>("V_nom")),
18 mReactanceInSeries(false) {
21
22 SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name);
23 **mIntfVoltage = Matrix::Zero(3, 1);
24 **mIntfCurrent = Matrix::Zero(3, 1);
25 mSLog->flush();
26}
27
30
31EMT::Ph3::RXLoad::RXLoad(String name, Matrix activePower, Matrix reactivePower,
32 Real volt, Logger::Level logLevel)
33 : RXLoad(name, logLevel) {
34 **mActivePower = activePower;
35 **mReactivePower = reactivePower;
36 mPower = MatrixComp::Zero(3, 3);
37 mPower << Complex((**mActivePower)(0, 0), (**mReactivePower)(0, 0)),
38 Complex((**mActivePower)(0, 1), (**mReactivePower)(0, 1)),
39 Complex((**mActivePower)(0, 2), (**mReactivePower)(0, 2)),
40 Complex((**mActivePower)(1, 0), (**mReactivePower)(1, 0)),
41 Complex((**mActivePower)(1, 1), (**mReactivePower)(1, 1)),
42 Complex((**mActivePower)(1, 2), (**mReactivePower)(1, 2)),
43 Complex((**mActivePower)(2, 0), (**mReactivePower)(2, 0)),
44 Complex((**mActivePower)(2, 1), (**mReactivePower)(2, 1)),
45 Complex((**mActivePower)(2, 2), (**mReactivePower)(2, 2));
46
47 **mNomVoltage = volt;
49}
50
58
59void EMT::Ph3::RXLoad::setParameters(Matrix activePower, Matrix reactivePower,
60 Real volt, bool reactanceInSeries) {
61 **mActivePower = activePower;
62 **mReactivePower = reactivePower;
63 mReactanceInSeries = reactanceInSeries;
64
67 }
68 // complex power
69 mPower = MatrixComp::Zero(3, 3);
70 mPower(0, 0) = {(**mActivePower)(0, 0), (**mReactivePower)(0, 0)};
71 mPower(1, 1) = {(**mActivePower)(1, 1), (**mReactivePower)(1, 1)};
72 mPower(2, 2) = {(**mActivePower)(2, 2), (**mReactivePower)(2, 2)};
73
74 **mNomVoltage = volt;
75
76 SPDLOG_LOGGER_INFO(mSLog,
77 "\nActive Power [W]: {}"
78 "\nReactive Power [VAr]: {}",
81 SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage={} [V]", **mNomVoltage);
82
84}
85
88 return;
89 mSubCompCreated = true;
90
91 // Intentionally empty: which of R/L/C exist depends on the load power sign, known only in
92 // initializeParentFromNodesAndTerminals(), where the sub-components are created. Safe: any
93 // series-mode virtual node is already declared in setParameters().
94}
95
97 Real omega = 2. * PI * frequency;
98
100 **mActivePower = Matrix::Zero(3, 3);
101 (**mActivePower)(0, 0) = mTerminals[0]->singleActivePower() / 3.;
102 (**mActivePower)(1, 1) = mTerminals[0]->singleActivePower() / 3.;
103 (**mActivePower)(2, 2) = mTerminals[0]->singleActivePower() / 3.;
104
105 **mReactivePower = Matrix::Zero(3, 3);
106 (**mReactivePower)(0, 0) = mTerminals[0]->singleReactivePower() / 3.;
107 (**mReactivePower)(1, 1) = mTerminals[0]->singleReactivePower() / 3.;
108 (**mReactivePower)(2, 2) = mTerminals[0]->singleReactivePower() / 3.;
109
110 // complex power
111 mPower = MatrixComp::Zero(3, 3);
112 mPower(0, 0) = {(**mActivePower)(0, 0), (**mReactivePower)(0, 0)};
113 mPower(1, 1) = {(**mActivePower)(1, 1), (**mReactivePower)(1, 1)};
114 mPower(2, 2) = {(**mActivePower)(2, 2), (**mReactivePower)(2, 2)};
115
116 **mNomVoltage = std::abs(mTerminals[0]->initialSingleVoltage());
117
118 SPDLOG_LOGGER_INFO(mSLog,
119 "\nActive Power [W]: {}"
120 "\nReactive Power [VAr]: {}",
123 SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage={} [V]", **mNomVoltage);
124 }
125
126 // Compute derived impedance values and create+parametrize sub-components
127 // now that power and voltage are guaranteed to be known.
128 if ((**mActivePower)(0, 0) != 0) {
130 std::pow(**mNomVoltage / sqrt(3), 2) * (**mActivePower).inverse();
131 }
132 if ((**mReactivePower)(0, 0) != 0)
133 mReactance =
134 std::pow(**mNomVoltage / sqrt(3), 2) * (**mReactivePower).inverse();
135 else
136 mReactance = Matrix::Zero(3, 3);
137
138 if ((**mActivePower)(0, 0) != 0) {
140 std::make_shared<EMT::Ph3::Resistor>(**mName + "_res", mLogLevel);
141 mSubResistor->setParameters(mResistance);
142 if (mReactanceInSeries) {
143 mSubResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]});
144 } else {
145 mSubResistor->connect({SimNode::GND, mTerminals[0]->node()});
146 }
149 }
150
151 if (mReactance(0, 0) > 0) {
152 mInductance = mReactance / omega;
153
155 std::make_shared<EMT::Ph3::Inductor>(**mName + "_ind", mLogLevel);
156 mSubInductor->setParameters(mInductance);
157 if (mReactanceInSeries) {
159 } else {
160 mSubInductor->connect({SimNode::GND, mTerminals[0]->node()});
161 }
164 } else if (mReactance(0, 0) < 0) {
165 mCapacitance = -1. / omega * mReactance.inverse();
166
168 std::make_shared<EMT::Ph3::Capacitor>(**mName + "_cap", mLogLevel);
169 mSubCapacitor->setParameters(mCapacitance);
170 if (mReactanceInSeries) {
172 } else {
173 mSubCapacitor->connect({SimNode::GND, mTerminals[0]->node()});
174 }
178 }
179
180 MatrixComp vInitABC = MatrixComp::Zero(3, 1);
181 vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * mTerminals[0]->initialSingleVoltage();
182 vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B;
183 vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C;
184 **mIntfVoltage = vInitABC.real();
185
186 if ((**mActivePower)(0, 0) != 0) {
188 std::pow(**mNomVoltage / sqrt(3), 2) * (**mActivePower).inverse();
189 }
190
191 if ((**mReactivePower)(0, 0) != 0)
192 mReactance =
193 std::pow(**mNomVoltage / sqrt(3), 2) * (**mReactivePower).inverse();
194 else
195 mReactance = Matrix::Zero(1, 1);
196
197 if (mReactanceInSeries) {
198 MatrixComp impedance = MatrixComp::Zero(3, 3);
199 impedance << Complex(mResistance(0, 0), mReactance(0, 0)),
200 Complex(mResistance(0, 1), mReactance(0, 1)),
201 Complex(mResistance(0, 2), mReactance(0, 2)),
202 Complex(mResistance(1, 0), mReactance(1, 0)),
203 Complex(mResistance(1, 1), mReactance(1, 1)),
204 Complex(mResistance(1, 2), mReactance(1, 2)),
205 Complex(mResistance(2, 0), mReactance(2, 0)),
206 Complex(mResistance(2, 1), mReactance(2, 1)),
207 Complex(mResistance(2, 2), mReactance(2, 2));
208 **mIntfCurrent = (impedance.inverse() * vInitABC).real();
209
210 // Initialization of virtual node
211 // Initial voltage of phase B,C is set after A
212 MatrixComp vInitTerm0 = MatrixComp::Zero(3, 1);
213 vInitTerm0(0, 0) = initialSingleVoltage(0);
214 vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B;
215 vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C;
216 mVirtualNodes[0]->setInitialVoltage(vInitTerm0 +
218 }
219
220 if ((**mActivePower)(0, 0) != 0) {
221 mSubResistor->initializeFromNodesAndTerminals(frequency);
222 if (!mReactanceInSeries) {
223 **mIntfCurrent += mSubResistor->intfCurrent();
224 }
225 }
226
227 if (mReactance(0, 0) > 0) {
228 mSubInductor->initializeFromNodesAndTerminals(frequency);
229 if (!mReactanceInSeries) {
230 **mIntfCurrent += mSubInductor->intfCurrent();
231 }
232 } else if (mReactance(0, 0) < 0) {
233 mSubCapacitor->initializeFromNodesAndTerminals(frequency);
234 if (!mReactanceInSeries) {
235 **mIntfCurrent += mSubCapacitor->intfCurrent();
236 }
237 }
238
239 SPDLOG_LOGGER_INFO(
240 mSLog,
241 "\n--- Initialization from powerflow ---"
242 "\nVoltage across: {:s}"
243 "\nCurrent: {:s}"
244 "\nTerminal 0 voltage: {:s}"
245 "\nActive Power: {:s}"
246 "\nReactive Power: {:s}"
247 "\nResistance: {:s}"
248 "\nReactance: {:s}"
249 "\n--- Initialization from powerflow finished ---",
256 mSLog->flush();
257}
258
260 AttributeBase::List &prevStepDependencies,
261 AttributeBase::List &attributeDependencies,
262 AttributeBase::List &modifiedAttributes) {
263 modifiedAttributes.push_back(mRightVector);
264};
265
267 AttributeBase::List &prevStepDependencies,
268 AttributeBase::List &attributeDependencies,
269 AttributeBase::List &modifiedAttributes,
270 Attribute<Matrix>::Ptr &leftVector) {
271 attributeDependencies.push_back(leftVector);
272 modifiedAttributes.push_back(mIntfCurrent);
273 modifiedAttributes.push_back(mIntfVoltage);
274};
275
279
281 Attribute<Matrix>::Ptr &leftVector) {
282 mnaCompUpdateVoltage(**leftVector);
283 mnaCompUpdateCurrent(**leftVector);
284}
285
287 **mIntfVoltage = Matrix::Zero(3, 1);
288 (**mIntfVoltage)(0, 0) =
290 (**mIntfVoltage)(1, 0) =
292 (**mIntfVoltage)(2, 0) =
294}
295
297 if (mReactanceInSeries) {
298 **mIntfCurrent = mSubInductor->intfCurrent();
299 } else {
300 **mIntfCurrent = Matrix::Zero(3, 1);
301 for (auto &subc : mSubComponents) {
302 **mIntfCurrent += subc->intfCurrent();
303 }
304 }
305}
std::vector< Ptr > List
Definition Attribute.h:123
AttributePointer< Attribute< T > > Ptr
Definition Attribute.h:250
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)
const Attribute< Matrix >::Ptr mActivePower
Active power [Watt].
Bool mReactanceInSeries
If set to true, the reactance is in series with the resistor. Otherwise it is parallel to the resisto...
void setParameters(Matrix activePower, Matrix reactivePower, Real volt, bool reactanceInSeries=false)
RXLoad(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and logging level.
std::shared_ptr< EMT::Ph3::Resistor > mSubResistor
Internal resistance.
std::shared_ptr< EMT::Ph3::Inductor > mSubInductor
Internal inductor.
void createSubComponents() override
Constructs and registers MNA subcomponents; idempotent.
std::shared_ptr< EMT::Ph3::Capacitor > mSubCapacitor
Internal capacitor.
Matrix mResistance
Resistance [Ohm].
void initializeParentFromNodesAndTerminals(Real frequency) override
Derives values from power flow data and pushes them to subcomponents.
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
Matrix mReactance
Reactance [Ohm].
const Attribute< Real >::Ptr mNomVoltage
Nominal voltage [V].
void mnaCompUpdateVoltage(const Matrix &leftVector) override
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
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre and post step operations.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Matrix mCapacitance
Capacitance [F].
const Attribute< Matrix >::Ptr mReactivePower
Reactive power [VAr].
void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
Matrix mInductance
Inductance [H].
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 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 Ptr GND
Definition SimNode.h:35
UInt matrixNodeIndex(UInt nodeIndex)
const Attribute< MatrixVar< Real > >::Ptr mIntfCurrent
SimTerminal< Real >::List mTerminals
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
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< RXLoad > 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: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