DPsim
Loading...
Searching...
No Matches
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
11using namespace CPS;
12
13EMT::Ph3::RXLoad::RXLoad(String uid, String name, Logger::Level logLevel)
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) {
19 mPhaseType = PhaseType::ABC;
20 setTerminalNumber(1);
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
28EMT::Ph3::RXLoad::RXLoad(String name, Logger::Level logLevel)
29 : RXLoad(name, name, logLevel) {}
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;
48 initPowerFromTerminal = false;
49}
50
51void EMT::Ph3::RXLoad::setParameters(Matrix activePower, Matrix reactivePower,
52 Real volt, bool reactanceInSeries) {
53 **mActivePower = activePower;
54 **mReactivePower = reactivePower;
55 mReactanceInSeries = reactanceInSeries;
56
57 if (mReactanceInSeries) {
58 setVirtualNodeNumber(1);
59 }
60 // complex power
61 mPower = MatrixComp::Zero(3, 3);
62 mPower(0, 0) = {(**mActivePower)(0, 0), (**mReactivePower)(0, 0)};
63 mPower(1, 1) = {(**mActivePower)(1, 1), (**mReactivePower)(1, 1)};
64 mPower(2, 2) = {(**mActivePower)(2, 2), (**mReactivePower)(2, 2)};
65
66 **mNomVoltage = volt;
67
68 SPDLOG_LOGGER_INFO(mSLog,
69 "\nActive Power [W]: {}"
70 "\nReactive Power [VAr]: {}",
71 Logger::matrixToString(**mActivePower),
72 Logger::matrixToString(**mReactivePower));
73 SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage={} [V]", **mNomVoltage);
74
75 initPowerFromTerminal = false;
76}
77
79
80 if (initPowerFromTerminal) {
81 **mActivePower = Matrix::Zero(3, 3);
82 (**mActivePower)(0, 0) = mTerminals[0]->singleActivePower() / 3.;
83 (**mActivePower)(1, 1) = mTerminals[0]->singleActivePower() / 3.;
84 (**mActivePower)(2, 2) = mTerminals[0]->singleActivePower() / 3.;
85
86 **mReactivePower = Matrix::Zero(3, 3);
87 (**mReactivePower)(0, 0) = mTerminals[0]->singleReactivePower() / 3.;
88 (**mReactivePower)(1, 1) = mTerminals[0]->singleReactivePower() / 3.;
89 (**mReactivePower)(2, 2) = mTerminals[0]->singleReactivePower() / 3.;
90
91 // complex power
92 mPower = MatrixComp::Zero(3, 3);
93 mPower(0, 0) = {(**mActivePower)(0, 0), (**mReactivePower)(0, 0)};
94 mPower(1, 1) = {(**mActivePower)(1, 1), (**mReactivePower)(1, 1)};
95 mPower(2, 2) = {(**mActivePower)(2, 2), (**mReactivePower)(2, 2)};
96
97 **mNomVoltage = std::abs(mTerminals[0]->initialSingleVoltage());
98
99 SPDLOG_LOGGER_INFO(mSLog,
100 "\nActive Power [W]: {}"
101 "\nReactive Power [VAr]: {}",
102 Logger::matrixToString(**mActivePower),
103 Logger::matrixToString(**mReactivePower));
104 SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage={} [V]", **mNomVoltage);
105 }
106
107 MatrixComp vInitABC = MatrixComp::Zero(3, 1);
108 vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * mTerminals[0]->initialSingleVoltage();
109 vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B;
110 vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C;
111 **mIntfVoltage = vInitABC.real();
112
113 if ((**mActivePower)(0, 0) != 0) {
115 std::pow(**mNomVoltage / sqrt(3), 2) * (**mActivePower).inverse();
116 }
117
118 if ((**mReactivePower)(0, 0) != 0)
119 mReactance =
120 std::pow(**mNomVoltage / sqrt(3), 2) * (**mReactivePower).inverse();
121 else
122 mReactance = Matrix::Zero(1, 1);
123
124 if (mReactanceInSeries) {
125 MatrixComp impedance = MatrixComp::Zero(3, 3);
126 impedance << Complex(mResistance(0, 0), mReactance(0, 0)),
127 Complex(mResistance(0, 1), mReactance(0, 1)),
128 Complex(mResistance(0, 2), mReactance(0, 2)),
129 Complex(mResistance(1, 0), mReactance(1, 0)),
130 Complex(mResistance(1, 1), mReactance(1, 1)),
131 Complex(mResistance(1, 2), mReactance(1, 2)),
132 Complex(mResistance(2, 0), mReactance(2, 0)),
133 Complex(mResistance(2, 1), mReactance(2, 1)),
134 Complex(mResistance(2, 2), mReactance(2, 2));
135 **mIntfCurrent = (impedance.inverse() * vInitABC).real();
136
137 // Initialization of virtual node
138 // Initial voltage of phase B,C is set after A
139 MatrixComp vInitTerm0 = MatrixComp::Zero(3, 1);
140 vInitTerm0(0, 0) = initialSingleVoltage(0);
141 vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B;
142 vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C;
143 mVirtualNodes[0]->setInitialVoltage(vInitTerm0 +
145 }
146
147 if ((**mActivePower)(0, 0) != 0) {
149 std::make_shared<EMT::Ph3::Resistor>(**mName + "_res", mLogLevel);
150 mSubResistor->setParameters(mResistance);
151 if (mReactanceInSeries) {
152 mSubResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]});
153 } else {
154 mSubResistor->connect({SimNode::GND, mTerminals[0]->node()});
155 }
156 mSubResistor->initialize(mFrequencies);
157 mSubResistor->initializeFromNodesAndTerminals(frequency);
158 addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
159 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
160
161 if (!mReactanceInSeries) {
162 **mIntfCurrent += mSubResistor->intfCurrent();
163 }
164 }
165
166 if (mReactance(0, 0) > 0) {
167 mInductance = mReactance / (2 * PI * frequency);
168
170 std::make_shared<EMT::Ph3::Inductor>(**mName + "_ind", mLogLevel);
171 mSubInductor->setParameters(mInductance);
172 if (mReactanceInSeries) {
173 mSubInductor->connect({SimNode::GND, mVirtualNodes[0]});
174 } else {
175 mSubInductor->connect({SimNode::GND, mTerminals[0]->node()});
176 }
177 mSubInductor->initialize(mFrequencies);
178 mSubInductor->initializeFromNodesAndTerminals(frequency);
179 addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
180 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
181
182 if (!mReactanceInSeries) {
183 **mIntfCurrent += mSubInductor->intfCurrent();
184 }
185 } else if (mReactance(0, 0) < 0) {
186 mCapacitance = -1 / (2 * PI * frequency) * mReactance.inverse();
187
189 std::make_shared<EMT::Ph3::Capacitor>(**mName + "_cap", mLogLevel);
190 mSubCapacitor->setParameters(mCapacitance);
191 if (mReactanceInSeries) {
192 mSubCapacitor->connect({SimNode::GND, mVirtualNodes[0]});
193 } else {
194 mSubCapacitor->connect({SimNode::GND, mTerminals[0]->node()});
195 }
196 mSubCapacitor->initialize(mFrequencies);
197 mSubCapacitor->initializeFromNodesAndTerminals(frequency);
199 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
200 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
201 if (!mReactanceInSeries) {
202 **mIntfCurrent += mSubCapacitor->intfCurrent();
203 }
204 }
205
206 SPDLOG_LOGGER_INFO(
207 mSLog,
208 "\n--- Initialization from powerflow ---"
209 "\nVoltage across: {:s}"
210 "\nCurrent: {:s}"
211 "\nTerminal 0 voltage: {:s}"
212 "\nActive Power: {:s}"
213 "\nReactive Power: {:s}"
214 "\nResistance: {:s}"
215 "\nReactance: {:s}"
216 "\n--- Initialization from powerflow finished ---",
217 Logger::matrixToString(**mIntfVoltage),
218 Logger::matrixToString(**mIntfCurrent),
219 Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)),
220 Logger::matrixToString(**mActivePower),
221 Logger::matrixToString(**mReactivePower),
222 Logger::matrixToString(mResistance), Logger::matrixToString(mReactance));
223 mSLog->flush();
224}
225
226void EMT::Ph3::RXLoad::mnaParentAddPreStepDependencies(
227 AttributeBase::List &prevStepDependencies,
228 AttributeBase::List &attributeDependencies,
229 AttributeBase::List &modifiedAttributes) {
230 modifiedAttributes.push_back(mRightVector);
231};
232
233void EMT::Ph3::RXLoad::mnaParentAddPostStepDependencies(
234 AttributeBase::List &prevStepDependencies,
235 AttributeBase::List &attributeDependencies,
236 AttributeBase::List &modifiedAttributes,
237 Attribute<Matrix>::Ptr &leftVector) {
238 attributeDependencies.push_back(leftVector);
239 modifiedAttributes.push_back(mIntfCurrent);
240 modifiedAttributes.push_back(mIntfVoltage);
241};
242
246
247void EMT::Ph3::RXLoad::mnaParentPostStep(Real time, Int timeStepCount,
248 Attribute<Matrix>::Ptr &leftVector) {
249 mnaCompUpdateVoltage(**leftVector);
250 mnaCompUpdateCurrent(**leftVector);
251}
252
253void EMT::Ph3::RXLoad::mnaCompUpdateVoltage(const Matrix &leftVector) {
254 **mIntfVoltage = Matrix::Zero(3, 1);
255 (**mIntfVoltage)(0, 0) =
256 Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0));
257 (**mIntfVoltage)(1, 0) =
258 Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1));
259 (**mIntfVoltage)(2, 0) =
260 Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2));
261}
262
263void EMT::Ph3::RXLoad::mnaCompUpdateCurrent(const Matrix &leftVector) {
264 if (mReactanceInSeries) {
265 **mIntfCurrent = mSubInductor->intfCurrent();
266 } else {
267 **mIntfCurrent = Matrix::Zero(3, 1);
268 for (auto &subc : mSubComponents) {
269 **mIntfCurrent += subc->intfCurrent();
270 }
271 }
272}
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...
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.
MatrixComp mPower
Power [Watt].
std::shared_ptr< EMT::Ph3::Inductor > mSubInductor
Internal inductor.
std::shared_ptr< EMT::Ph3::Capacitor > mSubCapacitor
Internal capacitor.
Matrix mResistance
Resistance [Ohm].
Matrix mReactance
Reactance [Ohm].
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.
Matrix mCapacitance
Capacitance [F].
const Attribute< Matrix >::Ptr mReactivePower
Reactive power [VAr].
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.
Attribute< Matrix >::Ptr mRightVector
const Attribute< MatrixVar< Real > >::Ptr mIntfCurrent
SimTerminal< Real >::List mTerminals
const Attribute< MatrixVar< Real > >::Ptr mIntfVoltage
SimNode< Real >::List mVirtualNodes
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.